mirror of https://gitee.com/openkylin/linux.git
Merge tag 'staging-4.15-rc1' into v4l_for_linus
There are some conflicts between staging and media trees, as reported by Stephen Rothwell <sfr@canb.auug.org.au>. So, merge from staging. * tag 'staging-4.15-rc1': (775 commits) staging: lustre: add SPDX identifiers to all lustre files staging: greybus: Remove redundant license text staging: greybus: add SPDX identifiers to all greybus driver files staging: ccree: simplify ioread/iowrite staging: ccree: simplify registers access staging: ccree: simplify error handling logic staging: ccree: remove dead code staging: ccree: handle limiting of DMA masks staging: ccree: copy IV to DMAable memory staging: fbtft: remove redundant initialization of buf staging: sm750fb: Fix parameter mistake in poke32 staging: wilc1000: Fix bssid buffer offset in Txq staging: fbtft: fb_ssd1331: fix mirrored display staging: android: Fix checkpatch.pl error staging: greybus: loopback: convert loopback to use generic async operations staging: greybus: operation: add private data with get/set accessors staging: greybus: loopback: Fix iteration count on async path staging: greybus: loopback: Hold per-connection mutex across operations staging: greybus/loopback: use ktime_get() for time intervals staging: fsl-dpaa2/eth: Extra headroom in RX buffers ... Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
commit
f2ecc3d078
|
@ -522,6 +522,7 @@ Description:
|
|||
Specifies the output powerdown mode.
|
||||
DAC output stage is disconnected from the amplifier and
|
||||
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
|
||||
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
||||
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
|
||||
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
|
||||
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
|
||||
|
@ -1242,9 +1243,9 @@ What: /sys/.../iio:deviceX/in_distance_raw
|
|||
KernelVersion: 4.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute is used to read the distance covered by the user
|
||||
since the last reboot while activated. Units after application
|
||||
of scale are meters.
|
||||
This attribute is used to read the measured distance to an object
|
||||
or the distance covered by the user since the last reboot while
|
||||
activated. Units after application of scale are meters.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/store_eeprom
|
||||
KernelVersion: 3.4.0
|
||||
|
|
|
@ -16,3 +16,13 @@ Description:
|
|||
the motion sensor is placed. For example, in a laptop a motion
|
||||
sensor can be located on the base or on the lid. Current valid
|
||||
values are 'base' and 'lid'.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/id
|
||||
Date: Septembre 2017
|
||||
KernelVersion: 4.14
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute is exposed by the CrOS EC legacy accelerometer
|
||||
driver and represents the sensor ID as exposed by the EC. This
|
||||
ID is used by the Android sensor service hardware abstraction
|
||||
layer (sensor HAL) through the Android container on ChromeOS.
|
||||
|
|
|
@ -14,3 +14,11 @@ Description:
|
|||
Show or set the gain boost of the amp, from 0-31 range.
|
||||
18 = indoors (default)
|
||||
14 = outdoors
|
||||
|
||||
What /sys/bus/iio/devices/iio:deviceX/noise_level_tripped
|
||||
Date: May 2017
|
||||
KernelVersion: 4.13
|
||||
Contact: Matt Ranostay <matt.ranostay@konsulko.com>
|
||||
Description:
|
||||
When 1 the noise level is over the trip level and not reporting
|
||||
valid data
|
||||
|
|
|
@ -352,44 +352,30 @@ Read-Copy Update (RCU)
|
|||
----------------------
|
||||
|
||||
.. kernel-doc:: include/linux/rcupdate.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: include/linux/rcupdate_wait.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: include/linux/rcutree.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: kernel/rcu/tree.c
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: kernel/rcu/tree_plugin.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: kernel/rcu/tree_exp.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: kernel/rcu/update.c
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: include/linux/srcu.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: kernel/rcu/srcutree.c
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: include/linux/rculist_bl.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: include/linux/rculist.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: include/linux/rculist_nulls.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: include/linux/rcu_sync.h
|
||||
:external:
|
||||
|
||||
.. kernel-doc:: kernel/rcu/sync.c
|
||||
:external:
|
||||
|
||||
|
|
|
@ -29,15 +29,29 @@ Required properties:
|
|||
"microchip,mcp3204"
|
||||
"microchip,mcp3208"
|
||||
"microchip,mcp3301"
|
||||
"microchip,mcp3550-50"
|
||||
"microchip,mcp3550-60"
|
||||
"microchip,mcp3551"
|
||||
"microchip,mcp3553"
|
||||
|
||||
NOTE: The use of the compatibles with no vendor prefix
|
||||
is deprecated and only listed because old DT use them.
|
||||
|
||||
- spi-cpha, spi-cpol (boolean):
|
||||
Either SPI mode (0,0) or (1,1) must be used, so specify
|
||||
none or both of spi-cpha, spi-cpol. The MCP3550/1/3
|
||||
is more efficient in mode (1,1) as only 3 instead of
|
||||
4 bytes need to be read from the ADC, but not all SPI
|
||||
masters support it.
|
||||
|
||||
- vref-supply: Phandle to the external reference voltage supply.
|
||||
|
||||
Examples:
|
||||
spi_controller {
|
||||
mcp3x0x@0 {
|
||||
compatible = "mcp3002";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
vref-supply = <&vref_reg>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@ for the Thermal Controller which holds a phandle to the AUXADC.
|
|||
Required properties:
|
||||
- compatible: Should be one of:
|
||||
- "mediatek,mt2701-auxadc": For MT2701 family of SoCs
|
||||
- "mediatek,mt2712-auxadc": For MT2712 family of SoCs
|
||||
- "mediatek,mt7622-auxadc": For MT7622 family of SoCs
|
||||
- "mediatek,mt8173-auxadc": For MT8173 family of SoCs
|
||||
- reg: Address range of the AUXADC unit.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
Maxim Integrated DS4422/DS4424 7-bit Sink/Source Current DAC Device Driver
|
||||
|
||||
Datasheet publicly available at:
|
||||
https://datasheets.maximintegrated.com/en/ds/DS4422-DS4424.pdf
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be one of
|
||||
maxim,ds4422
|
||||
maxim,ds4424
|
||||
- reg: Should contain the DAC I2C address
|
||||
|
||||
Optional properties:
|
||||
- vcc-supply: Power supply is optional. If not defined, driver will ignore it.
|
||||
|
||||
Example:
|
||||
ds4224@10 {
|
||||
compatible = "maxim,ds4424";
|
||||
reg = <0x10>; /* When A0, A1 pins are ground */
|
||||
vcc-supply = <&vcc_3v3>;
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
Texas Instruments 8/10/12-bit 2/4-channel DAC driver
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be one of:
|
||||
"ti,dac082s085"
|
||||
"ti,dac102s085"
|
||||
"ti,dac122s085"
|
||||
"ti,dac084s085"
|
||||
"ti,dac104s085"
|
||||
"ti,dac124s085"
|
||||
- reg: Chip select number.
|
||||
- spi-cpha, spi-cpol: SPI mode (0,1) or (1,0) must be used, so specify
|
||||
either spi-cpha or spi-cpol (but not both).
|
||||
- vref-supply: Phandle to the external reference voltage supply.
|
||||
|
||||
For other required and optional properties of SPI slave nodes please refer to
|
||||
../../spi/spi-bus.txt.
|
||||
|
||||
Example:
|
||||
vref_2v5_reg: regulator-vref {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "2v5";
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
dac@0 {
|
||||
compatible = "ti,dac082s085";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <40000000>;
|
||||
spi-cpol;
|
||||
vref-supply = <&vref_2v5_reg>;
|
||||
};
|
|
@ -20,9 +20,9 @@ Optional properties:
|
|||
|
||||
Example:
|
||||
|
||||
max30100@057 {
|
||||
max30100@57 {
|
||||
compatible = "maxim,max30100";
|
||||
reg = <57>;
|
||||
reg = <0x57>;
|
||||
maxim,led-current-microamp = <24000 50000>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <16 2>;
|
||||
|
|
|
@ -20,7 +20,7 @@ Optional properties:
|
|||
|
||||
Example:
|
||||
|
||||
max30100@57 {
|
||||
max30102@57 {
|
||||
compatible = "maxim,max30102";
|
||||
reg = <0x57>;
|
||||
maxim,red-led-current-microamp = <7000>;
|
||||
|
|
|
@ -16,6 +16,10 @@ Optional properties:
|
|||
- ams,tuning-capacitor-pf: Calibration tuning capacitor stepping
|
||||
value 0 - 120pF. This will require using the calibration data from
|
||||
the manufacturer.
|
||||
- ams,nflwdth: Set the noise and watchdog threshold register on
|
||||
startup. This will need to set according to the noise from the
|
||||
MCU board, and possibly the local environment. Refer to the
|
||||
datasheet for the threshold settings.
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -27,4 +31,5 @@ as3935@0 {
|
|||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <16 1>;
|
||||
ams,tuning-capacitor-pf = <80>;
|
||||
ams,nflwdth = <0x44>;
|
||||
};
|
||||
|
|
|
@ -46,6 +46,8 @@ Accelerometers:
|
|||
- st,h3lis331dl-accel
|
||||
- st,lng2dm-accel
|
||||
- st,lis3l02dq
|
||||
- st,lis2dw12
|
||||
- st,lis3dhh
|
||||
|
||||
Gyroscopes:
|
||||
- st,l3g4200d-gyro
|
||||
|
@ -71,3 +73,5 @@ Pressure sensors:
|
|||
- st,lps25h-press
|
||||
- st,lps331ap-press
|
||||
- st,lps22hb-press
|
||||
- st,lps33hw
|
||||
- st,lps35hw
|
||||
|
|
|
@ -99,7 +99,7 @@ Examples:
|
|||
compatible = "arm,gic-v3-its";
|
||||
msi-controller;
|
||||
#msi-cells = <1>;
|
||||
reg = <0x0 0x2c200000 0 0x200000>;
|
||||
reg = <0x0 0x2c200000 0 0x20000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -124,14 +124,14 @@ Examples:
|
|||
compatible = "arm,gic-v3-its";
|
||||
msi-controller;
|
||||
#msi-cells = <1>;
|
||||
reg = <0x0 0x2c200000 0 0x200000>;
|
||||
reg = <0x0 0x2c200000 0 0x20000>;
|
||||
};
|
||||
|
||||
gic-its@2c400000 {
|
||||
compatible = "arm,gic-v3-its";
|
||||
msi-controller;
|
||||
#msi-cells = <1>;
|
||||
reg = <0x0 0x2c400000 0 0x200000>;
|
||||
reg = <0x0 0x2c400000 0 0x20000>;
|
||||
};
|
||||
|
||||
ppi-partitions {
|
||||
|
|
|
@ -25,6 +25,7 @@ Below are the essential guides that every developer should read.
|
|||
submitting-patches
|
||||
coding-style
|
||||
email-clients
|
||||
kernel-enforcement-statement
|
||||
|
||||
Other guides to the community that are of interest to most developers are:
|
||||
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
Linux Kernel Enforcement Statement
|
||||
----------------------------------
|
||||
|
||||
As developers of the Linux kernel, we have a keen interest in how our software
|
||||
is used and how the license for our software is enforced. Compliance with the
|
||||
reciprocal sharing obligations of GPL-2.0 is critical to the long-term
|
||||
sustainability of our software and community.
|
||||
|
||||
Although there is a right to enforce the separate copyright interests in the
|
||||
contributions made to our community, we share an interest in ensuring that
|
||||
individual enforcement actions are conducted in a manner that benefits our
|
||||
community and do not have an unintended negative impact on the health and
|
||||
growth of our software ecosystem. In order to deter unhelpful enforcement
|
||||
actions, we agree that it is in the best interests of our development
|
||||
community to undertake the following commitment to users of the Linux kernel
|
||||
on behalf of ourselves and any successors to our copyright interests:
|
||||
|
||||
Notwithstanding the termination provisions of the GPL-2.0, we agree that
|
||||
it is in the best interests of our development community to adopt the
|
||||
following provisions of GPL-3.0 as additional permissions under our
|
||||
license with respect to any non-defensive assertion of rights under the
|
||||
license.
|
||||
|
||||
However, if you cease all violation of this License, then your license
|
||||
from a particular copyright holder is reinstated (a) provisionally,
|
||||
unless and until the copyright holder explicitly and finally
|
||||
terminates your license, and (b) permanently, if the copyright holder
|
||||
fails to notify you of the violation by some reasonable means prior to
|
||||
60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Our intent in providing these assurances is to encourage more use of the
|
||||
software. We want companies and individuals to use, modify and distribute
|
||||
this software. We want to work with users in an open and transparent way to
|
||||
eliminate any uncertainty about our expectations regarding compliance or
|
||||
enforcement that might limit adoption of our software. We view legal action
|
||||
as a last resort, to be initiated only when other community efforts have
|
||||
failed to resolve the problem.
|
||||
|
||||
Finally, once a non-compliance issue is resolved, we hope the user will feel
|
||||
welcome to join us in our efforts on this project. Working together, we will
|
||||
be stronger.
|
||||
|
||||
Except where noted below, we speak only for ourselves, and not for any company
|
||||
we might work for today, have in the past, or will in the future.
|
||||
|
||||
- Bjorn Andersson (Linaro)
|
||||
- Andrea Arcangeli (Red Hat)
|
||||
- Neil Armstrong
|
||||
- Jens Axboe
|
||||
- Pablo Neira Ayuso
|
||||
- Khalid Aziz
|
||||
- Ralf Baechle
|
||||
- Felipe Balbi
|
||||
- Arnd Bergmann
|
||||
- Ard Biesheuvel
|
||||
- Paolo Bonzini (Red Hat)
|
||||
- Christian Borntraeger
|
||||
- Mark Brown (Linaro)
|
||||
- Paul Burton
|
||||
- Javier Martinez Canillas
|
||||
- Rob Clark
|
||||
- Jonathan Corbet
|
||||
- Vivien Didelot (Savoir-faire Linux)
|
||||
- Hans de Goede (Red Hat)
|
||||
- Mel Gorman (SUSE)
|
||||
- Sven Eckelmann
|
||||
- Alex Elder (Linaro)
|
||||
- Fabio Estevam
|
||||
- Larry Finger
|
||||
- Bhumika Goyal
|
||||
- Andy Gross
|
||||
- Juergen Gross
|
||||
- Shawn Guo
|
||||
- Ulf Hansson
|
||||
- Tejun Heo
|
||||
- Rob Herring
|
||||
- Masami Hiramatsu
|
||||
- Michal Hocko
|
||||
- Simon Horman
|
||||
- Johan Hovold (Hovold Consulting AB)
|
||||
- Christophe JAILLET
|
||||
- Olof Johansson
|
||||
- Lee Jones (Linaro)
|
||||
- Heiner Kallweit
|
||||
- Srinivas Kandagatla
|
||||
- Jan Kara
|
||||
- Shuah Khan (Samsung)
|
||||
- David Kershner
|
||||
- Jaegeuk Kim
|
||||
- Namhyung Kim
|
||||
- Colin Ian King
|
||||
- Jeff Kirsher
|
||||
- Greg Kroah-Hartman (Linux Foundation)
|
||||
- Christian König
|
||||
- Vinod Koul
|
||||
- Krzysztof Kozlowski
|
||||
- Viresh Kumar
|
||||
- Aneesh Kumar K.V
|
||||
- Julia Lawall
|
||||
- Doug Ledford (Red Hat)
|
||||
- Chuck Lever (Oracle)
|
||||
- Daniel Lezcano
|
||||
- Shaohua Li
|
||||
- Xin Long (Red Hat)
|
||||
- Tony Luck
|
||||
- Mike Marshall
|
||||
- Chris Mason
|
||||
- Paul E. McKenney
|
||||
- David S. Miller
|
||||
- Ingo Molnar
|
||||
- Kuninori Morimoto
|
||||
- Borislav Petkov
|
||||
- Jiri Pirko
|
||||
- Josh Poimboeuf
|
||||
- Sebastian Reichel (Collabora)
|
||||
- Guenter Roeck
|
||||
- Joerg Roedel
|
||||
- Leon Romanovsky
|
||||
- Steven Rostedt (VMware)
|
||||
- Ivan Safonov
|
||||
- Ivan Safonov
|
||||
- Anna Schumaker
|
||||
- Jes Sorensen
|
||||
- K.Y. Srinivasan
|
||||
- Heiko Stuebner
|
||||
- Jiri Kosina (SUSE)
|
||||
- Dmitry Torokhov
|
||||
- Linus Torvalds
|
||||
- Thierry Reding
|
||||
- Rik van Riel
|
||||
- Geert Uytterhoeven (Glider bvba)
|
||||
- Daniel Vetter
|
||||
- Linus Walleij
|
||||
- Richard Weinberger
|
||||
- Dan Williams
|
||||
- Rafael J. Wysocki
|
||||
- Arvind Yadav
|
||||
- Masahiro Yamada
|
||||
- Wei Yongjun
|
||||
- Lv Zheng
|
|
@ -9230,7 +9230,6 @@ F: include/linux/isicom.h
|
|||
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
|
||||
M: Bin Liu <b-liu@ti.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
||||
S: Maintained
|
||||
F: drivers/usb/musb/
|
||||
|
||||
|
@ -10577,6 +10576,8 @@ M: Peter Zijlstra <peterz@infradead.org>
|
|||
M: Ingo Molnar <mingo@redhat.com>
|
||||
M: Arnaldo Carvalho de Melo <acme@kernel.org>
|
||||
R: Alexander Shishkin <alexander.shishkin@linux.intel.com>
|
||||
R: Jiri Olsa <jolsa@redhat.com>
|
||||
R: Namhyung Kim <namhyung@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
|
||||
S: Supported
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 14
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Fearless Coyote
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -131,7 +131,7 @@ endif
|
|||
KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
|
||||
KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
|
||||
|
||||
CHECKFLAGS += -D__arm__
|
||||
CHECKFLAGS += -D__arm__ -m32
|
||||
|
||||
#Default value
|
||||
head-y := arch/arm/kernel/head$(MMUEXT).o
|
||||
|
|
|
@ -23,7 +23,11 @@ ENTRY(putc)
|
|||
strb r0, [r1]
|
||||
mov r0, #0x03 @ SYS_WRITEC
|
||||
ARM( svc #0x123456 )
|
||||
#ifdef CONFIG_CPU_V7M
|
||||
THUMB( bkpt #0xab )
|
||||
#else
|
||||
THUMB( svc #0xab )
|
||||
#endif
|
||||
mov pc, lr
|
||||
.align 2
|
||||
1: .word _GLOBAL_OFFSET_TABLE_ - .
|
||||
|
|
|
@ -178,7 +178,7 @@ gic: interrupt-controller@d000 {
|
|||
};
|
||||
|
||||
i2c0: i2c@11000 {
|
||||
compatible = "marvell,mv64xxx-i2c";
|
||||
compatible = "marvell,mv78230-a0-i2c", "marvell,mv64xxx-i2c";
|
||||
reg = <0x11000 0x20>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -189,7 +189,7 @@ i2c0: i2c@11000 {
|
|||
};
|
||||
|
||||
i2c1: i2c@11100 {
|
||||
compatible = "marvell,mv64xxx-i2c";
|
||||
compatible = "marvell,mv78230-a0-i2c", "marvell,mv64xxx-i2c";
|
||||
reg = <0x11100 0x20>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
@ -67,8 +67,8 @@ macb0: ethernet@f8008000 {
|
|||
pinctrl-0 = <&pinctrl_macb0_default>;
|
||||
phy-mode = "rmii";
|
||||
|
||||
ethernet-phy@1 {
|
||||
reg = <0x1>;
|
||||
ethernet-phy@0 {
|
||||
reg = <0x0>;
|
||||
interrupt-parent = <&pioA>;
|
||||
interrupts = <PIN_PD31 IRQ_TYPE_LEVEL_LOW>;
|
||||
pinctrl-names = "default";
|
||||
|
|
|
@ -309,7 +309,7 @@ adc: adc@fc030000 {
|
|||
vddana-supply = <&vdd_3v3_lp_reg>;
|
||||
vref-supply = <&vdd_3v3_lp_reg>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_adc_default>;
|
||||
pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -340,6 +340,20 @@ pinctrl_can1_default: can1_default {
|
|||
bias-disable;
|
||||
};
|
||||
|
||||
/*
|
||||
* The ADTRG pin can work on any edge type.
|
||||
* In here it's being pulled up, so need to
|
||||
* connect it to ground to get an edge e.g.
|
||||
* Trigger can be configured on falling, rise
|
||||
* or any edge, and the pull-up can be changed
|
||||
* to pull-down or left floating according to
|
||||
* needs.
|
||||
*/
|
||||
pinctrl_adtrg_default: adtrg_default {
|
||||
pinmux = <PIN_PD31__ADTRG>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
pinctrl_charger_chglev: charger_chglev {
|
||||
pinmux = <PIN_PA12__GPIO>;
|
||||
bias-disable;
|
||||
|
|
|
@ -18,12 +18,9 @@ / {
|
|||
compatible = "raspberrypi,model-zero-w", "brcm,bcm2835";
|
||||
model = "Raspberry Pi Zero W";
|
||||
|
||||
/* Needed by firmware to properly init UARTs */
|
||||
aliases {
|
||||
uart0 = "/soc/serial@7e201000";
|
||||
uart1 = "/soc/serial@7e215040";
|
||||
serial0 = "/soc/serial@7e201000";
|
||||
serial1 = "/soc/serial@7e215040";
|
||||
chosen {
|
||||
/* 8250 auxiliary UART instead of pl011 */
|
||||
stdout-path = "serial1:115200n8";
|
||||
};
|
||||
|
||||
leds {
|
||||
|
|
|
@ -8,6 +8,11 @@ / {
|
|||
compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
|
||||
model = "Raspberry Pi 3 Model B";
|
||||
|
||||
chosen {
|
||||
/* 8250 auxiliary UART instead of pl011 */
|
||||
stdout-path = "serial1:115200n8";
|
||||
};
|
||||
|
||||
memory {
|
||||
reg = <0 0x40000000>;
|
||||
};
|
||||
|
|
|
@ -20,8 +20,13 @@ / {
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
serial1 = &uart1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "earlyprintk console=ttyAMA0";
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
thermal-zones {
|
||||
|
|
|
@ -145,11 +145,12 @@ mux1 {
|
|||
};
|
||||
|
||||
watchdog@41000000 {
|
||||
compatible = "cortina,gemini-watchdog";
|
||||
compatible = "cortina,gemini-watchdog", "faraday,ftwdt010";
|
||||
reg = <0x41000000 0x1000>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
resets = <&syscon GEMINI_RESET_WDOG>;
|
||||
clocks = <&syscon GEMINI_CLK_APB>;
|
||||
clock-names = "PCLK";
|
||||
};
|
||||
|
||||
uart0: serial@42000000 {
|
||||
|
|
|
@ -144,10 +144,10 @@ pcie: pcie@0x33800000 {
|
|||
interrupt-names = "msi";
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 0x7>;
|
||||
interrupt-map = <0 0 0 1 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0 0 0 2 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0 0 0 3 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0 0 0 4 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map = <0 0 0 1 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0 0 0 2 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0 0 0 3 &intc GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<0 0 0 4 &intc GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clks IMX7D_PCIE_CTRL_ROOT_CLK>,
|
||||
<&clks IMX7D_PLL_ENET_MAIN_100M_CLK>,
|
||||
<&clks IMX7D_PCIE_PHY_ROOT_CLK>;
|
||||
|
|
|
@ -87,9 +87,10 @@ dma: dma@90500000 {
|
|||
};
|
||||
|
||||
watchdog: watchdog@98500000 {
|
||||
compatible = "moxa,moxart-watchdog";
|
||||
compatible = "moxa,moxart-watchdog", "faraday,ftwdt010";
|
||||
reg = <0x98500000 0x10>;
|
||||
clocks = <&clk_apb>;
|
||||
clock-names = "PCLK";
|
||||
};
|
||||
|
||||
sdhci: sdhci@98e00000 {
|
||||
|
|
|
@ -1430,6 +1430,7 @@ adc: adc@fc030000 {
|
|||
atmel,min-sample-rate-hz = <200000>;
|
||||
atmel,max-sample-rate-hz = <20000000>;
|
||||
atmel,startup-time-ms = <4>;
|
||||
atmel,trigger-edge-type = <IRQ_TYPE_EDGE_RISING>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
|
|
@ -311,8 +311,8 @@ tcon1_in: port@0 {
|
|||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
tcon1_in_drc1: endpoint@0 {
|
||||
reg = <0>;
|
||||
tcon1_in_drc1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&drc1_out_tcon1>;
|
||||
};
|
||||
};
|
||||
|
@ -1012,8 +1012,8 @@ be1_out: port@1 {
|
|||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
|
||||
be1_out_drc1: endpoint@0 {
|
||||
reg = <0>;
|
||||
be1_out_drc1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&drc1_in_be1>;
|
||||
};
|
||||
};
|
||||
|
@ -1042,8 +1042,8 @@ drc1_in: port@0 {
|
|||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
drc1_in_be1: endpoint@0 {
|
||||
reg = <0>;
|
||||
drc1_in_be1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&be1_out_drc1>;
|
||||
};
|
||||
};
|
||||
|
@ -1053,8 +1053,8 @@ drc1_out: port@1 {
|
|||
#size-cells = <0>;
|
||||
reg = <1>;
|
||||
|
||||
drc1_out_tcon1: endpoint@0 {
|
||||
reg = <0>;
|
||||
drc1_out_tcon1: endpoint@1 {
|
||||
reg = <1>;
|
||||
remote-endpoint = <&tcon1_in_drc1>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -219,7 +219,8 @@ CONFIG_AD525X_DPOT_I2C=m
|
|||
CONFIG_ICS932S401=m
|
||||
CONFIG_APDS9802ALS=m
|
||||
CONFIG_ISL29003=m
|
||||
CONFIG_TI_DAC7512=m
|
||||
CONFIG_IIO=m
|
||||
CONFIG_AD5446=m
|
||||
CONFIG_EEPROM_AT24=m
|
||||
CONFIG_SENSORS_LIS3_SPI=m
|
||||
CONFIG_IDE=m
|
||||
|
|
|
@ -37,7 +37,8 @@ CONFIG_MTD_NAND_PXA3xx=y
|
|||
CONFIG_MTD_UBI=y
|
||||
CONFIG_BLK_DEV_LOOP=y
|
||||
CONFIG_ISL29003=y
|
||||
CONFIG_TI_DAC7512=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_AD5446=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_CHR_DEV_SG=y
|
||||
|
|
|
@ -115,7 +115,11 @@ ENTRY(printascii)
|
|||
mov r1, r0
|
||||
mov r0, #0x04 @ SYS_WRITE0
|
||||
ARM( svc #0x123456 )
|
||||
#ifdef CONFIG_CPU_V7M
|
||||
THUMB( bkpt #0xab )
|
||||
#else
|
||||
THUMB( svc #0xab )
|
||||
#endif
|
||||
ret lr
|
||||
ENDPROC(printascii)
|
||||
|
||||
|
@ -124,7 +128,11 @@ ENTRY(printch)
|
|||
strb r0, [r1]
|
||||
mov r0, #0x03 @ SYS_WRITEC
|
||||
ARM( svc #0x123456 )
|
||||
#ifdef CONFIG_CPU_V7M
|
||||
THUMB( bkpt #0xab )
|
||||
#else
|
||||
THUMB( svc #0xab )
|
||||
#endif
|
||||
ret lr
|
||||
ENDPROC(printch)
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <asm/mach/arch.h>
|
||||
|
||||
#include "db8500-regs.h"
|
||||
#include "pm_domains.h"
|
||||
|
||||
static int __init ux500_l2x0_unlock(void)
|
||||
{
|
||||
|
@ -157,6 +158,9 @@ static const struct of_device_id u8500_local_bus_nodes[] = {
|
|||
|
||||
static void __init u8500_init_machine(void)
|
||||
{
|
||||
/* Initialize ux500 power domains */
|
||||
ux500_pm_domains_init();
|
||||
|
||||
/* automatically probe child nodes of dbx5x0 devices */
|
||||
if (of_machine_is_compatible("st-ericsson,u8540"))
|
||||
of_platform_populate(NULL, u8500_local_bus_nodes,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/of_address.h>
|
||||
|
||||
#include "db8500-regs.h"
|
||||
#include "pm_domains.h"
|
||||
|
||||
/* ARM WFI Standby signal register */
|
||||
#define PRCM_ARM_WFI_STANDBY (prcmu_base + 0x130)
|
||||
|
@ -203,7 +202,4 @@ void __init ux500_pm_init(u32 phy_base, u32 size)
|
|||
|
||||
/* Set up ux500 suspend callbacks. */
|
||||
suspend_set_ops(UX500_SUSPEND_OPS);
|
||||
|
||||
/* Initialize ux500 power domains */
|
||||
ux500_pm_domains_init();
|
||||
}
|
||||
|
|
|
@ -344,6 +344,11 @@ void __init arm_mm_memblock_reserve(void)
|
|||
* reserved here.
|
||||
*/
|
||||
#endif
|
||||
/*
|
||||
* In any case, always ensure address 0 is never used as many things
|
||||
* get very confused if 0 is returned as a legitimate address.
|
||||
*/
|
||||
memblock_reserve(0, 1);
|
||||
}
|
||||
|
||||
void __init adjust_lowmem_bounds(void)
|
||||
|
|
|
@ -61,13 +61,6 @@ aliases {
|
|||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
reg_vcc3v3: vcc3v3 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc3v3";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
&ehci0 {
|
||||
|
@ -91,7 +84,7 @@ &i2c1_pins {
|
|||
&mmc0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc0_pins>;
|
||||
vmmc-supply = <®_vcc3v3>;
|
||||
vmmc-supply = <®_dcdc1>;
|
||||
cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
|
||||
cd-inverted;
|
||||
disable-wp;
|
||||
|
|
|
@ -336,7 +336,7 @@ cpm_pcie0: pcie@f2600000 {
|
|||
/* non-prefetchable memory */
|
||||
0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &cpm_icu 0 ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map = <0 0 0 0 &cpm_icu ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
num-lanes = <1>;
|
||||
clocks = <&cpm_clk 1 13>;
|
||||
|
@ -362,7 +362,7 @@ cpm_pcie1: pcie@f2620000 {
|
|||
/* non-prefetchable memory */
|
||||
0x82000000 0 0xf7000000 0 0xf7000000 0 0xf00000>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &cpm_icu 0 ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map = <0 0 0 0 &cpm_icu ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
num-lanes = <1>;
|
||||
|
@ -389,7 +389,7 @@ cpm_pcie2: pcie@f2640000 {
|
|||
/* non-prefetchable memory */
|
||||
0x82000000 0 0xf8000000 0 0xf8000000 0 0xf00000>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &cpm_icu 0 ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map = <0 0 0 0 &cpm_icu ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
num-lanes = <1>;
|
||||
|
|
|
@ -335,7 +335,7 @@ cps_pcie0: pcie@f4600000 {
|
|||
/* non-prefetchable memory */
|
||||
0x82000000 0 0xfa000000 0 0xfa000000 0 0xf00000>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &cps_icu 0 ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map = <0 0 0 0 &cps_icu ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 22 IRQ_TYPE_LEVEL_HIGH>;
|
||||
num-lanes = <1>;
|
||||
clocks = <&cps_clk 1 13>;
|
||||
|
@ -361,7 +361,7 @@ cps_pcie1: pcie@f4620000 {
|
|||
/* non-prefetchable memory */
|
||||
0x82000000 0 0xfb000000 0 0xfb000000 0 0xf00000>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &cps_icu 0 ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map = <0 0 0 0 &cps_icu ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
num-lanes = <1>;
|
||||
|
@ -388,7 +388,7 @@ cps_pcie2: pcie@f4640000 {
|
|||
/* non-prefetchable memory */
|
||||
0x82000000 0 0xfc000000 0 0xfc000000 0 0xf00000>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &cps_icu 0 ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map = <0 0 0 0 &cps_icu ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <ICU_GRP_NSR 23 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
num-lanes = <1>;
|
||||
|
|
|
@ -62,6 +62,7 @@ backlight: backlight {
|
|||
brightness-levels = <256 128 64 16 8 4 0>;
|
||||
default-brightness-level = <6>;
|
||||
|
||||
power-supply = <®_12v>;
|
||||
enable-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
|
@ -83,6 +84,15 @@ reg_3p3v: regulator1 {
|
|||
regulator-always-on;
|
||||
};
|
||||
|
||||
reg_12v: regulator2 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "fixed-12V";
|
||||
regulator-min-microvolt = <12000000>;
|
||||
regulator-max-microvolt = <12000000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
rsnd_ak4613: sound {
|
||||
compatible = "simple-audio-card";
|
||||
|
||||
|
|
|
@ -582,7 +582,7 @@ rkvdec_mmu: iommu@ff360480 {
|
|||
vop_mmu: iommu@ff373f00 {
|
||||
compatible = "rockchip,iommu";
|
||||
reg = <0x0 0xff373f00 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "vop_mmu";
|
||||
#iommu-cells = <0>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -740,7 +740,7 @@ i2s_8ch: i2s-8ch@ff898000 {
|
|||
iep_mmu: iommu@ff900800 {
|
||||
compatible = "rockchip,iommu";
|
||||
reg = <0x0 0xff900800 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "iep_mmu";
|
||||
#iommu-cells = <0>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -371,10 +371,10 @@ vcc_sdio: LDO_REG4 {
|
|||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <3300000>;
|
||||
regulator-suspend-microvolt = <3000000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -325,12 +325,12 @@ regulator-state-mem {
|
|||
vcc_sd: LDO_REG4 {
|
||||
regulator-name = "vcc_sd";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <3300000>;
|
||||
regulator-suspend-microvolt = <3000000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -315,10 +315,10 @@ vcc_sdio: LDO_REG4 {
|
|||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <3300000>;
|
||||
regulator-suspend-microvolt = <3000000>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -35,12 +35,12 @@ EXPORT_SYMBOL(memset);
|
|||
EXPORT_SYMBOL(__xchg8);
|
||||
EXPORT_SYMBOL(__xchg32);
|
||||
EXPORT_SYMBOL(__cmpxchg_u32);
|
||||
EXPORT_SYMBOL(__cmpxchg_u64);
|
||||
#ifdef CONFIG_SMP
|
||||
EXPORT_SYMBOL(__atomic_hash);
|
||||
#endif
|
||||
#ifdef CONFIG_64BIT
|
||||
EXPORT_SYMBOL(__xchg64);
|
||||
EXPORT_SYMBOL(__cmpxchg_u64);
|
||||
#endif
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
|
|
@ -742,7 +742,7 @@ lws_compare_and_swap_2:
|
|||
10: ldd 0(%r25), %r25
|
||||
11: ldd 0(%r24), %r24
|
||||
#else
|
||||
/* Load new value into r22/r23 - high/low */
|
||||
/* Load old value into r22/r23 - high/low */
|
||||
10: ldw 0(%r25), %r22
|
||||
11: ldw 4(%r25), %r23
|
||||
/* Load new value into fr4 for atomic store later */
|
||||
|
@ -834,11 +834,11 @@ cas2_action:
|
|||
copy %r0, %r28
|
||||
#else
|
||||
/* Compare first word */
|
||||
19: ldw,ma 0(%r26), %r29
|
||||
19: ldw 0(%r26), %r29
|
||||
sub,= %r29, %r22, %r0
|
||||
b,n cas2_end
|
||||
/* Compare second word */
|
||||
20: ldw,ma 4(%r26), %r29
|
||||
20: ldw 4(%r26), %r29
|
||||
sub,= %r29, %r23, %r0
|
||||
b,n cas2_end
|
||||
/* Perform the store */
|
||||
|
|
|
@ -253,7 +253,10 @@ static int __init init_cr16_clocksource(void)
|
|||
cpu0_loc = per_cpu(cpu_data, 0).cpu_loc;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
if (cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc)
|
||||
if (cpu == 0)
|
||||
continue;
|
||||
if ((cpu0_loc != 0) &&
|
||||
(cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc))
|
||||
continue;
|
||||
|
||||
clocksource_cr16.name = "cr16_unstable";
|
||||
|
|
|
@ -27,6 +27,7 @@ CONFIG_NET=y
|
|||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_DEVTMPFS=y
|
||||
# CONFIG_FIRMWARE_IN_KERNEL is not set
|
||||
CONFIG_BLK_DEV_RAM=y
|
||||
# CONFIG_BLK_DEV_XPRAM is not set
|
||||
# CONFIG_DCSSBLK is not set
|
||||
# CONFIG_DASD is not set
|
||||
|
@ -59,6 +60,7 @@ CONFIG_CONFIGFS_FS=y
|
|||
# CONFIG_NETWORK_FILESYSTEMS is not set
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_PANIC_ON_OOPS=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
|
|
|
@ -293,7 +293,10 @@ static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
|
|||
lc->lpp = LPP_MAGIC;
|
||||
lc->current_pid = tsk->pid;
|
||||
lc->user_timer = tsk->thread.user_timer;
|
||||
lc->guest_timer = tsk->thread.guest_timer;
|
||||
lc->system_timer = tsk->thread.system_timer;
|
||||
lc->hardirq_timer = tsk->thread.hardirq_timer;
|
||||
lc->softirq_timer = tsk->thread.softirq_timer;
|
||||
lc->steal_timer = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,10 @@ build_mmio_write(__writeq, "q", unsigned long, "r", )
|
|||
|
||||
#endif
|
||||
|
||||
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
|
||||
extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
|
||||
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
|
||||
|
||||
/**
|
||||
* virt_to_phys - map virtual addresses to physical
|
||||
* @address: address to remap
|
||||
|
|
|
@ -82,12 +82,21 @@ static inline u64 inc_mm_tlb_gen(struct mm_struct *mm)
|
|||
#define __flush_tlb_single(addr) __native_flush_tlb_single(addr)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If tlb_use_lazy_mode is true, then we try to avoid switching CR3 to point
|
||||
* to init_mm when we switch to a kernel thread (e.g. the idle thread). If
|
||||
* it's false, then we immediately switch CR3 when entering a kernel thread.
|
||||
*/
|
||||
DECLARE_STATIC_KEY_TRUE(tlb_use_lazy_mode);
|
||||
static inline bool tlb_defer_switch_to_init_mm(void)
|
||||
{
|
||||
/*
|
||||
* If we have PCID, then switching to init_mm is reasonably
|
||||
* fast. If we don't have PCID, then switching to init_mm is
|
||||
* quite slow, so we try to defer it in the hopes that we can
|
||||
* avoid it entirely. The latter approach runs the risk of
|
||||
* receiving otherwise unnecessary IPIs.
|
||||
*
|
||||
* This choice is just a heuristic. The tlb code can handle this
|
||||
* function returning true or false regardless of whether we have
|
||||
* PCID.
|
||||
*/
|
||||
return !static_cpu_has(X86_FEATURE_PCID);
|
||||
}
|
||||
|
||||
/*
|
||||
* 6 because 6 should be plenty and struct tlb_state will fit in
|
||||
|
|
|
@ -831,7 +831,6 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index,
|
|||
} else if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
|
||||
unsigned int apicid, nshared, first, last;
|
||||
|
||||
this_leaf = this_cpu_ci->info_list + index;
|
||||
nshared = base->eax.split.num_threads_sharing + 1;
|
||||
apicid = cpu_data(cpu).apicid;
|
||||
first = apicid - (apicid % nshared);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/microcode_intel.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/setup.h>
|
||||
|
@ -918,6 +919,18 @@ static int get_ucode_fw(void *to, const void *from, size_t n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool is_blacklisted(unsigned int cpu)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
||||
|
||||
if (c->x86 == 6 && c->x86_model == INTEL_FAM6_BROADWELL_X) {
|
||||
pr_err_once("late loading on model 79 is disabled.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum ucode_state request_microcode_fw(int cpu, struct device *device,
|
||||
bool refresh_fw)
|
||||
{
|
||||
|
@ -926,6 +939,9 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
|
|||
const struct firmware *firmware;
|
||||
enum ucode_state ret;
|
||||
|
||||
if (is_blacklisted(cpu))
|
||||
return UCODE_NFOUND;
|
||||
|
||||
sprintf(name, "intel-ucode/%02x-%02x-%02x",
|
||||
c->x86, c->x86_model, c->x86_mask);
|
||||
|
||||
|
@ -950,6 +966,9 @@ static int get_ucode_user(void *to, const void *from, size_t n)
|
|||
static enum ucode_state
|
||||
request_microcode_user(int cpu, const void __user *buf, size_t size)
|
||||
{
|
||||
if (is_blacklisted(cpu))
|
||||
return UCODE_NFOUND;
|
||||
|
||||
return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,10 +30,11 @@ static void __init i386_default_early_setup(void)
|
|||
|
||||
asmlinkage __visible void __init i386_start_kernel(void)
|
||||
{
|
||||
cr4_init_shadow();
|
||||
|
||||
/* Make sure IDT is set up before any exception happens */
|
||||
idt_setup_early_handler();
|
||||
|
||||
cr4_init_shadow();
|
||||
|
||||
sanitize_boot_params(&boot_params);
|
||||
|
||||
x86_early_init_platform_quirks();
|
||||
|
|
|
@ -174,3 +174,15 @@ const char *arch_vma_name(struct vm_area_struct *vma)
|
|||
return "[mpx]";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int valid_phys_addr_range(phys_addr_t addr, size_t count)
|
||||
{
|
||||
return addr + count <= __pa(high_memory);
|
||||
}
|
||||
|
||||
int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
|
||||
{
|
||||
phys_addr_t addr = (phys_addr_t)pfn << PAGE_SHIFT;
|
||||
|
||||
return valid_phys_addr_range(addr, count);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
atomic64_t last_mm_ctx_id = ATOMIC64_INIT(1);
|
||||
|
||||
DEFINE_STATIC_KEY_TRUE(tlb_use_lazy_mode);
|
||||
|
||||
static void choose_new_asid(struct mm_struct *next, u64 next_tlb_gen,
|
||||
u16 *new_asid, bool *need_flush)
|
||||
|
@ -147,8 +146,8 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
|||
this_cpu_write(cpu_tlbstate.is_lazy, false);
|
||||
|
||||
if (real_prev == next) {
|
||||
VM_BUG_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) !=
|
||||
next->context.ctx_id);
|
||||
VM_WARN_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) !=
|
||||
next->context.ctx_id);
|
||||
|
||||
/*
|
||||
* We don't currently support having a real mm loaded without
|
||||
|
@ -213,6 +212,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
|||
}
|
||||
|
||||
/*
|
||||
* Please ignore the name of this function. It should be called
|
||||
* switch_to_kernel_thread().
|
||||
*
|
||||
* enter_lazy_tlb() is a hint from the scheduler that we are entering a
|
||||
* kernel thread or other context without an mm. Acceptable implementations
|
||||
* include doing nothing whatsoever, switching to init_mm, or various clever
|
||||
|
@ -227,7 +229,7 @@ void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
|
|||
if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)
|
||||
return;
|
||||
|
||||
if (static_branch_unlikely(&tlb_use_lazy_mode)) {
|
||||
if (tlb_defer_switch_to_init_mm()) {
|
||||
/*
|
||||
* There's a significant optimization that may be possible
|
||||
* here. We have accurate enough TLB flush tracking that we
|
||||
|
@ -626,57 +628,3 @@ static int __init create_tlb_single_page_flush_ceiling(void)
|
|||
return 0;
|
||||
}
|
||||
late_initcall(create_tlb_single_page_flush_ceiling);
|
||||
|
||||
static ssize_t tlblazy_read_file(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
buf[0] = static_branch_likely(&tlb_use_lazy_mode) ? '1' : '0';
|
||||
buf[1] = '\n';
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static ssize_t tlblazy_write_file(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
bool val;
|
||||
|
||||
if (kstrtobool_from_user(user_buf, count, &val))
|
||||
return -EINVAL;
|
||||
|
||||
if (val)
|
||||
static_branch_enable(&tlb_use_lazy_mode);
|
||||
else
|
||||
static_branch_disable(&tlb_use_lazy_mode);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_tlblazy = {
|
||||
.read = tlblazy_read_file,
|
||||
.write = tlblazy_write_file,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int __init init_tlb_use_lazy_mode(void)
|
||||
{
|
||||
if (boot_cpu_has(X86_FEATURE_PCID)) {
|
||||
/*
|
||||
* Heuristic: with PCID on, switching to and from
|
||||
* init_mm is reasonably fast, but remote flush IPIs
|
||||
* as expensive as ever, so turn off lazy TLB mode.
|
||||
*
|
||||
* We can't do this in setup_pcid() because static keys
|
||||
* haven't been initialized yet, and it would blow up
|
||||
* badly.
|
||||
*/
|
||||
static_branch_disable(&tlb_use_lazy_mode);
|
||||
}
|
||||
|
||||
debugfs_create_file("tlb_use_lazy_mode", S_IRUSR | S_IWUSR,
|
||||
arch_debugfs_dir, NULL, &fops_tlblazy);
|
||||
return 0;
|
||||
}
|
||||
late_initcall(init_tlb_use_lazy_mode);
|
||||
|
|
|
@ -57,6 +57,8 @@ struct key *find_asymmetric_key(struct key *keyring,
|
|||
char *req, *p;
|
||||
int len;
|
||||
|
||||
BUG_ON(!id_0 && !id_1);
|
||||
|
||||
if (id_0) {
|
||||
lookup = id_0->data;
|
||||
len = id_0->len;
|
||||
|
@ -105,7 +107,7 @@ struct key *find_asymmetric_key(struct key *keyring,
|
|||
if (id_0 && id_1) {
|
||||
const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
|
||||
|
||||
if (!kids->id[0]) {
|
||||
if (!kids->id[1]) {
|
||||
pr_debug("First ID matches, but second is missing\n");
|
||||
goto reject;
|
||||
}
|
||||
|
|
|
@ -88,6 +88,9 @@ static int pkcs7_check_authattrs(struct pkcs7_message *msg)
|
|||
bool want = false;
|
||||
|
||||
sinfo = msg->signed_infos;
|
||||
if (!sinfo)
|
||||
goto inconsistent;
|
||||
|
||||
if (sinfo->authattrs) {
|
||||
want = true;
|
||||
msg->have_authattrs = true;
|
||||
|
|
|
@ -3662,12 +3662,6 @@ static void binder_stat_br(struct binder_proc *proc,
|
|||
}
|
||||
}
|
||||
|
||||
static int binder_has_thread_work(struct binder_thread *thread)
|
||||
{
|
||||
return !binder_worklist_empty(thread->proc, &thread->todo) ||
|
||||
thread->looper_need_return;
|
||||
}
|
||||
|
||||
static int binder_put_node_cmd(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
void __user **ptrp,
|
||||
|
@ -4297,12 +4291,9 @@ static unsigned int binder_poll(struct file *filp,
|
|||
|
||||
binder_inner_proc_unlock(thread->proc);
|
||||
|
||||
if (binder_has_work(thread, wait_for_proc_work))
|
||||
return POLLIN;
|
||||
|
||||
poll_wait(filp, &thread->wait, wait);
|
||||
|
||||
if (binder_has_thread_work(thread))
|
||||
if (binder_has_work(thread, wait_for_proc_work))
|
||||
return POLLIN;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -215,17 +215,12 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
|
|||
}
|
||||
}
|
||||
|
||||
if (!vma && need_mm)
|
||||
mm = get_task_mm(alloc->tsk);
|
||||
if (!vma && need_mm && mmget_not_zero(alloc->vma_vm_mm))
|
||||
mm = alloc->vma_vm_mm;
|
||||
|
||||
if (mm) {
|
||||
down_write(&mm->mmap_sem);
|
||||
vma = alloc->vma;
|
||||
if (vma && mm != alloc->vma_vm_mm) {
|
||||
pr_err("%d: vma mm and task mm mismatch\n",
|
||||
alloc->pid);
|
||||
vma = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vma && need_mm) {
|
||||
|
@ -565,7 +560,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc,
|
|||
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
|
||||
"%d: merge free, buffer %pK do not share page with %pK or %pK\n",
|
||||
alloc->pid, buffer->data,
|
||||
prev->data, next->data);
|
||||
prev->data, next ? next->data : NULL);
|
||||
binder_update_page_range(alloc, 0, buffer_start_page(buffer),
|
||||
buffer_start_page(buffer) + PAGE_SIZE,
|
||||
NULL);
|
||||
|
@ -720,6 +715,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
|
|||
barrier();
|
||||
alloc->vma = vma;
|
||||
alloc->vma_vm_mm = vma->vm_mm;
|
||||
mmgrab(alloc->vma_vm_mm);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -795,6 +791,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
|
|||
vfree(alloc->buffer);
|
||||
}
|
||||
mutex_unlock(&alloc->mutex);
|
||||
if (alloc->vma_vm_mm)
|
||||
mmdrop(alloc->vma_vm_mm);
|
||||
|
||||
binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE,
|
||||
"%s: %d buffers %d, pages %d\n",
|
||||
|
@ -889,7 +887,6 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc)
|
|||
void binder_alloc_vma_close(struct binder_alloc *alloc)
|
||||
{
|
||||
WRITE_ONCE(alloc->vma, NULL);
|
||||
WRITE_ONCE(alloc->vma_vm_mm, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -926,9 +923,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
|
|||
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
|
||||
vma = alloc->vma;
|
||||
if (vma) {
|
||||
mm = get_task_mm(alloc->tsk);
|
||||
if (!mm)
|
||||
goto err_get_task_mm_failed;
|
||||
if (!mmget_not_zero(alloc->vma_vm_mm))
|
||||
goto err_mmget;
|
||||
mm = alloc->vma_vm_mm;
|
||||
if (!down_write_trylock(&mm->mmap_sem))
|
||||
goto err_down_write_mmap_sem_failed;
|
||||
}
|
||||
|
@ -963,7 +960,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
|
|||
|
||||
err_down_write_mmap_sem_failed:
|
||||
mmput_async(mm);
|
||||
err_get_task_mm_failed:
|
||||
err_mmget:
|
||||
err_page_already_freed:
|
||||
mutex_unlock(&alloc->mutex);
|
||||
err_get_alloc_mutex_failed:
|
||||
|
@ -1002,7 +999,6 @@ struct shrinker binder_shrinker = {
|
|||
*/
|
||||
void binder_alloc_init(struct binder_alloc *alloc)
|
||||
{
|
||||
alloc->tsk = current->group_leader;
|
||||
alloc->pid = current->group_leader->pid;
|
||||
mutex_init(&alloc->mutex);
|
||||
INIT_LIST_HEAD(&alloc->buffers);
|
||||
|
|
|
@ -100,7 +100,6 @@ struct binder_lru_page {
|
|||
*/
|
||||
struct binder_alloc {
|
||||
struct mutex mutex;
|
||||
struct task_struct *tsk;
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *vma_vm_mm;
|
||||
void *buffer;
|
||||
|
|
|
@ -243,7 +243,6 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize,
|
|||
struct nbd_config *config = nbd->config;
|
||||
config->blksize = blocksize;
|
||||
config->bytesize = blocksize * nr_blocks;
|
||||
nbd_size_update(nbd);
|
||||
}
|
||||
|
||||
static void nbd_complete_rq(struct request *req)
|
||||
|
@ -1094,6 +1093,7 @@ static int nbd_start_device(struct nbd_device *nbd)
|
|||
args->index = i;
|
||||
queue_work(recv_workqueue, &args->work);
|
||||
}
|
||||
nbd_size_update(nbd);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -2604,7 +2604,7 @@ static void *skd_alloc_dma(struct skd_device *skdev, struct kmem_cache *s,
|
|||
return NULL;
|
||||
*dma_handle = dma_map_single(dev, buf, s->size, dir);
|
||||
if (dma_mapping_error(dev, *dma_handle)) {
|
||||
kfree(buf);
|
||||
kmem_cache_free(s, buf);
|
||||
buf = NULL;
|
||||
}
|
||||
return buf;
|
||||
|
|
|
@ -720,7 +720,7 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
|
|||
if (mbus->hw_io_coherency)
|
||||
w->mbus_attr |= ATTR_HW_COHERENCY;
|
||||
w->base = base & DDR_BASE_CS_LOW_MASK;
|
||||
w->size = (size | ~DDR_SIZE_MASK) + 1;
|
||||
w->size = (u64)(size | ~DDR_SIZE_MASK) + 1;
|
||||
}
|
||||
}
|
||||
mvebu_mbus_dram_info.num_cs = cs;
|
||||
|
|
|
@ -117,7 +117,8 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id)
|
|||
/* Turn off the clock (and clear the event) */
|
||||
disable_timer(cs5535_event_clock);
|
||||
|
||||
if (clockevent_state_shutdown(&cs5535_clockevent))
|
||||
if (clockevent_state_detached(&cs5535_clockevent) ||
|
||||
clockevent_state_shutdown(&cs5535_clockevent))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* Clear the counter */
|
||||
|
|
|
@ -344,7 +344,7 @@ msgdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
|
|||
|
||||
spin_lock_irqsave(&mdev->lock, irqflags);
|
||||
if (desc_cnt > mdev->desc_free_cnt) {
|
||||
spin_unlock_bh(&mdev->lock);
|
||||
spin_unlock_irqrestore(&mdev->lock, irqflags);
|
||||
dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ msgdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
|
|||
|
||||
spin_lock_irqsave(&mdev->lock, irqflags);
|
||||
if (desc_cnt > mdev->desc_free_cnt) {
|
||||
spin_unlock_bh(&mdev->lock);
|
||||
spin_unlock_irqrestore(&mdev->lock, irqflags);
|
||||
dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -205,32 +205,17 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
|
|||
struct amd_sched_entity *entity)
|
||||
{
|
||||
struct amd_sched_rq *rq = entity->rq;
|
||||
int r;
|
||||
|
||||
if (!amd_sched_entity_is_initialized(sched, entity))
|
||||
return;
|
||||
|
||||
/**
|
||||
* The client will not queue more IBs during this fini, consume existing
|
||||
* queued IBs or discard them on SIGKILL
|
||||
* queued IBs
|
||||
*/
|
||||
if ((current->flags & PF_SIGNALED) && current->exit_code == SIGKILL)
|
||||
r = -ERESTARTSYS;
|
||||
else
|
||||
r = wait_event_killable(sched->job_scheduled,
|
||||
amd_sched_entity_is_idle(entity));
|
||||
wait_event(sched->job_scheduled, amd_sched_entity_is_idle(entity));
|
||||
|
||||
amd_sched_rq_remove_entity(rq, entity);
|
||||
if (r) {
|
||||
struct amd_sched_job *job;
|
||||
|
||||
/* Park the kernel for a moment to make sure it isn't processing
|
||||
* our enity.
|
||||
*/
|
||||
kthread_park(sched->thread);
|
||||
kthread_unpark(sched->thread);
|
||||
while (kfifo_out(&entity->job_queue, &job, sizeof(job)))
|
||||
sched->ops->free_job(job);
|
||||
|
||||
}
|
||||
kfifo_free(&entity->job_queue);
|
||||
}
|
||||
|
||||
|
|
|
@ -168,11 +168,13 @@ static struct drm_driver exynos_drm_driver = {
|
|||
static int exynos_drm_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct exynos_drm_private *private = drm_dev->dev_private;
|
||||
struct exynos_drm_private *private;
|
||||
|
||||
if (pm_runtime_suspended(dev) || !drm_dev)
|
||||
return 0;
|
||||
|
||||
private = drm_dev->dev_private;
|
||||
|
||||
drm_kms_helper_poll_disable(drm_dev);
|
||||
exynos_drm_fbdev_suspend(drm_dev);
|
||||
private->suspend_state = drm_atomic_helper_suspend(drm_dev);
|
||||
|
@ -188,11 +190,12 @@ static int exynos_drm_suspend(struct device *dev)
|
|||
static int exynos_drm_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct exynos_drm_private *private = drm_dev->dev_private;
|
||||
struct exynos_drm_private *private;
|
||||
|
||||
if (pm_runtime_suspended(dev) || !drm_dev)
|
||||
return 0;
|
||||
|
||||
private = drm_dev->dev_private;
|
||||
drm_atomic_helper_resume(drm_dev, private->suspend_state);
|
||||
exynos_drm_fbdev_resume(drm_dev);
|
||||
drm_kms_helper_poll_enable(drm_dev);
|
||||
|
@ -427,6 +430,7 @@ static void exynos_drm_unbind(struct device *dev)
|
|||
|
||||
kfree(drm->dev_private);
|
||||
drm->dev_private = NULL;
|
||||
dev_set_drvdata(dev, NULL);
|
||||
|
||||
drm_dev_unref(drm);
|
||||
}
|
||||
|
|
|
@ -308,20 +308,8 @@ static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu)
|
|||
|
||||
static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu)
|
||||
{
|
||||
struct intel_gvt_workload_scheduler *scheduler = &vgpu->gvt->scheduler;
|
||||
int ring_id;
|
||||
|
||||
kfree(vgpu->sched_data);
|
||||
vgpu->sched_data = NULL;
|
||||
|
||||
spin_lock_bh(&scheduler->mmio_context_lock);
|
||||
for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) {
|
||||
if (scheduler->engine_owner[ring_id] == vgpu) {
|
||||
intel_gvt_switch_mmio(vgpu, NULL, ring_id);
|
||||
scheduler->engine_owner[ring_id] = NULL;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&scheduler->mmio_context_lock);
|
||||
}
|
||||
|
||||
static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)
|
||||
|
@ -388,6 +376,7 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
|
|||
{
|
||||
struct intel_gvt_workload_scheduler *scheduler =
|
||||
&vgpu->gvt->scheduler;
|
||||
int ring_id;
|
||||
|
||||
gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id);
|
||||
|
||||
|
@ -401,4 +390,13 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
|
|||
scheduler->need_reschedule = true;
|
||||
scheduler->current_vgpu = NULL;
|
||||
}
|
||||
|
||||
spin_lock_bh(&scheduler->mmio_context_lock);
|
||||
for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) {
|
||||
if (scheduler->engine_owner[ring_id] == vgpu) {
|
||||
intel_gvt_switch_mmio(vgpu, NULL, ring_id);
|
||||
scheduler->engine_owner[ring_id] = NULL;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&scheduler->mmio_context_lock);
|
||||
}
|
||||
|
|
|
@ -2657,6 +2657,9 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
|
|||
if (READ_ONCE(obj->mm.pages))
|
||||
return -ENODEV;
|
||||
|
||||
if (obj->mm.madv != I915_MADV_WILLNEED)
|
||||
return -EFAULT;
|
||||
|
||||
/* Before the pages are instantiated the object is treated as being
|
||||
* in the CPU domain. The pages will be clflushed as required before
|
||||
* use, and we can freely write into the pages directly. If userspace
|
||||
|
|
|
@ -33,21 +33,20 @@
|
|||
#include "intel_drv.h"
|
||||
#include "i915_trace.h"
|
||||
|
||||
static bool ggtt_is_idle(struct drm_i915_private *dev_priv)
|
||||
static bool ggtt_is_idle(struct drm_i915_private *i915)
|
||||
{
|
||||
struct i915_ggtt *ggtt = &dev_priv->ggtt;
|
||||
struct intel_engine_cs *engine;
|
||||
enum intel_engine_id id;
|
||||
struct intel_engine_cs *engine;
|
||||
enum intel_engine_id id;
|
||||
|
||||
for_each_engine(engine, dev_priv, id) {
|
||||
struct intel_timeline *tl;
|
||||
if (i915->gt.active_requests)
|
||||
return false;
|
||||
|
||||
tl = &ggtt->base.timeline.engine[engine->id];
|
||||
if (i915_gem_active_isset(&tl->last_request))
|
||||
return false;
|
||||
}
|
||||
for_each_engine(engine, i915, id) {
|
||||
if (engine->last_retired_context != i915->kernel_context)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ggtt_flush(struct drm_i915_private *i915)
|
||||
|
@ -157,7 +156,8 @@ i915_gem_evict_something(struct i915_address_space *vm,
|
|||
min_size, alignment, cache_level,
|
||||
start, end, mode);
|
||||
|
||||
/* Retire before we search the active list. Although we have
|
||||
/*
|
||||
* Retire before we search the active list. Although we have
|
||||
* reasonable accuracy in our retirement lists, we may have
|
||||
* a stray pin (preventing eviction) that can only be resolved by
|
||||
* retiring.
|
||||
|
@ -182,7 +182,8 @@ i915_gem_evict_something(struct i915_address_space *vm,
|
|||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
/* Can we unpin some objects such as idle hw contents,
|
||||
/*
|
||||
* Can we unpin some objects such as idle hw contents,
|
||||
* or pending flips? But since only the GGTT has global entries
|
||||
* such as scanouts, rinbuffers and contexts, we can skip the
|
||||
* purge when inspecting per-process local address spaces.
|
||||
|
@ -190,19 +191,33 @@ i915_gem_evict_something(struct i915_address_space *vm,
|
|||
if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK)
|
||||
return -ENOSPC;
|
||||
|
||||
if (ggtt_is_idle(dev_priv)) {
|
||||
/* If we still have pending pageflip completions, drop
|
||||
* back to userspace to give our workqueues time to
|
||||
* acquire our locks and unpin the old scanouts.
|
||||
*/
|
||||
return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC;
|
||||
/*
|
||||
* Not everything in the GGTT is tracked via VMA using
|
||||
* i915_vma_move_to_active(), otherwise we could evict as required
|
||||
* with minimal stalling. Instead we are forced to idle the GPU and
|
||||
* explicitly retire outstanding requests which will then remove
|
||||
* the pinning for active objects such as contexts and ring,
|
||||
* enabling us to evict them on the next iteration.
|
||||
*
|
||||
* To ensure that all user contexts are evictable, we perform
|
||||
* a switch to the perma-pinned kernel context. This all also gives
|
||||
* us a termination condition, when the last retired context is
|
||||
* the kernel's there is no more we can evict.
|
||||
*/
|
||||
if (!ggtt_is_idle(dev_priv)) {
|
||||
ret = ggtt_flush(dev_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
goto search_again;
|
||||
}
|
||||
|
||||
ret = ggtt_flush(dev_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
goto search_again;
|
||||
/*
|
||||
* If we still have pending pageflip completions, drop
|
||||
* back to userspace to give our workqueues time to
|
||||
* acquire our locks and unpin the old scanouts.
|
||||
*/
|
||||
return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC;
|
||||
|
||||
found:
|
||||
/* drm_mm doesn't allow any other other operations while
|
||||
|
|
|
@ -6998,6 +6998,7 @@ enum {
|
|||
*/
|
||||
#define L3_GENERAL_PRIO_CREDITS(x) (((x) >> 1) << 19)
|
||||
#define L3_HIGH_PRIO_CREDITS(x) (((x) >> 1) << 14)
|
||||
#define L3_PRIO_CREDITS_MASK ((0x1f << 19) | (0x1f << 14))
|
||||
|
||||
#define GEN7_L3CNTLREG1 _MMIO(0xB01C)
|
||||
#define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C
|
||||
|
|
|
@ -664,8 +664,8 @@ intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv,
|
|||
int *n_entries)
|
||||
{
|
||||
if (IS_BROADWELL(dev_priv)) {
|
||||
*n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi);
|
||||
return hsw_ddi_translations_fdi;
|
||||
*n_entries = ARRAY_SIZE(bdw_ddi_translations_fdi);
|
||||
return bdw_ddi_translations_fdi;
|
||||
} else if (IS_HASWELL(dev_priv)) {
|
||||
*n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi);
|
||||
return hsw_ddi_translations_fdi;
|
||||
|
@ -2102,8 +2102,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
|
|||
* register writes.
|
||||
*/
|
||||
val = I915_READ(DPCLKA_CFGCR0);
|
||||
val &= ~(DPCLKA_CFGCR0_DDI_CLK_OFF(port) |
|
||||
DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port));
|
||||
val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
|
||||
I915_WRITE(DPCLKA_CFGCR0, val);
|
||||
} else if (IS_GEN9_BC(dev_priv)) {
|
||||
/* DDI -> PLL mapping */
|
||||
|
|
|
@ -1996,7 +1996,7 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv,
|
|||
|
||||
/* 3. Configure DPLL_CFGCR0 */
|
||||
/* Avoid touch CFGCR1 if HDMI mode is not enabled */
|
||||
if (pll->state.hw_state.cfgcr0 & DPLL_CTRL1_HDMI_MODE(pll->id)) {
|
||||
if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
|
||||
val = pll->state.hw_state.cfgcr1;
|
||||
I915_WRITE(CNL_DPLL_CFGCR1(pll->id), val);
|
||||
/* 4. Reab back to ensure writes completed */
|
||||
|
|
|
@ -1048,9 +1048,12 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine)
|
|||
}
|
||||
|
||||
/* WaProgramL3SqcReg1DefaultForPerf:bxt */
|
||||
if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER))
|
||||
I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) |
|
||||
L3_HIGH_PRIO_CREDITS(2));
|
||||
if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) {
|
||||
u32 val = I915_READ(GEN8_L3SQCREG1);
|
||||
val &= ~L3_PRIO_CREDITS_MASK;
|
||||
val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2);
|
||||
I915_WRITE(GEN8_L3SQCREG1, val);
|
||||
}
|
||||
|
||||
/* WaToEnableHwFixForPushConstHWBug:bxt */
|
||||
if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
|
||||
|
|
|
@ -8245,14 +8245,17 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv,
|
|||
int high_prio_credits)
|
||||
{
|
||||
u32 misccpctl;
|
||||
u32 val;
|
||||
|
||||
/* WaTempDisableDOPClkGating:bdw */
|
||||
misccpctl = I915_READ(GEN7_MISCCPCTL);
|
||||
I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
|
||||
|
||||
I915_WRITE(GEN8_L3SQCREG1,
|
||||
L3_GENERAL_PRIO_CREDITS(general_prio_credits) |
|
||||
L3_HIGH_PRIO_CREDITS(high_prio_credits));
|
||||
val = I915_READ(GEN8_L3SQCREG1);
|
||||
val &= ~L3_PRIO_CREDITS_MASK;
|
||||
val |= L3_GENERAL_PRIO_CREDITS(general_prio_credits);
|
||||
val |= L3_HIGH_PRIO_CREDITS(high_prio_credits);
|
||||
I915_WRITE(GEN8_L3SQCREG1, val);
|
||||
|
||||
/*
|
||||
* Wait at least 100 clocks before re-enabling clock gating.
|
||||
|
|
|
@ -223,7 +223,7 @@ void
|
|||
nouveau_fbcon_accel_save_disable(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
if (drm->fbcon) {
|
||||
if (drm->fbcon && drm->fbcon->helper.fbdev) {
|
||||
drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
|
||||
drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ void
|
|||
nouveau_fbcon_accel_restore(struct drm_device *dev)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
if (drm->fbcon) {
|
||||
if (drm->fbcon && drm->fbcon->helper.fbdev) {
|
||||
drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +245,8 @@ nouveau_fbcon_accel_fini(struct drm_device *dev)
|
|||
struct nouveau_fbdev *fbcon = drm->fbcon;
|
||||
if (fbcon && drm->channel) {
|
||||
console_lock();
|
||||
fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
|
||||
if (fbcon->helper.fbdev)
|
||||
fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
|
||||
console_unlock();
|
||||
nouveau_channel_idle(drm->channel);
|
||||
nvif_object_fini(&fbcon->twod);
|
||||
|
|
|
@ -3265,11 +3265,14 @@ nv50_mstm = {
|
|||
void
|
||||
nv50_mstm_service(struct nv50_mstm *mstm)
|
||||
{
|
||||
struct drm_dp_aux *aux = mstm->mgr.aux;
|
||||
struct drm_dp_aux *aux = mstm ? mstm->mgr.aux : NULL;
|
||||
bool handled = true;
|
||||
int ret;
|
||||
u8 esi[8] = {};
|
||||
|
||||
if (!aux)
|
||||
return;
|
||||
|
||||
while (handled) {
|
||||
ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8);
|
||||
if (ret != 8) {
|
||||
|
|
|
@ -39,5 +39,5 @@ int
|
|||
g84_bsp_new(struct nvkm_device *device, int index, struct nvkm_engine **pengine)
|
||||
{
|
||||
return nvkm_xtensa_new_(&g84_bsp, device, index,
|
||||
true, 0x103000, pengine);
|
||||
device->chipset != 0x92, 0x103000, pengine);
|
||||
}
|
||||
|
|
|
@ -241,6 +241,8 @@ nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde)
|
|||
mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem);
|
||||
}
|
||||
|
||||
mmu->func->flush(vm);
|
||||
|
||||
nvkm_memory_del(&pgt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -937,7 +937,10 @@ void vmbus_hvsock_device_unregister(struct vmbus_channel *channel)
|
|||
{
|
||||
BUG_ON(!is_hvsock_channel(channel));
|
||||
|
||||
channel->rescind = true;
|
||||
/* We always get a rescind msg when a connection is closed. */
|
||||
while (!READ_ONCE(channel->probe_done) || !READ_ONCE(channel->rescind))
|
||||
msleep(1);
|
||||
|
||||
vmbus_device_unregister(channel->device_obj);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister);
|
||||
|
|
|
@ -1021,7 +1021,7 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
|
|||
}
|
||||
|
||||
dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n",
|
||||
rinfo->sda_gpio, rinfo->scl_gpio);
|
||||
rinfo->scl_gpio, rinfo->sda_gpio);
|
||||
|
||||
rinfo->prepare_recovery = i2c_imx_prepare_recovery;
|
||||
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
|
||||
|
@ -1100,7 +1100,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Request IRQ */
|
||||
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
|
||||
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED,
|
||||
pdev->name, i2c_imx);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "can't claim irq %d\n", irq);
|
||||
|
|
|
@ -340,12 +340,15 @@ static int ismt_process_desc(const struct ismt_desc *desc,
|
|||
data->word = dma_buffer[0] | (dma_buffer[1] << 8);
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
if (desc->rxbytes != dma_buffer[0] + 1)
|
||||
return -EMSGSIZE;
|
||||
|
||||
memcpy(data->block, dma_buffer, desc->rxbytes);
|
||||
break;
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
memcpy(&data->block[1], dma_buffer, desc->rxbytes);
|
||||
data->block[0] = desc->rxbytes;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -360,6 +360,7 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
|
|||
unsigned long fclk_rate = 12000000;
|
||||
unsigned long internal_clk = 0;
|
||||
struct clk *fclk;
|
||||
int error;
|
||||
|
||||
if (omap->rev >= OMAP_I2C_REV_ON_3430_3530) {
|
||||
/*
|
||||
|
@ -378,6 +379,13 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
|
|||
* do this bit unconditionally.
|
||||
*/
|
||||
fclk = clk_get(omap->dev, "fck");
|
||||
if (IS_ERR(fclk)) {
|
||||
error = PTR_ERR(fclk);
|
||||
dev_err(omap->dev, "could not get fck: %i\n", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
fclk_rate = clk_get_rate(fclk);
|
||||
clk_put(fclk);
|
||||
|
||||
|
@ -410,6 +418,12 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)
|
|||
else
|
||||
internal_clk = 4000;
|
||||
fclk = clk_get(omap->dev, "fck");
|
||||
if (IS_ERR(fclk)) {
|
||||
error = PTR_ERR(fclk);
|
||||
dev_err(omap->dev, "could not get fck: %i\n", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
fclk_rate = clk_get_rate(fclk) / 1000;
|
||||
clk_put(fclk);
|
||||
|
||||
|
|
|
@ -85,6 +85,9 @@
|
|||
/* SB800 constants */
|
||||
#define SB800_PIIX4_SMB_IDX 0xcd6
|
||||
|
||||
#define KERNCZ_IMC_IDX 0x3e
|
||||
#define KERNCZ_IMC_DATA 0x3f
|
||||
|
||||
/*
|
||||
* SB800 port is selected by bits 2:1 of the smb_en register (0x2c)
|
||||
* or the smb_sel register (0x2e), depending on bit 0 of register 0x2f.
|
||||
|
@ -94,6 +97,12 @@
|
|||
#define SB800_PIIX4_PORT_IDX_ALT 0x2e
|
||||
#define SB800_PIIX4_PORT_IDX_SEL 0x2f
|
||||
#define SB800_PIIX4_PORT_IDX_MASK 0x06
|
||||
#define SB800_PIIX4_PORT_IDX_SHIFT 1
|
||||
|
||||
/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */
|
||||
#define SB800_PIIX4_PORT_IDX_KERNCZ 0x02
|
||||
#define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18
|
||||
#define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3
|
||||
|
||||
/* insmod parameters */
|
||||
|
||||
|
@ -149,6 +158,8 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
|
|||
*/
|
||||
static DEFINE_MUTEX(piix4_mutex_sb800);
|
||||
static u8 piix4_port_sel_sb800;
|
||||
static u8 piix4_port_mask_sb800;
|
||||
static u8 piix4_port_shift_sb800;
|
||||
static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = {
|
||||
" port 0", " port 2", " port 3", " port 4"
|
||||
};
|
||||
|
@ -159,6 +170,7 @@ struct i2c_piix4_adapdata {
|
|||
|
||||
/* SB800 */
|
||||
bool sb800_main;
|
||||
bool notify_imc;
|
||||
u8 port; /* Port number, shifted */
|
||||
};
|
||||
|
||||
|
@ -347,7 +359,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
|||
|
||||
/* Find which register is used for port selection */
|
||||
if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) {
|
||||
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT;
|
||||
switch (PIIX4_dev->device) {
|
||||
case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS:
|
||||
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ;
|
||||
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ;
|
||||
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ;
|
||||
break;
|
||||
case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS:
|
||||
default:
|
||||
piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT;
|
||||
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
|
||||
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
mutex_lock(&piix4_mutex_sb800);
|
||||
outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
|
||||
|
@ -355,6 +379,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
|||
piix4_port_sel_sb800 = (port_sel & 0x01) ?
|
||||
SB800_PIIX4_PORT_IDX_ALT :
|
||||
SB800_PIIX4_PORT_IDX;
|
||||
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
|
||||
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
|
||||
mutex_unlock(&piix4_mutex_sb800);
|
||||
}
|
||||
|
||||
|
@ -572,6 +598,67 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t piix4_imc_read(uint8_t idx)
|
||||
{
|
||||
outb_p(idx, KERNCZ_IMC_IDX);
|
||||
return inb_p(KERNCZ_IMC_DATA);
|
||||
}
|
||||
|
||||
static void piix4_imc_write(uint8_t idx, uint8_t value)
|
||||
{
|
||||
outb_p(idx, KERNCZ_IMC_IDX);
|
||||
outb_p(value, KERNCZ_IMC_DATA);
|
||||
}
|
||||
|
||||
static int piix4_imc_sleep(void)
|
||||
{
|
||||
int timeout = MAX_TIMEOUT;
|
||||
|
||||
if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc"))
|
||||
return -EBUSY;
|
||||
|
||||
/* clear response register */
|
||||
piix4_imc_write(0x82, 0x00);
|
||||
/* request ownership flag */
|
||||
piix4_imc_write(0x83, 0xB4);
|
||||
/* kick off IMC Mailbox command 96 */
|
||||
piix4_imc_write(0x80, 0x96);
|
||||
|
||||
while (timeout--) {
|
||||
if (piix4_imc_read(0x82) == 0xfa) {
|
||||
release_region(KERNCZ_IMC_IDX, 2);
|
||||
return 0;
|
||||
}
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
release_region(KERNCZ_IMC_IDX, 2);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void piix4_imc_wakeup(void)
|
||||
{
|
||||
int timeout = MAX_TIMEOUT;
|
||||
|
||||
if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc"))
|
||||
return;
|
||||
|
||||
/* clear response register */
|
||||
piix4_imc_write(0x82, 0x00);
|
||||
/* release ownership flag */
|
||||
piix4_imc_write(0x83, 0xB5);
|
||||
/* kick off IMC Mailbox command 96 */
|
||||
piix4_imc_write(0x80, 0x96);
|
||||
|
||||
while (timeout--) {
|
||||
if (piix4_imc_read(0x82) == 0xfa)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
release_region(KERNCZ_IMC_IDX, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles access to multiple SMBus ports on the SB800.
|
||||
* The port is selected by bits 2:1 of the smb_en register (0x2c).
|
||||
|
@ -612,12 +699,47 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify the IMC (Integrated Micro Controller) if required.
|
||||
* Among other responsibilities, the IMC is in charge of monitoring
|
||||
* the System fans and temperature sensors, and act accordingly.
|
||||
* All this is done through SMBus and can/will collide
|
||||
* with our transactions if they are long (BLOCK_DATA).
|
||||
* Therefore we need to request the ownership flag during those
|
||||
* transactions.
|
||||
*/
|
||||
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) {
|
||||
int ret;
|
||||
|
||||
ret = piix4_imc_sleep();
|
||||
switch (ret) {
|
||||
case -EBUSY:
|
||||
dev_warn(&adap->dev,
|
||||
"IMC base address index region 0x%x already in use.\n",
|
||||
KERNCZ_IMC_IDX);
|
||||
break;
|
||||
case -ETIMEDOUT:
|
||||
dev_warn(&adap->dev,
|
||||
"Failed to communicate with the IMC.\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* If IMC communication fails do not retry */
|
||||
if (ret) {
|
||||
dev_warn(&adap->dev,
|
||||
"Continuing without IMC notification.\n");
|
||||
adapdata->notify_imc = false;
|
||||
}
|
||||
}
|
||||
|
||||
outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
|
||||
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
|
||||
|
||||
port = adapdata->port;
|
||||
if ((smba_en_lo & SB800_PIIX4_PORT_IDX_MASK) != port)
|
||||
outb_p((smba_en_lo & ~SB800_PIIX4_PORT_IDX_MASK) | port,
|
||||
if ((smba_en_lo & piix4_port_mask_sb800) != port)
|
||||
outb_p((smba_en_lo & ~piix4_port_mask_sb800) | port,
|
||||
SB800_PIIX4_SMB_IDX + 1);
|
||||
|
||||
retval = piix4_access(adap, addr, flags, read_write,
|
||||
|
@ -628,6 +750,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
|
|||
/* Release the semaphore */
|
||||
outb_p(smbslvcnt | 0x20, SMBSLVCNT);
|
||||
|
||||
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc)
|
||||
piix4_imc_wakeup();
|
||||
|
||||
mutex_unlock(&piix4_mutex_sb800);
|
||||
|
||||
return retval;
|
||||
|
@ -679,7 +804,7 @@ static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS];
|
|||
static struct i2c_adapter *piix4_aux_adapter;
|
||||
|
||||
static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
||||
bool sb800_main, u8 port,
|
||||
bool sb800_main, u8 port, bool notify_imc,
|
||||
const char *name, struct i2c_adapter **padap)
|
||||
{
|
||||
struct i2c_adapter *adap;
|
||||
|
@ -706,7 +831,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
|||
|
||||
adapdata->smba = smba;
|
||||
adapdata->sb800_main = sb800_main;
|
||||
adapdata->port = port << 1;
|
||||
adapdata->port = port << piix4_port_shift_sb800;
|
||||
adapdata->notify_imc = notify_imc;
|
||||
|
||||
/* set up the sysfs linkage to our parent device */
|
||||
adap->dev.parent = &dev->dev;
|
||||
|
@ -728,14 +854,15 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba)
|
||||
static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba,
|
||||
bool notify_imc)
|
||||
{
|
||||
struct i2c_piix4_adapdata *adapdata;
|
||||
int port;
|
||||
int retval;
|
||||
|
||||
for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) {
|
||||
retval = piix4_add_adapter(dev, smba, true, port,
|
||||
retval = piix4_add_adapter(dev, smba, true, port, notify_imc,
|
||||
piix4_main_port_names_sb800[port],
|
||||
&piix4_main_adapters[port]);
|
||||
if (retval < 0)
|
||||
|
@ -769,6 +896,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS &&
|
||||
dev->revision >= 0x40) ||
|
||||
dev->vendor == PCI_VENDOR_ID_AMD) {
|
||||
bool notify_imc = false;
|
||||
is_sb800 = true;
|
||||
|
||||
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
|
||||
|
@ -778,6 +906,20 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (dev->vendor == PCI_VENDOR_ID_AMD &&
|
||||
dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) {
|
||||
u8 imc;
|
||||
|
||||
/*
|
||||
* Detect if IMC is active or not, this method is
|
||||
* described on coreboot's AMD IMC notes
|
||||
*/
|
||||
pci_bus_read_config_byte(dev->bus, PCI_DEVFN(0x14, 3),
|
||||
0x40, &imc);
|
||||
if (imc & 0x80)
|
||||
notify_imc = true;
|
||||
}
|
||||
|
||||
/* base address location etc changed in SB800 */
|
||||
retval = piix4_setup_sb800(dev, id, 0);
|
||||
if (retval < 0) {
|
||||
|
@ -789,7 +931,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
* Try to register multiplexed main SMBus adapter,
|
||||
* give up if we can't
|
||||
*/
|
||||
retval = piix4_add_adapters_sb800(dev, retval);
|
||||
retval = piix4_add_adapters_sb800(dev, retval, notify_imc);
|
||||
if (retval < 0) {
|
||||
release_region(SB800_PIIX4_SMB_IDX, 2);
|
||||
return retval;
|
||||
|
@ -800,7 +942,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
return retval;
|
||||
|
||||
/* Try to register main SMBus adapter, give up if we can't */
|
||||
retval = piix4_add_adapter(dev, retval, false, 0, "",
|
||||
retval = piix4_add_adapter(dev, retval, false, 0, false, "",
|
||||
&piix4_main_adapters[0]);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
@ -827,7 +969,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
if (retval > 0) {
|
||||
/* Try to add the aux adapter if it exists,
|
||||
* piix4_add_adapter will clean up if this fails */
|
||||
piix4_add_adapter(dev, retval, false, 0,
|
||||
piix4_add_adapter(dev, retval, false, 0, false,
|
||||
is_sb800 ? piix4_aux_port_name_sb800 : "",
|
||||
&piix4_aux_adapter);
|
||||
}
|
||||
|
|
|
@ -148,6 +148,17 @@ config HID_SENSOR_ACCEL_3D
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called hid-sensor-accel-3d.
|
||||
|
||||
config IIO_CROS_EC_ACCEL_LEGACY
|
||||
tristate "ChromeOS EC Legacy Accelerometer Sensor"
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select CROS_EC_LPC_REGISTER_DEVICE
|
||||
help
|
||||
Say yes here to get support for accelerometers on Chromebook using
|
||||
legacy EC firmware.
|
||||
Sensor data is retrieved through IO memory.
|
||||
Newer devices should use IIO_CROS_EC_SENSORS.
|
||||
|
||||
config IIO_ST_ACCEL_3AXIS
|
||||
tristate "STMicroelectronics accelerometers 3-Axis Driver"
|
||||
depends on (I2C || SPI_MASTER) && SYSFS
|
||||
|
@ -219,8 +230,8 @@ config KXCJK1013
|
|||
select IIO_TRIGGERED_BUFFER
|
||||
help
|
||||
Say Y here if you want to build a driver for the Kionix KXCJK-1013
|
||||
triaxial acceleration sensor. This driver also supports KXCJ9-1008
|
||||
and KXTJ2-1009.
|
||||
triaxial acceleration sensor. This driver also supports KXCJ9-1008,
|
||||
KXTJ2-1009 and KXTF9.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will
|
||||
be called kxcjk-1013.
|
||||
|
|
|
@ -43,6 +43,8 @@ obj-$(CONFIG_SCA3000) += sca3000.o
|
|||
obj-$(CONFIG_STK8312) += stk8312.o
|
||||
obj-$(CONFIG_STK8BA50) += stk8ba50.o
|
||||
|
||||
obj-$(CONFIG_IIO_CROS_EC_ACCEL_LEGACY) += cros_ec_accel_legacy.o
|
||||
|
||||
obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o
|
||||
|
||||
obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
|
||||
|
|
|
@ -95,7 +95,6 @@ static int adxl345_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info adxl345_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = adxl345_read_raw,
|
||||
};
|
||||
|
||||
|
|
|
@ -536,7 +536,6 @@ static const struct iio_info bma180_info = {
|
|||
.attrs = &bma180_attrs_group,
|
||||
.read_raw = bma180_read_raw,
|
||||
.write_raw = bma180_write_raw,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const char * const bma180_power_modes[] = { "low_noise", "low_power" };
|
||||
|
@ -700,7 +699,6 @@ static int bma180_trig_try_reen(struct iio_trigger *trig)
|
|||
static const struct iio_trigger_ops bma180_trigger_ops = {
|
||||
.set_trigger_state = bma180_data_rdy_trigger_set_state,
|
||||
.try_reenable = bma180_trig_try_reen,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int bma180_probe(struct i2c_client *client,
|
||||
|
|
|
@ -186,7 +186,6 @@ static int bma220_write_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info bma220_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = bma220_read_raw,
|
||||
.write_raw = bma220_write_raw,
|
||||
.attrs = &bma220_attribute_group,
|
||||
|
|
|
@ -1094,7 +1094,6 @@ static const struct iio_info bmc150_accel_info = {
|
|||
.write_event_value = bmc150_accel_write_event,
|
||||
.write_event_config = bmc150_accel_write_event_config,
|
||||
.read_event_config = bmc150_accel_read_event_config,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct iio_info bmc150_accel_info_fifo = {
|
||||
|
@ -1108,7 +1107,6 @@ static const struct iio_info bmc150_accel_info_fifo = {
|
|||
.validate_trigger = bmc150_accel_validate_trigger,
|
||||
.hwfifo_set_watermark = bmc150_accel_set_watermark,
|
||||
.hwfifo_flush_to_buffer = bmc150_accel_fifo_flush,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const unsigned long bmc150_accel_scan_masks[] = {
|
||||
|
@ -1200,7 +1198,6 @@ static int bmc150_accel_trigger_set_state(struct iio_trigger *trig,
|
|||
static const struct iio_trigger_ops bmc150_accel_trigger_ops = {
|
||||
.set_trigger_state = bmc150_accel_trigger_set_state,
|
||||
.try_reenable = bmc150_accel_trig_try_reen,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
|
||||
|
|
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
* Driver for older Chrome OS EC accelerometer
|
||||
*
|
||||
* Copyright 2017 Google, Inc
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* This driver uses the memory mapper cros-ec interface to communicate
|
||||
* with the Chrome OS EC about accelerometer data.
|
||||
* Accelerometer access is presented through iio sysfs.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
#include <linux/iio/triggered_buffer.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/cros_ec.h>
|
||||
#include <linux/mfd/cros_ec_commands.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define DRV_NAME "cros-ec-accel-legacy"
|
||||
|
||||
/*
|
||||
* Sensor scale hard coded at 10 bits per g, computed as:
|
||||
* g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2
|
||||
*/
|
||||
#define ACCEL_LEGACY_NSCALE 9586168
|
||||
|
||||
/* Indices for EC sensor values. */
|
||||
enum {
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
MAX_AXIS,
|
||||
};
|
||||
|
||||
/* State data for cros_ec_accel_legacy iio driver. */
|
||||
struct cros_ec_accel_legacy_state {
|
||||
struct cros_ec_device *ec;
|
||||
|
||||
/*
|
||||
* Array holding data from a single capture. 2 bytes per channel
|
||||
* for the 3 channels plus the timestamp which is always last and
|
||||
* 8-bytes aligned.
|
||||
*/
|
||||
s16 capture_data[8];
|
||||
s8 sign[MAX_AXIS];
|
||||
u8 sensor_num;
|
||||
};
|
||||
|
||||
static int ec_cmd_read_u8(struct cros_ec_device *ec, unsigned int offset,
|
||||
u8 *dest)
|
||||
{
|
||||
return ec->cmd_readmem(ec, offset, 1, dest);
|
||||
}
|
||||
|
||||
static int ec_cmd_read_u16(struct cros_ec_device *ec, unsigned int offset,
|
||||
u16 *dest)
|
||||
{
|
||||
__le16 tmp;
|
||||
int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
|
||||
|
||||
*dest = le16_to_cpu(tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_ec_until_not_busy() - Read from EC status byte until it reads not busy.
|
||||
* @st: Pointer to state information for device.
|
||||
*
|
||||
* This function reads EC status until its busy bit gets cleared. It does not
|
||||
* wait indefinitely and returns -EIO if the EC status is still busy after a
|
||||
* few hundreds milliseconds.
|
||||
*
|
||||
* Return: 8-bit status if ok, -EIO on error
|
||||
*/
|
||||
static int read_ec_until_not_busy(struct cros_ec_accel_legacy_state *st)
|
||||
{
|
||||
struct cros_ec_device *ec = st->ec;
|
||||
u8 status;
|
||||
int attempts = 0;
|
||||
|
||||
ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
|
||||
while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
|
||||
/* Give up after enough attempts, return error. */
|
||||
if (attempts++ >= 50)
|
||||
return -EIO;
|
||||
|
||||
/* Small delay every so often. */
|
||||
if (attempts % 5 == 0)
|
||||
msleep(25);
|
||||
|
||||
ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_ec_accel_data_unsafe() - Read acceleration data from EC shared memory.
|
||||
* @st: Pointer to state information for device.
|
||||
* @scan_mask: Bitmap of the sensor indices to scan.
|
||||
* @data: Location to store data.
|
||||
*
|
||||
* This is the unsafe function for reading the EC data. It does not guarantee
|
||||
* that the EC will not modify the data as it is being read in.
|
||||
*/
|
||||
static void read_ec_accel_data_unsafe(struct cros_ec_accel_legacy_state *st,
|
||||
unsigned long scan_mask, s16 *data)
|
||||
{
|
||||
int i = 0;
|
||||
int num_enabled = bitmap_weight(&scan_mask, MAX_AXIS);
|
||||
|
||||
/* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
|
||||
while (num_enabled--) {
|
||||
i = find_next_bit(&scan_mask, MAX_AXIS, i);
|
||||
ec_cmd_read_u16(st->ec,
|
||||
EC_MEMMAP_ACC_DATA +
|
||||
sizeof(s16) *
|
||||
(1 + i + st->sensor_num * MAX_AXIS),
|
||||
data);
|
||||
*data *= st->sign[i];
|
||||
i++;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* read_ec_accel_data() - Read acceleration data from EC shared memory.
|
||||
* @st: Pointer to state information for device.
|
||||
* @scan_mask: Bitmap of the sensor indices to scan.
|
||||
* @data: Location to store data.
|
||||
*
|
||||
* This is the safe function for reading the EC data. It guarantees that
|
||||
* the data sampled was not modified by the EC while being read.
|
||||
*
|
||||
* Return: 0 if ok, -ve on error
|
||||
*/
|
||||
static int read_ec_accel_data(struct cros_ec_accel_legacy_state *st,
|
||||
unsigned long scan_mask, s16 *data)
|
||||
{
|
||||
u8 samp_id = 0xff;
|
||||
u8 status = 0;
|
||||
int ret;
|
||||
int attempts = 0;
|
||||
|
||||
/*
|
||||
* Continually read all data from EC until the status byte after
|
||||
* all reads reflects that the EC is not busy and the sample id
|
||||
* matches the sample id from before all reads. This guarantees
|
||||
* that data read in was not modified by the EC while reading.
|
||||
*/
|
||||
while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
|
||||
EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
|
||||
/* If we have tried to read too many times, return error. */
|
||||
if (attempts++ >= 5)
|
||||
return -EIO;
|
||||
|
||||
/* Read status byte until EC is not busy. */
|
||||
ret = read_ec_until_not_busy(st);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
status = ret;
|
||||
|
||||
/*
|
||||
* Store the current sample id so that we can compare to the
|
||||
* sample id after reading the data.
|
||||
*/
|
||||
samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
|
||||
|
||||
/* Read all EC data, format it, and store it into data. */
|
||||
read_ec_accel_data_unsafe(st, scan_mask, data);
|
||||
|
||||
/* Read status byte. */
|
||||
ec_cmd_read_u8(st->ec, EC_MEMMAP_ACC_STATUS, &status);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
|
||||
s16 data = 0;
|
||||
int ret = IIO_VAL_INT;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
ret = read_ec_accel_data(st, (1 << chan->scan_index), &data);
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = data;
|
||||
return IIO_VAL_INT;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = 0;
|
||||
*val2 = ACCEL_LEGACY_NSCALE;
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
case IIO_CHAN_INFO_CALIBBIAS:
|
||||
/* Calibration not supported. */
|
||||
*val = 0;
|
||||
return IIO_VAL_INT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int cros_ec_accel_legacy_write(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val, int val2, long mask)
|
||||
{
|
||||
/*
|
||||
* Do nothing but don't return an error code to allow calibration
|
||||
* script to work.
|
||||
*/
|
||||
if (mask == IIO_CHAN_INFO_CALIBBIAS)
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct iio_info cros_ec_accel_legacy_info = {
|
||||
.read_raw = &cros_ec_accel_legacy_read,
|
||||
.write_raw = &cros_ec_accel_legacy_write,
|
||||
};
|
||||
|
||||
/**
|
||||
* cros_ec_accel_legacy_capture() - The trigger handler function
|
||||
* @irq: The interrupt number.
|
||||
* @p: Private data - always a pointer to the poll func.
|
||||
*
|
||||
* On a trigger event occurring, if the pollfunc is attached then this
|
||||
* handler is called as a threaded interrupt (and hence may sleep). It
|
||||
* is responsible for grabbing data from the device and pushing it into
|
||||
* the associated buffer.
|
||||
*
|
||||
* Return: IRQ_HANDLED
|
||||
*/
|
||||
static irqreturn_t cros_ec_accel_legacy_capture(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *indio_dev = pf->indio_dev;
|
||||
struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
|
||||
|
||||
/* Clear capture data. */
|
||||
memset(st->capture_data, 0, sizeof(st->capture_data));
|
||||
|
||||
/*
|
||||
* Read data based on which channels are enabled in scan mask. Note
|
||||
* that on a capture we are always reading the calibrated data.
|
||||
*/
|
||||
read_ec_accel_data(st, *indio_dev->active_scan_mask, st->capture_data);
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, (void *)st->capture_data,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
/*
|
||||
* Tell the core we are done with this trigger and ready for the
|
||||
* next one.
|
||||
*/
|
||||
iio_trigger_notify_done(indio_dev->trig);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static char *cros_ec_accel_legacy_loc_strings[] = {
|
||||
[MOTIONSENSE_LOC_BASE] = "base",
|
||||
[MOTIONSENSE_LOC_LID] = "lid",
|
||||
[MOTIONSENSE_LOC_MAX] = "unknown",
|
||||
};
|
||||
|
||||
static ssize_t cros_ec_accel_legacy_loc(struct iio_dev *indio_dev,
|
||||
uintptr_t private,
|
||||
const struct iio_chan_spec *chan,
|
||||
char *buf)
|
||||
{
|
||||
struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
cros_ec_accel_legacy_loc_strings[st->sensor_num +
|
||||
MOTIONSENSE_LOC_BASE]);
|
||||
}
|
||||
|
||||
static ssize_t cros_ec_accel_legacy_id(struct iio_dev *indio_dev,
|
||||
uintptr_t private,
|
||||
const struct iio_chan_spec *chan,
|
||||
char *buf)
|
||||
{
|
||||
struct cros_ec_accel_legacy_state *st = iio_priv(indio_dev);
|
||||
|
||||
return sprintf(buf, "%d\n", st->sensor_num);
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec_ext_info cros_ec_accel_legacy_ext_info[] = {
|
||||
{
|
||||
.name = "id",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.read = cros_ec_accel_legacy_id,
|
||||
},
|
||||
{
|
||||
.name = "location",
|
||||
.shared = IIO_SHARED_BY_ALL,
|
||||
.read = cros_ec_accel_legacy_loc,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
#define CROS_EC_ACCEL_LEGACY_CHAN(_axis) \
|
||||
{ \
|
||||
.type = IIO_ACCEL, \
|
||||
.channel2 = IIO_MOD_X + (_axis), \
|
||||
.modified = 1, \
|
||||
.info_mask_separate = \
|
||||
BIT(IIO_CHAN_INFO_RAW) | \
|
||||
BIT(IIO_CHAN_INFO_SCALE) | \
|
||||
BIT(IIO_CHAN_INFO_CALIBBIAS), \
|
||||
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.ext_info = cros_ec_accel_legacy_ext_info, \
|
||||
.scan_type = { \
|
||||
.sign = 's', \
|
||||
.realbits = 16, \
|
||||
.storagebits = 16, \
|
||||
}, \
|
||||
} \
|
||||
|
||||
static struct iio_chan_spec ec_accel_channels[] = {
|
||||
CROS_EC_ACCEL_LEGACY_CHAN(X),
|
||||
CROS_EC_ACCEL_LEGACY_CHAN(Y),
|
||||
CROS_EC_ACCEL_LEGACY_CHAN(Z),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(MAX_AXIS)
|
||||
};
|
||||
|
||||
static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cros_ec_dev *ec = dev_get_drvdata(dev->parent);
|
||||
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
|
||||
struct iio_dev *indio_dev;
|
||||
struct cros_ec_accel_legacy_state *state;
|
||||
int ret, i;
|
||||
|
||||
if (!ec || !ec->ec_dev) {
|
||||
dev_warn(&pdev->dev, "No EC device found.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ec->ec_dev->cmd_readmem) {
|
||||
dev_warn(&pdev->dev, "EC does not support direct reads.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, indio_dev);
|
||||
state = iio_priv(indio_dev);
|
||||
state->ec = ec->ec_dev;
|
||||
state->sensor_num = sensor_platform->sensor_num;
|
||||
|
||||
indio_dev->dev.parent = dev;
|
||||
indio_dev->name = pdev->name;
|
||||
indio_dev->channels = ec_accel_channels;
|
||||
/*
|
||||
* Present the channel using HTML5 standard:
|
||||
* need to invert X and Y and invert some lid axis.
|
||||
*/
|
||||
for (i = X ; i < MAX_AXIS; i++) {
|
||||
switch (i) {
|
||||
case X:
|
||||
ec_accel_channels[X].scan_index = Y;
|
||||
case Y:
|
||||
ec_accel_channels[Y].scan_index = X;
|
||||
case Z:
|
||||
ec_accel_channels[Z].scan_index = Z;
|
||||
}
|
||||
if (state->sensor_num == MOTIONSENSE_LOC_LID && i != Y)
|
||||
state->sign[i] = -1;
|
||||
else
|
||||
state->sign[i] = 1;
|
||||
}
|
||||
indio_dev->num_channels = ARRAY_SIZE(ec_accel_channels);
|
||||
indio_dev->dev.parent = &pdev->dev;
|
||||
indio_dev->info = &cros_ec_accel_legacy_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
|
||||
cros_ec_accel_legacy_capture,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_iio_device_register(dev, indio_dev);
|
||||
}
|
||||
|
||||
static struct platform_driver cros_ec_accel_platform_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.probe = cros_ec_accel_legacy_probe,
|
||||
};
|
||||
module_platform_driver(cros_ec_accel_platform_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ChromeOS EC legacy accelerometer driver");
|
||||
MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
|
@ -88,7 +88,6 @@ static int da280_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info da280_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = da280_read_raw,
|
||||
};
|
||||
|
||||
|
|
|
@ -212,7 +212,6 @@ static int da311_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info da311_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = da311_read_raw,
|
||||
};
|
||||
|
||||
|
|
|
@ -124,7 +124,6 @@ static int dmard06_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info dmard06_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = dmard06_read_raw,
|
||||
};
|
||||
|
||||
|
|
|
@ -93,7 +93,6 @@ static int dmard09_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info dmard09_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = dmard09_read_raw,
|
||||
};
|
||||
|
||||
|
|
|
@ -170,7 +170,6 @@ static int dmard10_read_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info dmard10_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = dmard10_read_raw,
|
||||
};
|
||||
|
||||
|
|
|
@ -225,7 +225,6 @@ static int accel_3d_write_raw(struct iio_dev *indio_dev,
|
|||
}
|
||||
|
||||
static const struct iio_info accel_3d_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &accel_3d_read_raw,
|
||||
.write_raw = &accel_3d_write_raw,
|
||||
};
|
||||
|
|
|
@ -34,6 +34,13 @@
|
|||
#define KXCJK1013_DRV_NAME "kxcjk1013"
|
||||
#define KXCJK1013_IRQ_NAME "kxcjk1013_event"
|
||||
|
||||
#define KXTF9_REG_HP_XOUT_L 0x00
|
||||
#define KXTF9_REG_HP_XOUT_H 0x01
|
||||
#define KXTF9_REG_HP_YOUT_L 0x02
|
||||
#define KXTF9_REG_HP_YOUT_H 0x03
|
||||
#define KXTF9_REG_HP_ZOUT_L 0x04
|
||||
#define KXTF9_REG_HP_ZOUT_H 0x05
|
||||
|
||||
#define KXCJK1013_REG_XOUT_L 0x06
|
||||
/*
|
||||
* From low byte X axis register, all the other addresses of Y and Z can be
|
||||
|
@ -48,17 +55,33 @@
|
|||
|
||||
#define KXCJK1013_REG_DCST_RESP 0x0C
|
||||
#define KXCJK1013_REG_WHO_AM_I 0x0F
|
||||
#define KXCJK1013_REG_INT_SRC1 0x16
|
||||
#define KXTF9_REG_TILT_POS_CUR 0x10
|
||||
#define KXTF9_REG_TILT_POS_PREV 0x11
|
||||
#define KXTF9_REG_INT_SRC1 0x15
|
||||
#define KXCJK1013_REG_INT_SRC1 0x16 /* compatible, but called INT_SRC2 in KXTF9 ds */
|
||||
#define KXCJK1013_REG_INT_SRC2 0x17
|
||||
#define KXCJK1013_REG_STATUS_REG 0x18
|
||||
#define KXCJK1013_REG_INT_REL 0x1A
|
||||
#define KXCJK1013_REG_CTRL1 0x1B
|
||||
#define KXCJK1013_REG_CTRL2 0x1D
|
||||
#define KXTF9_REG_CTRL2 0x1C
|
||||
#define KXCJK1013_REG_CTRL2 0x1D /* mostly compatible, CTRL_REG3 in KTXF9 ds */
|
||||
#define KXCJK1013_REG_INT_CTRL1 0x1E
|
||||
#define KXCJK1013_REG_INT_CTRL2 0x1F
|
||||
#define KXTF9_REG_INT_CTRL3 0x20
|
||||
#define KXCJK1013_REG_DATA_CTRL 0x21
|
||||
#define KXTF9_REG_TILT_TIMER 0x28
|
||||
#define KXCJK1013_REG_WAKE_TIMER 0x29
|
||||
#define KXTF9_REG_TDT_TIMER 0x2B
|
||||
#define KXTF9_REG_TDT_THRESH_H 0x2C
|
||||
#define KXTF9_REG_TDT_THRESH_L 0x2D
|
||||
#define KXTF9_REG_TDT_TAP_TIMER 0x2E
|
||||
#define KXTF9_REG_TDT_TOTAL_TIMER 0x2F
|
||||
#define KXTF9_REG_TDT_LATENCY_TIMER 0x30
|
||||
#define KXTF9_REG_TDT_WINDOW_TIMER 0x31
|
||||
#define KXCJK1013_REG_SELF_TEST 0x3A
|
||||
#define KXTF9_REG_WAKE_THRESH 0x5A
|
||||
#define KXTF9_REG_TILT_ANGLE 0x5C
|
||||
#define KXTF9_REG_HYST_SET 0x5F
|
||||
#define KXCJK1013_REG_WAKE_THRES 0x6A
|
||||
|
||||
#define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7)
|
||||
|
@ -67,14 +90,33 @@
|
|||
#define KXCJK1013_REG_CTRL1_BIT_GSEL1 BIT(4)
|
||||
#define KXCJK1013_REG_CTRL1_BIT_GSEL0 BIT(3)
|
||||
#define KXCJK1013_REG_CTRL1_BIT_WUFE BIT(1)
|
||||
#define KXCJK1013_REG_INT_REG1_BIT_IEA BIT(4)
|
||||
#define KXCJK1013_REG_INT_REG1_BIT_IEN BIT(5)
|
||||
|
||||
#define KXCJK1013_REG_INT_CTRL1_BIT_IEU BIT(2) /* KXTF9 */
|
||||
#define KXCJK1013_REG_INT_CTRL1_BIT_IEL BIT(3)
|
||||
#define KXCJK1013_REG_INT_CTRL1_BIT_IEA BIT(4)
|
||||
#define KXCJK1013_REG_INT_CTRL1_BIT_IEN BIT(5)
|
||||
|
||||
#define KXTF9_REG_TILT_BIT_LEFT_EDGE BIT(5)
|
||||
#define KXTF9_REG_TILT_BIT_RIGHT_EDGE BIT(4)
|
||||
#define KXTF9_REG_TILT_BIT_LOWER_EDGE BIT(3)
|
||||
#define KXTF9_REG_TILT_BIT_UPPER_EDGE BIT(2)
|
||||
#define KXTF9_REG_TILT_BIT_FACE_DOWN BIT(1)
|
||||
#define KXTF9_REG_TILT_BIT_FACE_UP BIT(0)
|
||||
|
||||
#define KXCJK1013_DATA_MASK_12_BIT 0x0FFF
|
||||
#define KXCJK1013_MAX_STARTUP_TIME_US 100000
|
||||
|
||||
#define KXCJK1013_SLEEP_DELAY_MS 2000
|
||||
|
||||
#define KXCJK1013_REG_INT_SRC1_BIT_TPS BIT(0) /* KXTF9 */
|
||||
#define KXCJK1013_REG_INT_SRC1_BIT_WUFS BIT(1)
|
||||
#define KXCJK1013_REG_INT_SRC1_MASK_TDTS (BIT(2) | BIT(3)) /* KXTF9 */
|
||||
#define KXCJK1013_REG_INT_SRC1_TAP_NONE 0
|
||||
#define KXCJK1013_REG_INT_SRC1_TAP_SINGLE BIT(2)
|
||||
#define KXCJK1013_REG_INT_SRC1_TAP_DOUBLE BIT(3)
|
||||
#define KXCJK1013_REG_INT_SRC1_BIT_DRDY BIT(4)
|
||||
|
||||
/* KXCJK: INT_SOURCE2: motion detect, KXTF9: INT_SRC_REG1: tap detect */
|
||||
#define KXCJK1013_REG_INT_SRC2_BIT_ZP BIT(0)
|
||||
#define KXCJK1013_REG_INT_SRC2_BIT_ZN BIT(1)
|
||||
#define KXCJK1013_REG_INT_SRC2_BIT_YP BIT(2)
|
||||
|
@ -88,6 +130,7 @@ enum kx_chipset {
|
|||
KXCJK1013,
|
||||
KXCJ91008,
|
||||
KXTJ21009,
|
||||
KXTF9,
|
||||
KX_MAX_CHIPS /* this must be last */
|
||||
};
|
||||
|
||||
|
@ -128,15 +171,42 @@ enum kxcjk1013_range {
|
|||
KXCJK1013_RANGE_8G,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
struct kx_odr_map {
|
||||
int val;
|
||||
int val2;
|
||||
int odr_bits;
|
||||
} samp_freq_table[] = { {0, 781000, 0x08}, {1, 563000, 0x09},
|
||||
{3, 125000, 0x0A}, {6, 250000, 0x0B}, {12, 500000, 0},
|
||||
{25, 0, 0x01}, {50, 0, 0x02}, {100, 0, 0x03},
|
||||
{200, 0, 0x04}, {400, 0, 0x05}, {800, 0, 0x06},
|
||||
{1600, 0, 0x07} };
|
||||
int wuf_bits;
|
||||
};
|
||||
|
||||
static const struct kx_odr_map samp_freq_table[] = {
|
||||
{ 0, 781000, 0x08, 0x00 },
|
||||
{ 1, 563000, 0x09, 0x01 },
|
||||
{ 3, 125000, 0x0A, 0x02 },
|
||||
{ 6, 250000, 0x0B, 0x03 },
|
||||
{ 12, 500000, 0x00, 0x04 },
|
||||
{ 25, 0, 0x01, 0x05 },
|
||||
{ 50, 0, 0x02, 0x06 },
|
||||
{ 100, 0, 0x03, 0x06 },
|
||||
{ 200, 0, 0x04, 0x06 },
|
||||
{ 400, 0, 0x05, 0x06 },
|
||||
{ 800, 0, 0x06, 0x06 },
|
||||
{ 1600, 0, 0x07, 0x06 },
|
||||
};
|
||||
|
||||
static const char *const kxcjk1013_samp_freq_avail =
|
||||
"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600";
|
||||
|
||||
static const struct kx_odr_map kxtf9_samp_freq_table[] = {
|
||||
{ 25, 0, 0x01, 0x00 },
|
||||
{ 50, 0, 0x02, 0x01 },
|
||||
{ 100, 0, 0x03, 0x01 },
|
||||
{ 200, 0, 0x04, 0x01 },
|
||||
{ 400, 0, 0x05, 0x01 },
|
||||
{ 800, 0, 0x06, 0x01 },
|
||||
};
|
||||
|
||||
static const char *const kxtf9_samp_freq_avail =
|
||||
"25 50 100 200 400 800";
|
||||
|
||||
/* Refer to section 4 of the specification */
|
||||
static const struct {
|
||||
|
@ -188,6 +258,15 @@ static const struct {
|
|||
{0x06, 3000},
|
||||
{0x07, 2000},
|
||||
},
|
||||
/* KXTF9 */
|
||||
{
|
||||
{0x01, 81000},
|
||||
{0x02, 41000},
|
||||
{0x03, 21000},
|
||||
{0x04, 11000},
|
||||
{0x05, 5100},
|
||||
{0x06, 2700},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct {
|
||||
|
@ -198,23 +277,6 @@ static const struct {
|
|||
{19163, 1, 0},
|
||||
{38326, 0, 1} };
|
||||
|
||||
static const struct {
|
||||
int val;
|
||||
int val2;
|
||||
int odr_bits;
|
||||
} wake_odr_data_rate_table[] = { {0, 781000, 0x00},
|
||||
{1, 563000, 0x01},
|
||||
{3, 125000, 0x02},
|
||||
{6, 250000, 0x03},
|
||||
{12, 500000, 0x04},
|
||||
{25, 0, 0x05},
|
||||
{50, 0, 0x06},
|
||||
{100, 0, 0x06},
|
||||
{200, 0, 0x06},
|
||||
{400, 0, 0x06},
|
||||
{800, 0, 0x06},
|
||||
{1600, 0, 0x06} };
|
||||
|
||||
static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
|
||||
enum kxcjk1013_mode mode)
|
||||
{
|
||||
|
@ -341,9 +403,9 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
|
|||
}
|
||||
|
||||
if (data->active_high_intr)
|
||||
ret |= KXCJK1013_REG_INT_REG1_BIT_IEA;
|
||||
ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEA;
|
||||
else
|
||||
ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEA;
|
||||
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
|
||||
ret);
|
||||
|
@ -401,7 +463,7 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
|
|||
|
||||
static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
|
||||
{
|
||||
int ret;
|
||||
int waketh_reg, ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
KXCJK1013_REG_WAKE_TIMER,
|
||||
|
@ -412,8 +474,9 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
KXCJK1013_REG_WAKE_THRES,
|
||||
waketh_reg = data->chipset == KXTF9 ?
|
||||
KXTF9_REG_WAKE_THRESH : KXCJK1013_REG_WAKE_THRES;
|
||||
ret = i2c_smbus_write_byte_data(data->client, waketh_reg,
|
||||
data->wake_thres);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error writing reg_wake_thres\n");
|
||||
|
@ -449,9 +512,9 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
|
|||
}
|
||||
|
||||
if (status)
|
||||
ret |= KXCJK1013_REG_INT_REG1_BIT_IEN;
|
||||
ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN;
|
||||
else
|
||||
ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEN;
|
||||
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
|
||||
ret);
|
||||
|
@ -509,9 +572,9 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
|
|||
}
|
||||
|
||||
if (status)
|
||||
ret |= KXCJK1013_REG_INT_REG1_BIT_IEN;
|
||||
ret |= KXCJK1013_REG_INT_CTRL1_BIT_IEN;
|
||||
else
|
||||
ret &= ~KXCJK1013_REG_INT_REG1_BIT_IEN;
|
||||
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_INT_CTRL1,
|
||||
ret);
|
||||
|
@ -547,28 +610,30 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kxcjk1013_convert_freq_to_bit(int val, int val2)
|
||||
static const struct kx_odr_map *kxcjk1013_find_odr_value(
|
||||
const struct kx_odr_map *map, size_t map_size, int val, int val2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) {
|
||||
if (samp_freq_table[i].val == val &&
|
||||
samp_freq_table[i].val2 == val2) {
|
||||
return samp_freq_table[i].odr_bits;
|
||||
}
|
||||
for (i = 0; i < map_size; ++i) {
|
||||
if (map[i].val == val && map[i].val2 == val2)
|
||||
return &map[i];
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
static int kxcjk1013_convert_wake_odr_to_bit(int val, int val2)
|
||||
static int kxcjk1013_convert_odr_value(const struct kx_odr_map *map,
|
||||
size_t map_size, int odr_bits,
|
||||
int *val, int *val2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(wake_odr_data_rate_table); ++i) {
|
||||
if (wake_odr_data_rate_table[i].val == val &&
|
||||
wake_odr_data_rate_table[i].val2 == val2) {
|
||||
return wake_odr_data_rate_table[i].odr_bits;
|
||||
for (i = 0; i < map_size; ++i) {
|
||||
if (map[i].odr_bits == odr_bits) {
|
||||
*val = map[i].val;
|
||||
*val2 = map[i].val2;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -578,16 +643,24 @@ static int kxcjk1013_convert_wake_odr_to_bit(int val, int val2)
|
|||
static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
|
||||
{
|
||||
int ret;
|
||||
int odr_bits;
|
||||
enum kxcjk1013_mode store_mode;
|
||||
const struct kx_odr_map *odr_setting;
|
||||
|
||||
ret = kxcjk1013_get_mode(data, &store_mode);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
odr_bits = kxcjk1013_convert_freq_to_bit(val, val2);
|
||||
if (odr_bits < 0)
|
||||
return odr_bits;
|
||||
if (data->chipset == KXTF9)
|
||||
odr_setting = kxcjk1013_find_odr_value(kxtf9_samp_freq_table,
|
||||
ARRAY_SIZE(kxtf9_samp_freq_table),
|
||||
val, val2);
|
||||
else
|
||||
odr_setting = kxcjk1013_find_odr_value(samp_freq_table,
|
||||
ARRAY_SIZE(samp_freq_table),
|
||||
val, val2);
|
||||
|
||||
if (IS_ERR(odr_setting))
|
||||
return PTR_ERR(odr_setting);
|
||||
|
||||
/* To change ODR, the chip must be set to STANDBY as per spec */
|
||||
ret = kxcjk1013_set_mode(data, STANDBY);
|
||||
|
@ -595,20 +668,16 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
|
|||
return ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_DATA_CTRL,
|
||||
odr_bits);
|
||||
odr_setting->odr_bits);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error writing data_ctrl\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->odr_bits = odr_bits;
|
||||
|
||||
odr_bits = kxcjk1013_convert_wake_odr_to_bit(val, val2);
|
||||
if (odr_bits < 0)
|
||||
return odr_bits;
|
||||
data->odr_bits = odr_setting->odr_bits;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, KXCJK1013_REG_CTRL2,
|
||||
odr_bits);
|
||||
odr_setting->wuf_bits);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
|
||||
return ret;
|
||||
|
@ -625,17 +694,14 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
|
|||
|
||||
static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(samp_freq_table); ++i) {
|
||||
if (samp_freq_table[i].odr_bits == data->odr_bits) {
|
||||
*val = samp_freq_table[i].val;
|
||||
*val2 = samp_freq_table[i].val2;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
if (data->chipset == KXTF9)
|
||||
return kxcjk1013_convert_odr_value(kxtf9_samp_freq_table,
|
||||
ARRAY_SIZE(kxtf9_samp_freq_table),
|
||||
data->odr_bits, val, val2);
|
||||
else
|
||||
return kxcjk1013_convert_odr_value(samp_freq_table,
|
||||
ARRAY_SIZE(samp_freq_table),
|
||||
data->odr_bits, val, val2);
|
||||
}
|
||||
|
||||
static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis)
|
||||
|
@ -886,13 +952,29 @@ static int kxcjk1013_buffer_postdisable(struct iio_dev *indio_dev)
|
|||
return kxcjk1013_set_power_state(data, false);
|
||||
}
|
||||
|
||||
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(
|
||||
"0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600");
|
||||
static ssize_t kxcjk1013_get_samp_freq_avail(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct kxcjk1013_data *data = iio_priv(indio_dev);
|
||||
const char *str;
|
||||
|
||||
if (data->chipset == KXTF9)
|
||||
str = kxtf9_samp_freq_avail;
|
||||
else
|
||||
str = kxcjk1013_samp_freq_avail;
|
||||
|
||||
return sprintf(buf, "%s\n", str);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(in_accel_sampling_frequency_available, S_IRUGO,
|
||||
kxcjk1013_get_samp_freq_avail, NULL, 0);
|
||||
|
||||
static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019163 0.038326");
|
||||
|
||||
static struct attribute *kxcjk1013_attributes[] = {
|
||||
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
|
||||
&iio_dev_attr_in_accel_sampling_frequency_available.dev_attr.attr,
|
||||
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
@ -950,7 +1032,6 @@ static const struct iio_info kxcjk1013_info = {
|
|||
.write_event_value = kxcjk1013_write_event,
|
||||
.write_event_config = kxcjk1013_write_event_config,
|
||||
.read_event_config = kxcjk1013_read_event_config,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0};
|
||||
|
@ -1036,9 +1117,74 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
|
|||
static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
|
||||
.set_trigger_state = kxcjk1013_data_rdy_trigger_set_state,
|
||||
.try_reenable = kxcjk1013_trig_try_reen,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct kxcjk1013_data *data = iio_priv(indio_dev);
|
||||
|
||||
int ret = i2c_smbus_read_byte_data(data->client,
|
||||
KXCJK1013_REG_INT_SRC2);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev, "Error reading reg_int_src2\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_XN)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_X,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
data->timestamp);
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_XP)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_X,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
data->timestamp);
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_YN)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Y,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
data->timestamp);
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_YP)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Y,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
data->timestamp);
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZN)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Z,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
data->timestamp);
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZP)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Z,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
data->timestamp);
|
||||
}
|
||||
|
||||
static irqreturn_t kxcjk1013_event_handler(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *indio_dev = private;
|
||||
|
@ -1051,66 +1197,17 @@ static irqreturn_t kxcjk1013_event_handler(int irq, void *private)
|
|||
goto ack_intr;
|
||||
}
|
||||
|
||||
if (ret & 0x02) {
|
||||
ret = i2c_smbus_read_byte_data(data->client,
|
||||
KXCJK1013_REG_INT_SRC2);
|
||||
if (ret < 0) {
|
||||
dev_err(&data->client->dev,
|
||||
"Error reading reg_int_src2\n");
|
||||
goto ack_intr;
|
||||
}
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_XN)
|
||||
if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) {
|
||||
if (data->chipset == KXTF9)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_X,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
data->timestamp);
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_XP)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_X,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
data->timestamp);
|
||||
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_YN)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Y,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
data->timestamp);
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_YP)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Y,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
data->timestamp);
|
||||
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZN)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Z,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_FALLING),
|
||||
data->timestamp);
|
||||
if (ret & KXCJK1013_REG_INT_SRC2_BIT_ZP)
|
||||
iio_push_event(indio_dev,
|
||||
IIO_MOD_EVENT_CODE(IIO_ACCEL,
|
||||
0,
|
||||
IIO_MOD_Z,
|
||||
IIO_MOD_X_AND_Y_AND_Z,
|
||||
IIO_EV_TYPE_THRESH,
|
||||
IIO_EV_DIR_RISING),
|
||||
data->timestamp);
|
||||
else
|
||||
kxcjk1013_report_motion_event(indio_dev);
|
||||
}
|
||||
|
||||
ack_intr:
|
||||
|
@ -1403,6 +1500,7 @@ static const struct i2c_device_id kxcjk1013_id[] = {
|
|||
{"kxcjk1013", KXCJK1013},
|
||||
{"kxcj91008", KXCJ91008},
|
||||
{"kxtj21009", KXTJ21009},
|
||||
{"kxtf9", KXTF9},
|
||||
{"SMO8500", KXCJ91008},
|
||||
{}
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue