mirror of https://gitee.com/openkylin/linux.git
ASoC: Updates for v4.6
The main thing in terms of the core this time around has been some additional framework work for dynamic topologies (though we *still* don't appear to have a stable ABI for the topology code, it's probably worth considering if this will ever happen...). Otherwise the work has almost all been in the drivers: - HDMI support for Sky Lake, along with other fixes and enhancements for the Intel drivers. - Lots of improvements to the Renesas drivers. - Capture support for Qualcomm drivers. - Support for TI DaVinci DRA7xxx devices. - New machine drivers for Freescale systems with Cirrus CODECs, Mediatek systems with RT5650 CODECs. - New CPU drivers for Allwinner S/PDIF controllers - New CODEC drivers for Maxim MAX9867 and MAX98926 and Realtek RT5514. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJW5qP+AAoJECTWi3JdVIfQJhAH/RKv268gjE07uJ8jeGAT7uY4 XM19VmUl7ZOlphctfr/I+1hRwo+mgGN4LSfKnXxsPk9Uq/WJUok4D7MjDN33jeX/ heK9WAO8zXkgi9n2lhGI/z9uE76kPA/Qw0aEYcbmA6bDc4GF3AKphnByh6kDShtE BfblofsFaDywA09XQ2lh3wW0rZtJ51tQUeOi35UADyEPzQetzN+xiY85Bkia5BEt Yjp37nLJET8Gk0r9snE2MpACUkEyw7CiPXCjkK47npia41LVnTarZAq5+JmfKygg YV2EnC3AFYthhjZPfmO1usI2vJVwkN40nGrKipH2QX08TanK8r2qiTsmGADNX4E= =0/1R -----END PGP SIGNATURE----- Merge tag 'asoc-v4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus ASoC: Updates for v4.6 The main thing in terms of the core this time around has been some additional framework work for dynamic topologies (though we *still* don't appear to have a stable ABI for the topology code, it's probably worth considering if this will ever happen...). Otherwise the work has almost all been in the drivers: - HDMI support for Sky Lake, along with other fixes and enhancements for the Intel drivers. - Lots of improvements to the Renesas drivers. - Capture support for Qualcomm drivers. - Support for TI DaVinci DRA7xxx devices. - New machine drivers for Freescale systems with Cirrus CODECs, Mediatek systems with RT5650 CODECs. - New CPU drivers for Allwinner S/PDIF controllers - New CODEC drivers for Maxim MAX9867 and MAX98926 and Realtek RT5514.
This commit is contained in:
commit
ca80e26a59
|
@ -56,10 +56,6 @@
|
|||
<entry><constant>MEDIA_ENT_F_CONN_COMPOSITE</constant></entry>
|
||||
<entry>Connector for a RGB composite signal.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_F_CONN_TEST</constant></entry>
|
||||
<entry>Connector for a test generator.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><constant>MEDIA_ENT_F_CAM_SENSOR</constant></entry>
|
||||
<entry>Camera video sensor entity.</entry>
|
||||
|
|
|
@ -5,15 +5,18 @@ Index Device Endianness properties
|
|||
---------------------------------------------------
|
||||
1 BE 'big-endian'
|
||||
2 LE 'little-endian'
|
||||
3 Native 'native-endian'
|
||||
|
||||
For one device driver, which will run in different scenarios above
|
||||
on different SoCs using the devicetree, we need one way to simplify
|
||||
this.
|
||||
|
||||
Required properties:
|
||||
- {big,little}-endian: these are boolean properties, if absent
|
||||
meaning that the CPU and the Device are in the same endianness mode,
|
||||
these properties are for register values and all the buffers only.
|
||||
Optional properties:
|
||||
- {big,little,native}-endian: these are boolean properties, if absent
|
||||
then the implementation will choose a default based on the device
|
||||
being controlled. These properties are for register values and all
|
||||
the buffers only. Native endian means that the CPU and device have
|
||||
the same endianness.
|
||||
|
||||
Examples:
|
||||
Scenario 1 : CPU in LE mode & device in LE mode.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
Analog Devices ADAU1361/ADAU1461/ADAU1761/ADAU1961/ADAU1381/ADAU1781
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Should contain one of the following:
|
||||
"adi,adau1361"
|
||||
"adi,adau1461"
|
||||
"adi,adau1761"
|
||||
"adi,adau1961"
|
||||
"adi,adau1381"
|
||||
"adi,adau1781"
|
||||
|
||||
- reg: The i2c address. Value depends on the state of ADDR0
|
||||
and ADDR1, as wired in hardware.
|
||||
|
||||
Examples:
|
||||
#include <dt-bindings/sound/adau17x1.h>
|
||||
|
||||
i2c_bus {
|
||||
adau1361@38 {
|
||||
compatible = "adi,adau1761";
|
||||
reg = <0x38>;
|
||||
};
|
||||
};
|
|
@ -24,6 +24,9 @@ The compatible list for this generic sound card currently:
|
|||
|
||||
"fsl,imx-audio-cs42888"
|
||||
|
||||
"fsl,imx-audio-cs427x"
|
||||
(compatible with CS4271 and CS4272)
|
||||
|
||||
"fsl,imx-audio-wm8962"
|
||||
(compatible with Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt)
|
||||
|
||||
|
@ -63,6 +66,12 @@ Optional properties:
|
|||
- audio-asrc : The phandle of ASRC. It can be absent if there's no
|
||||
need to add ASRC support via DPCM.
|
||||
|
||||
Optional unless SSI is selected as a CPU DAI:
|
||||
|
||||
- mux-int-port : The internal port of the i.MX audio muxer (AUDMUX)
|
||||
|
||||
- mux-ext-port : The external port of the i.MX audio muxer
|
||||
|
||||
Example:
|
||||
sound-cs42888 {
|
||||
compatible = "fsl,imx-audio-cs42888";
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
max9867 codec
|
||||
|
||||
This device supports I2C mode only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "maxim,max9867"
|
||||
- reg : The chip select number on the I2C bus
|
||||
|
||||
Example:
|
||||
|
||||
&i2c {
|
||||
max9867: max9867@0x18 {
|
||||
compatible = "maxim,max9867";
|
||||
reg = <0x18>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
max98926 audio CODEC
|
||||
|
||||
This device supports I2C.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "maxim,max98926"
|
||||
|
||||
- vmon-slot-no : slot number used to send voltage information
|
||||
or in inteleave mode this will be used as
|
||||
interleave slot.
|
||||
|
||||
- imon-slot-no : slot number used to send current information
|
||||
|
||||
- interleave-mode : When using two MAX98926 in a system it is
|
||||
possible to create ADC data that that will
|
||||
overflow the frame size. Digital Audio Interleave
|
||||
mode provides a means to output VMON and IMON data
|
||||
from two devices on a single DOUT line when running
|
||||
smaller frames sizes such as 32 BCLKS per LRCLK or
|
||||
48 BCLKS per LRCLK.
|
||||
|
||||
- reg : the I2C address of the device for I2C
|
||||
|
||||
Example:
|
||||
|
||||
codec: max98926@1a {
|
||||
compatible = "maxim,max98926";
|
||||
vmon-slot-no = <0>;
|
||||
imon-slot-no = <2>;
|
||||
reg = <0x1a>;
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
MT8173 with RT5650 RT5514 CODECS
|
||||
|
||||
Required properties:
|
||||
- compatible : "mediatek,mt8173-rt5650-rt5514"
|
||||
- mediatek,audio-codec: the phandles of rt5650 and rt5514 codecs
|
||||
- mediatek,platform: the phandle of MT8173 ASoC platform
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "mediatek,mt8173-rt5650-rt5514";
|
||||
mediatek,audio-codec = <&rt5650 &rt5514>;
|
||||
mediatek,platform = <&afe>;
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
MT8173 with RT5650 CODECS
|
||||
|
||||
Required properties:
|
||||
- compatible : "mediatek,mt8173-rt5650"
|
||||
- mediatek,audio-codec: the phandles of rt5650 codecs
|
||||
- mediatek,platform: the phandle of MT8173 ASoC platform
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "mediatek,mt8173-rt5650";
|
||||
mediatek,audio-codec = <&rt5650>;
|
||||
mediatek,platform = <&afe>;
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
Texas Instruments pcm179x DT bindings
|
||||
|
||||
This driver supports the SPI bus.
|
||||
This driver supports both the I2C and SPI bus.
|
||||
|
||||
Required properties:
|
||||
|
||||
|
@ -9,6 +9,11 @@ Required properties:
|
|||
For required properties on SPI, please consult
|
||||
Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
|
||||
Required properties on I2C:
|
||||
|
||||
- reg: the I2C address
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
codec_spi: 1792a@0 {
|
||||
|
@ -16,3 +21,7 @@ Examples:
|
|||
spi-max-frequency = <600000>;
|
||||
};
|
||||
|
||||
codec_i2c: 1792a@4c {
|
||||
compatible = "ti,pcm1792a";
|
||||
reg = <0x4c>;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,337 @@
|
|||
Renesas R-Car sound
|
||||
|
||||
=============================================
|
||||
* Modules
|
||||
=============================================
|
||||
|
||||
Renesas R-Car sound is constructed from below modules
|
||||
(for Gen2 or later)
|
||||
|
||||
SCU : Sampling Rate Converter Unit
|
||||
- SRC : Sampling Rate Converter
|
||||
- CMD
|
||||
- CTU : Channel Transfer Unit
|
||||
- MIX : Mixer
|
||||
- DVC : Digital Volume and Mute Function
|
||||
SSIU : Serial Sound Interface Unit
|
||||
SSI : Serial Sound Interface
|
||||
|
||||
See detail of each module's channels, connection, limitation on datasheet
|
||||
|
||||
=============================================
|
||||
* Multi channel
|
||||
=============================================
|
||||
|
||||
Multi channel is supported by Multi-SSI, or TDM-SSI.
|
||||
|
||||
Multi-SSI : 6ch case, you can use stereo x 3 SSI
|
||||
TDM-SSI : 6ch case, you can use TDM
|
||||
|
||||
=============================================
|
||||
* Enable/Disable each modules
|
||||
=============================================
|
||||
|
||||
See datasheet to check SRC/CTU/MIX/DVC connect-limitation.
|
||||
DT controls enabling/disabling module.
|
||||
${LINUX}/arch/arm/boot/dts/r8a7790-lager.dts can be good example.
|
||||
This is example of
|
||||
|
||||
Playback: [MEM] -> [SRC2] -> [DVC0] -> [SSIU0/SSI0] -> [codec]
|
||||
Capture: [MEM] <- [DVC1] <- [SRC3] <- [SSIU1/SSI1] <- [codec]
|
||||
|
||||
&rcar_sound {
|
||||
...
|
||||
rcar_sound,dai {
|
||||
dai0 {
|
||||
playback = <&ssi0 &src2 &dvc0>;
|
||||
capture = <&ssi1 &src3 &dvc1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
You can use below.
|
||||
${LINUX}/arch/arm/boot/dts/r8a7790.dts can be good example.
|
||||
|
||||
&src0 &ctu00 &mix0 &dvc0 &ssi0
|
||||
&src1 &ctu01 &mix1 &dvc1 &ssi1
|
||||
&src2 &ctu02 &ssi2
|
||||
&src3 &ctu03 &ssi3
|
||||
&src4 &ssi4
|
||||
&src5 &ctu10 &ssi5
|
||||
&src6 &ctu11 &ssi6
|
||||
&src7 &ctu12 &ssi7
|
||||
&src8 &ctu13 &ssi8
|
||||
&src9 &ssi9
|
||||
|
||||
=============================================
|
||||
* SRC (Sampling Rate Converter)
|
||||
=============================================
|
||||
|
||||
[xx]Hz [yy]Hz
|
||||
------> [SRC] ------>
|
||||
|
||||
SRC can convert [xx]Hz to [yy]Hz. Then, it has below 2 modes
|
||||
|
||||
Asynchronous mode: input data / output data are based on different clocks.
|
||||
you can use this mode on Playback / Capture
|
||||
Synchronous mode: input data / output data are based on same clocks.
|
||||
This mode will be used if system doesn't have its input clock,
|
||||
for example digital TV case.
|
||||
you can use this mode on Playback
|
||||
|
||||
------------------
|
||||
** Asynchronous mode
|
||||
------------------
|
||||
|
||||
You need to use "renesas,rsrc-card" sound card for it.
|
||||
example)
|
||||
|
||||
sound {
|
||||
compatible = "renesas,rsrc-card";
|
||||
...
|
||||
/*
|
||||
* SRC Asynchronous mode setting
|
||||
* Playback:
|
||||
* All input data will be converted to 48kHz
|
||||
* Capture:
|
||||
* Inputed 48kHz data will be converted to
|
||||
* system specified Hz
|
||||
*/
|
||||
convert-rate = <48000>;
|
||||
...
|
||||
cpu {
|
||||
sound-dai = <&rcar_sound>;
|
||||
};
|
||||
codec {
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
------------------
|
||||
** Synchronous mode
|
||||
------------------
|
||||
|
||||
> amixer set "SRC Out Rate" on
|
||||
> aplay xxxx.wav
|
||||
> amixer set "SRC Out Rate" 48000
|
||||
> amixer set "SRC Out Rate" 44100
|
||||
|
||||
=============================================
|
||||
* CTU (Channel Transfer Unit)
|
||||
=============================================
|
||||
|
||||
[xx]ch [yy]ch
|
||||
------> [CTU] -------->
|
||||
|
||||
CTU can convert [xx]ch to [yy]ch, or exchange outputed channel.
|
||||
CTU conversion needs matrix settings.
|
||||
For more detail information, see below
|
||||
|
||||
Renesas R-Car datasheet
|
||||
- Sampling Rate Converter Unit (SCU)
|
||||
- SCU Operation
|
||||
- CMD Block
|
||||
- Functional Blocks in CMD
|
||||
|
||||
Renesas R-Car datasheet
|
||||
- Sampling Rate Converter Unit (SCU)
|
||||
- Register Description
|
||||
- CTUn Scale Value exx Register (CTUn_SVxxR)
|
||||
|
||||
${LINUX}/sound/soc/sh/rcar/ctu.c
|
||||
- comment of header
|
||||
|
||||
You need to use "renesas,rsrc-card" sound card for it.
|
||||
example)
|
||||
|
||||
sound {
|
||||
compatible = "renesas,rsrc-card";
|
||||
...
|
||||
/*
|
||||
* CTU setting
|
||||
* All input data will be converted to 2ch
|
||||
* as output data
|
||||
*/
|
||||
convert-channels = <2>;
|
||||
...
|
||||
cpu {
|
||||
sound-dai = <&rcar_sound>;
|
||||
};
|
||||
codec {
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
Ex) Exchange output channel
|
||||
Input -> Output
|
||||
1ch -> 0ch
|
||||
0ch -> 1ch
|
||||
|
||||
example of using matrix
|
||||
output 0ch = (input 0ch x 0) + (input 1ch x 1)
|
||||
output 1ch = (input 0ch x 1) + (input 1ch x 0)
|
||||
|
||||
amixer set "CTU Reset" on
|
||||
amixer set "CTU Pass" 9,10
|
||||
amixer set "CTU SV0" 0,4194304
|
||||
amixer set "CTU SV1" 4194304,0
|
||||
|
||||
example of changing connection
|
||||
amixer set "CTU Reset" on
|
||||
amixer set "CTU Pass" 2,1
|
||||
|
||||
=============================================
|
||||
* MIX (Mixer)
|
||||
=============================================
|
||||
|
||||
MIX merges 2 sounds path. You can see 2 sound interface on system,
|
||||
and these sounds will be merged by MIX.
|
||||
|
||||
aplay -D plughw:0,0 xxxx.wav &
|
||||
aplay -D plughw:0,1 yyyy.wav
|
||||
|
||||
You need to use "renesas,rsrc-card" sound card for it.
|
||||
Ex)
|
||||
[MEM] -> [SRC1] -> [CTU02] -+-> [MIX0] -> [DVC0] -> [SSI0]
|
||||
|
|
||||
[MEM] -> [SRC2] -> [CTU03] -+
|
||||
|
||||
sound {
|
||||
compatible = "renesas,rsrc-card";
|
||||
...
|
||||
cpu@0 {
|
||||
sound-dai = <&rcar_sound 0>;
|
||||
};
|
||||
cpu@1 {
|
||||
sound-dai = <&rcar_sound 1>;
|
||||
};
|
||||
codec {
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
&rcar_sound {
|
||||
...
|
||||
rcar_sound,dai {
|
||||
dai0 {
|
||||
playback = <&src1 &ctu02 &mix0 &dvc0 &ssi0>;
|
||||
};
|
||||
dai1 {
|
||||
playback = <&src2 &ctu03 &mix0 &dvc0 &ssi0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
=============================================
|
||||
* DVC (Digital Volume and Mute Function)
|
||||
=============================================
|
||||
|
||||
DVC controls Playback/Capture volume.
|
||||
|
||||
Playback Volume
|
||||
amixer set "DVC Out" 100%
|
||||
|
||||
Capture Volume
|
||||
amixer set "DVC In" 100%
|
||||
|
||||
Playback Mute
|
||||
amixer set "DVC Out Mute" on
|
||||
|
||||
Capture Mute
|
||||
amixer set "DVC In Mute" on
|
||||
|
||||
Volume Ramp
|
||||
amixer set "DVC Out Ramp Up Rate" "0.125 dB/64 steps"
|
||||
amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
|
||||
amixer set "DVC Out Ramp" on
|
||||
aplay xxx.wav &
|
||||
amixer set "DVC Out" 80% // Volume Down
|
||||
amixer set "DVC Out" 100% // Volume Up
|
||||
|
||||
=============================================
|
||||
* SSIU (Serial Sound Interface Unit)
|
||||
=============================================
|
||||
|
||||
There is no DT settings for SSIU, because SSIU will be automatically
|
||||
selected via SSI.
|
||||
SSIU can avoid some under/over run error, because it has some buffer.
|
||||
But you can't use it if SSI was PIO mode.
|
||||
In DMA mode, you can select not to use SSIU by using "no-busif" on DT.
|
||||
|
||||
&ssi0 {
|
||||
no-busif;
|
||||
};
|
||||
|
||||
=============================================
|
||||
* SSI (Serial Sound Interface)
|
||||
=============================================
|
||||
|
||||
** PIO mode
|
||||
|
||||
You can use PIO mode which is for connection check by using.
|
||||
Note: The system will drop non-SSI modules in PIO mode
|
||||
even though if DT is selecting other modules.
|
||||
|
||||
&ssi0 {
|
||||
pio-transfer
|
||||
};
|
||||
|
||||
** DMA mode without SSIU
|
||||
|
||||
You can use DMA without SSIU.
|
||||
Note: under/over run, or noise are likely to occur
|
||||
|
||||
&ssi0 {
|
||||
no-busif;
|
||||
};
|
||||
|
||||
** PIN sharing
|
||||
|
||||
Each SSI can share WS pin. It is based on platform.
|
||||
This is example if SSI1 want to share WS pin with SSI0
|
||||
|
||||
&ssi1 {
|
||||
shared-pin;
|
||||
};
|
||||
|
||||
** Multi-SSI
|
||||
|
||||
You can use Multi-SSI.
|
||||
This is example of SSI0/SSI1/SSI2 (= for 6ch)
|
||||
|
||||
&rcar_sound {
|
||||
...
|
||||
rcar_sound,dai {
|
||||
dai0 {
|
||||
playback = <&ssi0 &ssi1 &ssi2 &src0 &dvc0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
** TDM-SSI
|
||||
|
||||
You can use TDM with SSI.
|
||||
This is example of TDM 6ch.
|
||||
Driver can automatically switches TDM <-> stereo mode in this case.
|
||||
|
||||
rsnd_tdm: sound {
|
||||
compatible = "simple-audio-card";
|
||||
...
|
||||
simple-audio-card,cpu {
|
||||
/* system can use TDM 6ch */
|
||||
dai-tdm-slot-num = <6>;
|
||||
sound-dai = <&rcar_sound>;
|
||||
};
|
||||
simple-audio-card,codec {
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
=============================================
|
||||
Required properties:
|
||||
=============================================
|
||||
|
||||
- compatible : "renesas,rcar_sound-<soctype>", fallbacks
|
||||
"renesas,rcar_sound-gen1" if generation1, and
|
||||
"renesas,rcar_sound-gen2" if generation2
|
||||
|
@ -64,7 +395,10 @@ DAI subnode properties:
|
|||
- playback : list of playback modules
|
||||
- capture : list of capture modules
|
||||
|
||||
|
||||
=============================================
|
||||
Example:
|
||||
=============================================
|
||||
|
||||
rcar_sound: sound@ec500000 {
|
||||
#sound-dai-cells = <1>;
|
||||
|
@ -250,7 +584,9 @@ rcar_sound: sound@ec500000 {
|
|||
};
|
||||
};
|
||||
|
||||
=============================================
|
||||
Example: simple sound card
|
||||
=============================================
|
||||
|
||||
rsnd_ak4643: sound {
|
||||
compatible = "simple-audio-card";
|
||||
|
@ -290,7 +626,9 @@ Example: simple sound card
|
|||
shared-pin;
|
||||
};
|
||||
|
||||
=============================================
|
||||
Example: simple sound card for TDM
|
||||
=============================================
|
||||
|
||||
rsnd_tdm: sound {
|
||||
compatible = "simple-audio-card";
|
||||
|
@ -309,7 +647,9 @@ Example: simple sound card for TDM
|
|||
};
|
||||
};
|
||||
|
||||
=============================================
|
||||
Example: simple sound card for Multi channel
|
||||
=============================================
|
||||
|
||||
&rcar_sound {
|
||||
pinctrl-0 = <&sound_pins &sound_clk_pins>;
|
||||
|
|
|
@ -30,6 +30,7 @@ Optional subnode properties:
|
|||
- frame-inversion : bool property. Add this if the
|
||||
dai-link uses frame clock inversion.
|
||||
- convert-rate : platform specified sampling rate convert
|
||||
- convert-channels : platform specified converted channel size (2 - 8 ch)
|
||||
- audio-prefix : see audio-routing
|
||||
- audio-routing : A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the connection's sink,
|
||||
|
|
|
@ -9,6 +9,7 @@ Required properties:
|
|||
- "rockchip,rk3066-i2s": for rk3066
|
||||
- "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
|
||||
- "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
|
||||
- "rockchip,rk3399-i2s", "rockchip,rk3066-i2s": for rk3399
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: should contain the I2S interrupt.
|
||||
|
|
|
@ -7,8 +7,12 @@ a fibre cable.
|
|||
Required properties:
|
||||
|
||||
- compatible: should be one of the following:
|
||||
- "rockchip,rk3288-spdif", "rockchip,rk3188-spdif" or
|
||||
"rockchip,rk3066-spdif"
|
||||
- "rockchip,rk3066-spdif"
|
||||
- "rockchip,rk3188-spdif"
|
||||
- "rockchip,rk3288-spdif"
|
||||
- "rockchip,rk3366-spdif"
|
||||
- "rockchip,rk3368-spdif"
|
||||
- "rockchip,rk3399-spdif"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: should contain the SPDIF interrupt.
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
RT5514 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "realtek,rt5514".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5514:
|
||||
|
||||
* DMIC1L
|
||||
* DMIC1R
|
||||
* DMIC2L
|
||||
* DMIC2R
|
||||
* AMICL
|
||||
* AMICR
|
||||
|
||||
Example:
|
||||
|
||||
codec: rt5514@57 {
|
||||
compatible = "realtek,rt5514";
|
||||
reg = <0x57>;
|
||||
};
|
|
@ -8,6 +8,12 @@ Required properties:
|
|||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- clocks: The phandle of the master clock to the CODEC.
|
||||
|
||||
- clock-names: Should be "mclk".
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5616:
|
||||
|
||||
* IN1P
|
||||
|
|
|
@ -12,6 +12,9 @@ Required properties:
|
|||
|
||||
Optional properties:
|
||||
|
||||
- clocks: The phandle of the master clock to the CODEC
|
||||
- clock-names: Should be "mclk"
|
||||
|
||||
- realtek,in1-differential
|
||||
- realtek,in2-differential
|
||||
- realtek,in3-differential
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
Allwinner Sony/Philips Digital Interface Format (S/PDIF) Controller
|
||||
|
||||
The Allwinner S/PDIF audio block is a transceiver that allows the
|
||||
processor to receive and transmit digital audio via an coaxial cable or
|
||||
a fibre cable.
|
||||
For now only playback is supported.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be one of the following:
|
||||
- "allwinner,sun4i-a10-spdif": for the Allwinner A10 SoC
|
||||
|
||||
- reg : Offset and length of the register set for the device.
|
||||
|
||||
- interrupts : Contains the spdif interrupt.
|
||||
|
||||
- dmas : Generic dma devicetree binding as described in
|
||||
Documentation/devicetree/bindings/dma/dma.txt.
|
||||
|
||||
- dma-names : Two dmas have to be defined, "tx" and "rx".
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names.
|
||||
|
||||
- clock-names : Includes the following entries:
|
||||
"apb" clock for the spdif bus.
|
||||
"spdif" clock for spdif controller.
|
||||
|
||||
Example:
|
||||
|
||||
spdif: spdif@01c21000 {
|
||||
compatible = "allwinner,sun4i-a10-spdif";
|
||||
reg = <0x01c21000 0x40>;
|
||||
interrupts = <13>;
|
||||
clocks = <&apb0_gates 1>, <&spdif_clk>;
|
||||
clock-names = "apb", "spdif";
|
||||
dmas = <&dma 0 2>, <&dma 0 2>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "okay";
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
Texas Intstruments ADS117x ADC
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "ti,ads1174" or "ti,ads1178"
|
||||
|
||||
Example:
|
||||
|
||||
ads1178 {
|
||||
compatible = "ti,ads1178";
|
||||
};
|
|
@ -400,3 +400,7 @@ wm8350_wdt:
|
|||
nowayout: Watchdog cannot be stopped once started
|
||||
(default=kernel config parameter)
|
||||
-------------------------------------------------
|
||||
sun4v_wdt:
|
||||
timeout_ms: Watchdog timeout in milliseconds 1..180000, default=60000)
|
||||
nowayout: Watchdog cannot be stopped once started
|
||||
-------------------------------------------------
|
||||
|
|
|
@ -4518,6 +4518,12 @@ L: linuxppc-dev@lists.ozlabs.org
|
|||
S: Maintained
|
||||
F: drivers/dma/fsldma.*
|
||||
|
||||
FREESCALE GPMI NAND DRIVER
|
||||
M: Han Xu <han.xu@nxp.com>
|
||||
L: linux-mtd@lists.infradead.org
|
||||
S: Maintained
|
||||
F: drivers/mtd/nand/gpmi-nand/*
|
||||
|
||||
FREESCALE I2C CPM DRIVER
|
||||
M: Jochen Friedrich <jochen@scram.de>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
|
@ -4534,7 +4540,7 @@ F: include/linux/platform_data/video-imxfb.h
|
|||
F: drivers/video/fbdev/imxfb.c
|
||||
|
||||
FREESCALE QUAD SPI DRIVER
|
||||
M: Han Xu <han.xu@freescale.com>
|
||||
M: Han Xu <han.xu@nxp.com>
|
||||
L: linux-mtd@lists.infradead.org
|
||||
S: Maintained
|
||||
F: drivers/mtd/spi-nor/fsl-quadspi.c
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 5
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -195,5 +195,7 @@ CFLAGS_font.o := -Dstatic=
|
|||
$(obj)/font.c: $(FONTC)
|
||||
$(call cmd,shipped)
|
||||
|
||||
AFLAGS_hyp-stub.o := -Wa,-march=armv7-a
|
||||
|
||||
$(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
|
||||
$(call cmd,shipped)
|
||||
|
|
|
@ -283,7 +283,6 @@ &hsusb {
|
|||
pinctrl-names = "default";
|
||||
|
||||
status = "okay";
|
||||
renesas,enable-gpio = <&gpio5 31 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
&usbphy {
|
||||
|
|
|
@ -88,6 +88,7 @@ obj-$(CONFIG_DEBUG_LL) += debug.o
|
|||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
|
||||
obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o
|
||||
AFLAGS_hyp-stub.o :=-Wa,-march=armv7-a
|
||||
ifeq ($(CONFIG_ARM_PSCI),y)
|
||||
obj-$(CONFIG_SMP) += psci_smp.o
|
||||
endif
|
||||
|
|
|
@ -161,7 +161,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
|||
u64 val;
|
||||
|
||||
val = kvm_arm_timer_get_reg(vcpu, reg->id);
|
||||
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
|
||||
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
static unsigned long num_core_regs(void)
|
||||
|
|
|
@ -49,6 +49,9 @@ static int change_memory_common(unsigned long addr, int numpages,
|
|||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
if (!numpages)
|
||||
return 0;
|
||||
|
||||
if (start < MODULES_VADDR || start >= MODULES_END)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -34,13 +34,13 @@
|
|||
/*
|
||||
* VMALLOC and SPARSEMEM_VMEMMAP ranges.
|
||||
*
|
||||
* VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
|
||||
* VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
|
||||
* (rounded up to PUD_SIZE).
|
||||
* VMALLOC_START: beginning of the kernel VA space
|
||||
* VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
|
||||
* fixed mappings and modules
|
||||
*/
|
||||
#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
|
||||
#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT - 1)) * sizeof(struct page), PUD_SIZE)
|
||||
|
||||
#ifndef CONFIG_KASAN
|
||||
#define VMALLOC_START (VA_START)
|
||||
|
@ -51,7 +51,8 @@
|
|||
|
||||
#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
|
||||
|
||||
#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K))
|
||||
#define VMEMMAP_START (VMALLOC_END + SZ_64K)
|
||||
#define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
|
||||
|
||||
#define FIRST_USER_ADDRESS 0UL
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
|||
u64 val;
|
||||
|
||||
val = kvm_arm_timer_get_reg(vcpu, reg->id);
|
||||
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
|
||||
return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -319,8 +319,8 @@ void __init mem_init(void)
|
|||
#endif
|
||||
MLG(VMALLOC_START, VMALLOC_END),
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
MLG((unsigned long)vmemmap,
|
||||
(unsigned long)vmemmap + VMEMMAP_SIZE),
|
||||
MLG(VMEMMAP_START,
|
||||
VMEMMAP_START + VMEMMAP_SIZE),
|
||||
MLM((unsigned long)virt_to_page(PAGE_OFFSET),
|
||||
(unsigned long)virt_to_page(high_memory)),
|
||||
#endif
|
||||
|
|
|
@ -74,7 +74,7 @@ uart0: serial@10000100 {
|
|||
timer: timer@10000040 {
|
||||
compatible = "syscon";
|
||||
reg = <0x10000040 0x2c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -54,7 +54,7 @@ ubus {
|
|||
periph_cntl: syscon@10000000 {
|
||||
compatible = "syscon";
|
||||
reg = <0x10000000 0x14>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot: syscon-reboot@10000008 {
|
||||
|
|
|
@ -98,7 +98,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7125-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x60c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -118,7 +118,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7346-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x51c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -112,7 +112,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7358-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x51c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -112,7 +112,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7360-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x51c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -118,7 +118,7 @@ upg_aon_irq0_intc: upg_aon_irq0_intc@408b80 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7362-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x51c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -99,7 +99,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7420-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x60c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -100,7 +100,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x51c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -114,7 +114,7 @@ upg_irq0_intc: upg_irq0_intc@406780 {
|
|||
sun_top_ctrl: syscon@404000 {
|
||||
compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
|
||||
reg = <0x404000 0x51c>;
|
||||
little-endian;
|
||||
native-endian;
|
||||
};
|
||||
|
||||
reboot {
|
||||
|
|
|
@ -270,7 +270,7 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask)
|
|||
}
|
||||
EXPORT_SYMBOL(jz_gpio_port_get_value);
|
||||
|
||||
#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f)
|
||||
#define IRQ_TO_BIT(irq) BIT((irq - JZ4740_IRQ_GPIO(0)) & 0x1f)
|
||||
|
||||
static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq)
|
||||
{
|
||||
|
|
|
@ -125,7 +125,7 @@ LEAF(_restore_fp_context)
|
|||
END(_restore_fp_context)
|
||||
.set reorder
|
||||
|
||||
.type fault@function
|
||||
.type fault, @function
|
||||
.ent fault
|
||||
fault: li v0, -EFAULT
|
||||
jr ra
|
||||
|
|
|
@ -358,7 +358,7 @@ LEAF(_restore_msa_all_upper)
|
|||
|
||||
.set reorder
|
||||
|
||||
.type fault@function
|
||||
.type fault, @function
|
||||
.ent fault
|
||||
fault: li v0, -EFAULT # failure
|
||||
jr ra
|
||||
|
|
|
@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
|
|||
asmlinkage void do_ov(struct pt_regs *regs)
|
||||
{
|
||||
enum ctx_state prev_state;
|
||||
siginfo_t info;
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGFPE,
|
||||
.si_code = FPE_INTOVF,
|
||||
.si_addr = (void __user *)regs->cp0_epc,
|
||||
};
|
||||
|
||||
prev_state = exception_enter();
|
||||
die_if_kernel("Integer overflow", regs);
|
||||
|
||||
info.si_code = FPE_INTOVF;
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void __user *) regs->cp0_epc;
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -874,7 +874,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
|
|||
void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
||||
const char *str)
|
||||
{
|
||||
siginfo_t info;
|
||||
siginfo_t info = { 0 };
|
||||
char b[40];
|
||||
|
||||
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
|
||||
|
@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
|
|||
else
|
||||
info.si_code = FPE_INTOVF;
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void __user *) regs->cp0_epc;
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
break;
|
||||
|
|
|
@ -702,7 +702,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
|
|||
} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
|
||||
void __user *uaddr = (void __user *)(long)reg->addr;
|
||||
|
||||
return copy_to_user(uaddr, vs, 16);
|
||||
return copy_to_user(uaddr, vs, 16) ? -EFAULT : 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -732,7 +732,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
|
|||
} else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
|
||||
void __user *uaddr = (void __user *)(long)reg->addr;
|
||||
|
||||
return copy_from_user(vs, uaddr, 16);
|
||||
return copy_from_user(vs, uaddr, 16) ? -EFAULT : 0;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -164,11 +164,13 @@ static int __init mips_sc_probe_cm3(void)
|
|||
|
||||
sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
|
||||
sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
|
||||
c->scache.sets = 64 << sets;
|
||||
if (sets)
|
||||
c->scache.sets = 64 << sets;
|
||||
|
||||
line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
|
||||
line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
|
||||
c->scache.linesz = 2 << line_sz;
|
||||
if (line_sz)
|
||||
c->scache.linesz = 2 << line_sz;
|
||||
|
||||
assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
|
||||
assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
|
||||
|
@ -176,9 +178,12 @@ static int __init mips_sc_probe_cm3(void)
|
|||
c->scache.waysize = c->scache.sets * c->scache.linesz;
|
||||
c->scache.waybit = __ffs(c->scache.waysize);
|
||||
|
||||
c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
|
||||
if (c->scache.linesz) {
|
||||
c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __init mips_sc_probe(void)
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
* floppy accesses go through the track buffer.
|
||||
*/
|
||||
#define _CROSS_64KB(a,s,vdma) \
|
||||
(!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
|
||||
(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
|
||||
|
||||
#define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
|
||||
|
||||
|
|
|
@ -361,8 +361,9 @@
|
|||
#define __NR_membarrier (__NR_Linux + 343)
|
||||
#define __NR_userfaultfd (__NR_Linux + 344)
|
||||
#define __NR_mlock2 (__NR_Linux + 345)
|
||||
#define __NR_copy_file_range (__NR_Linux + 346)
|
||||
|
||||
#define __NR_Linux_syscalls (__NR_mlock2 + 1)
|
||||
#define __NR_Linux_syscalls (__NR_copy_file_range + 1)
|
||||
|
||||
|
||||
#define __IGNORE_select /* newselect */
|
||||
|
|
|
@ -269,14 +269,19 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
|||
|
||||
long do_syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
/* Do the secure computing check first. */
|
||||
secure_computing_strict(regs->gr[20]);
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||
tracehook_report_syscall_entry(regs))
|
||||
ret = -1L;
|
||||
tracehook_report_syscall_entry(regs)) {
|
||||
/*
|
||||
* Tracing decided this syscall should not happen or the
|
||||
* debugger stored an invalid system call number. Skip
|
||||
* the system call and the system call restart handling.
|
||||
*/
|
||||
regs->gr[20] = -1UL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
if (!is_compat_task())
|
||||
|
@ -290,7 +295,8 @@ long do_syscall_trace_enter(struct pt_regs *regs)
|
|||
regs->gr[24] & 0xffffffff,
|
||||
regs->gr[23] & 0xffffffff);
|
||||
|
||||
return ret ? : regs->gr[20];
|
||||
out:
|
||||
return regs->gr[20];
|
||||
}
|
||||
|
||||
void do_syscall_trace_exit(struct pt_regs *regs)
|
||||
|
|
|
@ -343,7 +343,7 @@ tracesys_next:
|
|||
#endif
|
||||
|
||||
comiclr,>>= __NR_Linux_syscalls, %r20, %r0
|
||||
b,n .Lsyscall_nosys
|
||||
b,n .Ltracesys_nosys
|
||||
|
||||
LDREGX %r20(%r19), %r19
|
||||
|
||||
|
@ -359,6 +359,9 @@ tracesys_next:
|
|||
be 0(%sr7,%r19)
|
||||
ldo R%tracesys_exit(%r2),%r2
|
||||
|
||||
.Ltracesys_nosys:
|
||||
ldo -ENOSYS(%r0),%r28 /* set errno */
|
||||
|
||||
/* Do *not* call this function on the gateway page, because it
|
||||
makes a direct call to syscall_trace. */
|
||||
|
||||
|
|
|
@ -441,6 +441,7 @@
|
|||
ENTRY_SAME(membarrier)
|
||||
ENTRY_SAME(userfaultfd)
|
||||
ENTRY_SAME(mlock2) /* 345 */
|
||||
ENTRY_SAME(copy_file_range)
|
||||
|
||||
|
||||
.ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b))
|
||||
|
|
|
@ -109,8 +109,9 @@ void arch_unregister_hw_breakpoint(struct perf_event *bp)
|
|||
* If the breakpoint is unregistered between a hw_breakpoint_handler()
|
||||
* and the single_step_dabr_instruction(), then cleanup the breakpoint
|
||||
* restoration variables to prevent dangling pointers.
|
||||
* FIXME, this should not be using bp->ctx at all! Sayeth peterz.
|
||||
*/
|
||||
if (bp->ctx && bp->ctx->task)
|
||||
if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L))
|
||||
bp->ctx->task->thread.last_hit_ubp = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/hugetlb.h>
|
||||
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#ifdef CONFIG_PPC_FSL_BOOK3E
|
||||
#ifdef CONFIG_PPC64
|
||||
static inline int tlb1_next(void)
|
||||
|
@ -60,6 +62,14 @@ static inline void book3e_tlb_lock(void)
|
|||
unsigned long tmp;
|
||||
int token = smp_processor_id() + 1;
|
||||
|
||||
/*
|
||||
* Besides being unnecessary in the absence of SMT, this
|
||||
* check prevents trying to do lbarx/stbcx. on e5500 which
|
||||
* doesn't implement either feature.
|
||||
*/
|
||||
if (!cpu_has_feature(CPU_FTR_SMT))
|
||||
return;
|
||||
|
||||
asm volatile("1: lbarx %0, 0, %1;"
|
||||
"cmpwi %0, 0;"
|
||||
"bne 2f;"
|
||||
|
@ -80,6 +90,9 @@ static inline void book3e_tlb_unlock(void)
|
|||
{
|
||||
struct paca_struct *paca = get_paca();
|
||||
|
||||
if (!cpu_has_feature(CPU_FTR_SMT))
|
||||
return;
|
||||
|
||||
isync();
|
||||
paca->tcd_ptr->lock = 0;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,13 @@ LDFLAGS := -m elf32_sparc
|
|||
export BITS := 32
|
||||
UTS_MACHINE := sparc
|
||||
|
||||
# We are adding -Wa,-Av8 to KBUILD_CFLAGS to deal with a specs bug in some
|
||||
# versions of gcc. Some gcc versions won't pass -Av8 to binutils when you
|
||||
# give -mcpu=v8. This silently worked with older bintutils versions but
|
||||
# does not any more.
|
||||
KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
|
||||
KBUILD_CFLAGS += -Wa,-Av8
|
||||
|
||||
KBUILD_AFLAGS += -m32 -Wa,-Av8
|
||||
|
||||
else
|
||||
|
|
|
@ -422,8 +422,9 @@
|
|||
#define __NR_listen 354
|
||||
#define __NR_setsockopt 355
|
||||
#define __NR_mlock2 356
|
||||
#define __NR_copy_file_range 357
|
||||
|
||||
#define NR_syscalls 357
|
||||
#define NR_syscalls 358
|
||||
|
||||
/* Bitmask values returned from kern_features system call. */
|
||||
#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001
|
||||
|
|
|
@ -948,7 +948,24 @@ linux_syscall_trace:
|
|||
cmp %o0, 0
|
||||
bne 3f
|
||||
mov -ENOSYS, %o0
|
||||
|
||||
/* Syscall tracing can modify the registers. */
|
||||
ld [%sp + STACKFRAME_SZ + PT_G1], %g1
|
||||
sethi %hi(sys_call_table), %l7
|
||||
ld [%sp + STACKFRAME_SZ + PT_I0], %i0
|
||||
or %l7, %lo(sys_call_table), %l7
|
||||
ld [%sp + STACKFRAME_SZ + PT_I1], %i1
|
||||
ld [%sp + STACKFRAME_SZ + PT_I2], %i2
|
||||
ld [%sp + STACKFRAME_SZ + PT_I3], %i3
|
||||
ld [%sp + STACKFRAME_SZ + PT_I4], %i4
|
||||
ld [%sp + STACKFRAME_SZ + PT_I5], %i5
|
||||
cmp %g1, NR_syscalls
|
||||
bgeu 3f
|
||||
mov -ENOSYS, %o0
|
||||
|
||||
sll %g1, 2, %l4
|
||||
mov %i0, %o0
|
||||
ld [%l7 + %l4], %l7
|
||||
mov %i1, %o1
|
||||
mov %i2, %o2
|
||||
mov %i3, %o3
|
||||
|
|
|
@ -338,8 +338,9 @@ ENTRY(sun4v_mach_set_watchdog)
|
|||
mov %o1, %o4
|
||||
mov HV_FAST_MACH_SET_WATCHDOG, %o5
|
||||
ta HV_FAST_TRAP
|
||||
brnz,a,pn %o4, 0f
|
||||
stx %o1, [%o4]
|
||||
retl
|
||||
0: retl
|
||||
nop
|
||||
ENDPROC(sun4v_mach_set_watchdog)
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
|
|||
unsigned char fenab;
|
||||
int err;
|
||||
|
||||
flush_user_windows();
|
||||
synchronize_user_stack();
|
||||
if (get_thread_wsaved() ||
|
||||
(((unsigned long)ucp) & (sizeof(unsigned long)-1)) ||
|
||||
(!__access_ok(ucp, sizeof(*ucp))))
|
||||
|
|
|
@ -37,6 +37,7 @@ EXPORT_SYMBOL(sun4v_niagara_getperf);
|
|||
EXPORT_SYMBOL(sun4v_niagara_setperf);
|
||||
EXPORT_SYMBOL(sun4v_niagara2_getperf);
|
||||
EXPORT_SYMBOL(sun4v_niagara2_setperf);
|
||||
EXPORT_SYMBOL(sun4v_mach_set_watchdog);
|
||||
|
||||
/* from hweight.S */
|
||||
EXPORT_SYMBOL(__arch_hweight8);
|
||||
|
|
|
@ -158,7 +158,25 @@ linux_syscall_trace32:
|
|||
add %sp, PTREGS_OFF, %o0
|
||||
brnz,pn %o0, 3f
|
||||
mov -ENOSYS, %o0
|
||||
|
||||
/* Syscall tracing can modify the registers. */
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
|
||||
sethi %hi(sys_call_table32), %l7
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0
|
||||
or %l7, %lo(sys_call_table32), %l7
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5
|
||||
|
||||
cmp %g1, NR_syscalls
|
||||
bgeu,pn %xcc, 3f
|
||||
mov -ENOSYS, %o0
|
||||
|
||||
sll %g1, 2, %l4
|
||||
srl %i0, 0, %o0
|
||||
lduw [%l7 + %l4], %l7
|
||||
srl %i4, 0, %o4
|
||||
srl %i1, 0, %o1
|
||||
srl %i2, 0, %o2
|
||||
|
@ -170,7 +188,25 @@ linux_syscall_trace:
|
|||
add %sp, PTREGS_OFF, %o0
|
||||
brnz,pn %o0, 3f
|
||||
mov -ENOSYS, %o0
|
||||
|
||||
/* Syscall tracing can modify the registers. */
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
|
||||
sethi %hi(sys_call_table64), %l7
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0
|
||||
or %l7, %lo(sys_call_table64), %l7
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5
|
||||
|
||||
cmp %g1, NR_syscalls
|
||||
bgeu,pn %xcc, 3f
|
||||
mov -ENOSYS, %o0
|
||||
|
||||
sll %g1, 2, %l4
|
||||
mov %i0, %o0
|
||||
lduw [%l7 + %l4], %l7
|
||||
mov %i1, %o1
|
||||
mov %i2, %o2
|
||||
mov %i3, %o3
|
||||
|
|
|
@ -88,4 +88,4 @@ sys_call_table:
|
|||
/*340*/ .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
|
||||
/*345*/ .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
|
||||
/*350*/ .long sys_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
|
||||
/*355*/ .long sys_setsockopt, sys_mlock2
|
||||
/*355*/ .long sys_setsockopt, sys_mlock2, sys_copy_file_range
|
||||
|
|
|
@ -89,7 +89,7 @@ sys_call_table32:
|
|||
/*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
|
||||
.word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
|
||||
/*350*/ .word sys32_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
|
||||
.word compat_sys_setsockopt, sys_mlock2
|
||||
.word compat_sys_setsockopt, sys_mlock2, sys_copy_file_range
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
|
@ -170,4 +170,4 @@ sys_call_table:
|
|||
/*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
|
||||
.word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
|
||||
/*350*/ .word sys64_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
|
||||
.word sys_setsockopt, sys_mlock2
|
||||
.word sys_setsockopt, sys_mlock2, sys_copy_file_range
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <skas.h>
|
||||
|
||||
void (*pm_power_off)(void);
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
static void kill_off_processes(void)
|
||||
{
|
||||
|
|
|
@ -69,7 +69,7 @@ void do_signal(struct pt_regs *regs)
|
|||
struct ksignal ksig;
|
||||
int handled_sig = 0;
|
||||
|
||||
if (get_signal(&ksig)) {
|
||||
while (get_signal(&ksig)) {
|
||||
handled_sig = 1;
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(&ksig, regs);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <asm/cacheflush.h>
|
||||
#include <asm/realmode.h>
|
||||
|
||||
#include <linux/ftrace.h>
|
||||
#include "../../realmode/rm/wakeup.h"
|
||||
#include "sleep.h"
|
||||
|
||||
|
@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void)
|
|||
saved_magic = 0x123456789abcdef0L;
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
/*
|
||||
* Pause/unpause graph tracing around do_suspend_lowlevel as it has
|
||||
* inconsistent call/return info after it jumps to the wakeup vector.
|
||||
*/
|
||||
pause_graph_tracing();
|
||||
do_suspend_lowlevel();
|
||||
unpause_graph_tracing();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -596,6 +596,8 @@ struct vcpu_vmx {
|
|||
/* Support for PML */
|
||||
#define PML_ENTITY_NUM 512
|
||||
struct page *pml_pg;
|
||||
|
||||
u64 current_tsc_ratio;
|
||||
};
|
||||
|
||||
enum segment_cache_field {
|
||||
|
@ -2127,14 +2129,16 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||
rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
|
||||
vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
|
||||
|
||||
/* Setup TSC multiplier */
|
||||
if (cpu_has_vmx_tsc_scaling())
|
||||
vmcs_write64(TSC_MULTIPLIER,
|
||||
vcpu->arch.tsc_scaling_ratio);
|
||||
|
||||
vmx->loaded_vmcs->cpu = cpu;
|
||||
}
|
||||
|
||||
/* Setup TSC multiplier */
|
||||
if (kvm_has_tsc_control &&
|
||||
vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio) {
|
||||
vmx->current_tsc_ratio = vcpu->arch.tsc_scaling_ratio;
|
||||
vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
|
||||
}
|
||||
|
||||
vmx_vcpu_pi_load(vcpu, cpu);
|
||||
}
|
||||
|
||||
|
|
|
@ -2752,7 +2752,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||
}
|
||||
|
||||
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
|
||||
vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD;
|
||||
}
|
||||
|
||||
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
|
@ -6619,12 +6618,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
|||
* KVM_DEBUGREG_WONT_EXIT again.
|
||||
*/
|
||||
if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
|
||||
int i;
|
||||
|
||||
WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
|
||||
kvm_x86_ops->sync_dirty_debug_regs(vcpu);
|
||||
for (i = 0; i < KVM_NR_DB_REGS; i++)
|
||||
vcpu->arch.eff_db[i] = vcpu->arch.db[i];
|
||||
kvm_update_dr0123(vcpu);
|
||||
kvm_update_dr6(vcpu);
|
||||
kvm_update_dr7(vcpu);
|
||||
vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -109,7 +109,7 @@ unsigned long os_get_top_address(void)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
|
||||
printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT);
|
||||
printf("Locating the top of the address space ... ");
|
||||
fflush(stdout);
|
||||
|
||||
|
@ -134,7 +134,7 @@ unsigned long os_get_top_address(void)
|
|||
exit(1);
|
||||
}
|
||||
top <<= UM_KERN_PAGE_SHIFT;
|
||||
printf("0x%x\n", top);
|
||||
printf("0x%lx\n", top);
|
||||
|
||||
return top;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,49 @@ static int __blk_rq_unmap_user(struct bio *bio)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __blk_rq_map_user_iov(struct request *rq,
|
||||
struct rq_map_data *map_data, struct iov_iter *iter,
|
||||
gfp_t gfp_mask, bool copy)
|
||||
{
|
||||
struct request_queue *q = rq->q;
|
||||
struct bio *bio, *orig_bio;
|
||||
int ret;
|
||||
|
||||
if (copy)
|
||||
bio = bio_copy_user_iov(q, map_data, iter, gfp_mask);
|
||||
else
|
||||
bio = bio_map_user_iov(q, iter, gfp_mask);
|
||||
|
||||
if (IS_ERR(bio))
|
||||
return PTR_ERR(bio);
|
||||
|
||||
if (map_data && map_data->null_mapped)
|
||||
bio_set_flag(bio, BIO_NULL_MAPPED);
|
||||
|
||||
iov_iter_advance(iter, bio->bi_iter.bi_size);
|
||||
if (map_data)
|
||||
map_data->offset += bio->bi_iter.bi_size;
|
||||
|
||||
orig_bio = bio;
|
||||
blk_queue_bounce(q, &bio);
|
||||
|
||||
/*
|
||||
* We link the bounce buffer in and could have to traverse it
|
||||
* later so we have to get a ref to prevent it from being freed
|
||||
*/
|
||||
bio_get(bio);
|
||||
|
||||
ret = blk_rq_append_bio(q, rq, bio);
|
||||
if (ret) {
|
||||
bio_endio(bio);
|
||||
__blk_rq_unmap_user(orig_bio);
|
||||
bio_put(bio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage
|
||||
* @q: request queue where request should be inserted
|
||||
|
@ -82,10 +125,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
|
|||
struct rq_map_data *map_data,
|
||||
const struct iov_iter *iter, gfp_t gfp_mask)
|
||||
{
|
||||
struct bio *bio;
|
||||
int unaligned = 0;
|
||||
struct iov_iter i;
|
||||
struct iovec iov, prv = {.iov_base = NULL, .iov_len = 0};
|
||||
bool copy = (q->dma_pad_mask & iter->count) || map_data;
|
||||
struct bio *bio = NULL;
|
||||
struct iov_iter i;
|
||||
int ret;
|
||||
|
||||
if (!iter || !iter->count)
|
||||
return -EINVAL;
|
||||
|
@ -101,42 +145,29 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
|
|||
*/
|
||||
if ((uaddr & queue_dma_alignment(q)) ||
|
||||
iovec_gap_to_prv(q, &prv, &iov))
|
||||
unaligned = 1;
|
||||
copy = true;
|
||||
|
||||
prv.iov_base = iov.iov_base;
|
||||
prv.iov_len = iov.iov_len;
|
||||
}
|
||||
|
||||
if (unaligned || (q->dma_pad_mask & iter->count) || map_data)
|
||||
bio = bio_copy_user_iov(q, map_data, iter, gfp_mask);
|
||||
else
|
||||
bio = bio_map_user_iov(q, iter, gfp_mask);
|
||||
|
||||
if (IS_ERR(bio))
|
||||
return PTR_ERR(bio);
|
||||
|
||||
if (map_data && map_data->null_mapped)
|
||||
bio_set_flag(bio, BIO_NULL_MAPPED);
|
||||
|
||||
if (bio->bi_iter.bi_size != iter->count) {
|
||||
/*
|
||||
* Grab an extra reference to this bio, as bio_unmap_user()
|
||||
* expects to be able to drop it twice as it happens on the
|
||||
* normal IO completion path
|
||||
*/
|
||||
bio_get(bio);
|
||||
bio_endio(bio);
|
||||
__blk_rq_unmap_user(bio);
|
||||
return -EINVAL;
|
||||
}
|
||||
i = *iter;
|
||||
do {
|
||||
ret =__blk_rq_map_user_iov(rq, map_data, &i, gfp_mask, copy);
|
||||
if (ret)
|
||||
goto unmap_rq;
|
||||
if (!bio)
|
||||
bio = rq->bio;
|
||||
} while (iov_iter_count(&i));
|
||||
|
||||
if (!bio_flagged(bio, BIO_USER_MAPPED))
|
||||
rq->cmd_flags |= REQ_COPY_USER;
|
||||
|
||||
blk_queue_bounce(q, &bio);
|
||||
bio_get(bio);
|
||||
blk_rq_bio_prep(q, rq, bio);
|
||||
return 0;
|
||||
|
||||
unmap_rq:
|
||||
__blk_rq_unmap_user(bio);
|
||||
rq->bio = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_map_user_iov);
|
||||
|
||||
|
|
|
@ -304,7 +304,6 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
|
|||
struct bio *nxt)
|
||||
{
|
||||
struct bio_vec end_bv = { NULL }, nxt_bv;
|
||||
struct bvec_iter iter;
|
||||
|
||||
if (!blk_queue_cluster(q))
|
||||
return 0;
|
||||
|
@ -316,11 +315,8 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
|
|||
if (!bio_has_data(bio))
|
||||
return 1;
|
||||
|
||||
bio_for_each_segment(end_bv, bio, iter)
|
||||
if (end_bv.bv_len == iter.bi_size)
|
||||
break;
|
||||
|
||||
nxt_bv = bio_iovec(nxt);
|
||||
bio_get_last_bvec(bio, &end_bv);
|
||||
bio_get_first_bvec(nxt, &nxt_bv);
|
||||
|
||||
if (!BIOVEC_PHYS_MERGEABLE(&end_bv, &nxt_bv))
|
||||
return 0;
|
||||
|
|
|
@ -1590,14 +1590,21 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
|
|||
start = ndr_desc->res->start;
|
||||
len = ndr_desc->res->end - ndr_desc->res->start + 1;
|
||||
|
||||
/*
|
||||
* If ARS is unimplemented, unsupported, or if the 'Persistent Memory
|
||||
* Scrub' flag in extended status is not set, skip this but continue
|
||||
* initialization
|
||||
*/
|
||||
rc = ars_get_cap(nd_desc, ars_cap, start, len);
|
||||
if (rc == -ENOTTY) {
|
||||
dev_dbg(acpi_desc->dev,
|
||||
"Address Range Scrub is not implemented, won't create an error list\n");
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If ARS is unsupported, or if the 'Persistent Memory Scrub' flag in
|
||||
* extended status is not set, skip this but continue initialization
|
||||
*/
|
||||
if ((ars_cap->status & 0xffff) ||
|
||||
!(ars_cap->status >> 16 & ND_ARS_PERSISTENT)) {
|
||||
dev_warn(acpi_desc->dev,
|
||||
|
|
|
@ -367,15 +367,21 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
|||
{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
|
||||
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
|
||||
{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
|
||||
|
||||
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
|
||||
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
|
@ -1325,6 +1331,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
|
|||
{}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
/*
|
||||
* Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
|
||||
* Workaround is to make sure all pending IRQs are served before leaving
|
||||
* handler.
|
||||
*/
|
||||
static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
struct ata_host *host = dev_instance;
|
||||
struct ahci_host_priv *hpriv;
|
||||
unsigned int rc = 0;
|
||||
void __iomem *mmio;
|
||||
u32 irq_stat, irq_masked;
|
||||
unsigned int handled = 1;
|
||||
|
||||
VPRINTK("ENTER\n");
|
||||
hpriv = host->private_data;
|
||||
mmio = hpriv->mmio;
|
||||
irq_stat = readl(mmio + HOST_IRQ_STAT);
|
||||
if (!irq_stat)
|
||||
return IRQ_NONE;
|
||||
|
||||
do {
|
||||
irq_masked = irq_stat & hpriv->port_map;
|
||||
spin_lock(&host->lock);
|
||||
rc = ahci_handle_port_intr(host, irq_masked);
|
||||
if (!rc)
|
||||
handled = 0;
|
||||
writel(irq_stat, mmio + HOST_IRQ_STAT);
|
||||
irq_stat = readl(mmio + HOST_IRQ_STAT);
|
||||
spin_unlock(&host->lock);
|
||||
} while (irq_stat);
|
||||
VPRINTK("EXIT\n");
|
||||
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
|
||||
* to single msi.
|
||||
|
@ -1560,6 +1604,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (ahci_broken_devslp(pdev))
|
||||
hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
|
||||
hpriv->irq_handler = ahci_thunderx_irq_handler;
|
||||
#endif
|
||||
|
||||
/* save initial config */
|
||||
ahci_pci_save_initial_config(pdev, hpriv);
|
||||
|
||||
|
|
|
@ -240,8 +240,7 @@ enum {
|
|||
error-handling stage) */
|
||||
AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */
|
||||
AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */
|
||||
AHCI_HFLAG_EDGE_IRQ = (1 << 19), /* HOST_IRQ_STAT behaves as
|
||||
Edge Triggered */
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
AHCI_HFLAG_MULTI_MSI = (1 << 20), /* multiple PCI MSIs */
|
||||
AHCI_HFLAG_MULTI_MSIX = (1 << 21), /* per-port MSI-X */
|
||||
|
@ -361,6 +360,7 @@ struct ahci_host_priv {
|
|||
* be overridden anytime before the host is activated.
|
||||
*/
|
||||
void (*start_engine)(struct ata_port *ap);
|
||||
irqreturn_t (*irq_handler)(int irq, void *dev_instance);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PCI_MSI
|
||||
|
@ -424,6 +424,7 @@ int ahci_reset_em(struct ata_host *host);
|
|||
void ahci_print_info(struct ata_host *host, const char *scc_s);
|
||||
int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht);
|
||||
void ahci_error_handler(struct ata_port *ap);
|
||||
u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
|
||||
|
||||
static inline void __iomem *__ahci_port_base(struct ata_host *host,
|
||||
unsigned int port_no)
|
||||
|
|
|
@ -548,6 +548,88 @@ static int xgene_ahci_softreset(struct ata_link *link, unsigned int *class,
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* xgene_ahci_handle_broken_edge_irq - Handle the broken irq.
|
||||
* @ata_host: Host that recieved the irq
|
||||
* @irq_masked: HOST_IRQ_STAT value
|
||||
*
|
||||
* For hardware with broken edge trigger latch
|
||||
* the HOST_IRQ_STAT register misses the edge interrupt
|
||||
* when clearing of HOST_IRQ_STAT register and hardware
|
||||
* reporting the PORT_IRQ_STAT register at the
|
||||
* same clock cycle.
|
||||
* As such, the algorithm below outlines the workaround.
|
||||
*
|
||||
* 1. Read HOST_IRQ_STAT register and save the state.
|
||||
* 2. Clear the HOST_IRQ_STAT register.
|
||||
* 3. Read back the HOST_IRQ_STAT register.
|
||||
* 4. If HOST_IRQ_STAT register equals to zero, then
|
||||
* traverse the rest of port's PORT_IRQ_STAT register
|
||||
* to check if an interrupt is triggered at that point else
|
||||
* go to step 6.
|
||||
* 5. If PORT_IRQ_STAT register of rest ports is not equal to zero
|
||||
* then update the state of HOST_IRQ_STAT saved in step 1.
|
||||
* 6. Handle port interrupts.
|
||||
* 7. Exit
|
||||
*/
|
||||
static int xgene_ahci_handle_broken_edge_irq(struct ata_host *host,
|
||||
u32 irq_masked)
|
||||
{
|
||||
struct ahci_host_priv *hpriv = host->private_data;
|
||||
void __iomem *port_mmio;
|
||||
int i;
|
||||
|
||||
if (!readl(hpriv->mmio + HOST_IRQ_STAT)) {
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
if (irq_masked & (1 << i))
|
||||
continue;
|
||||
|
||||
port_mmio = ahci_port_base(host->ports[i]);
|
||||
if (readl(port_mmio + PORT_IRQ_STAT))
|
||||
irq_masked |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
return ahci_handle_port_intr(host, irq_masked);
|
||||
}
|
||||
|
||||
static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance)
|
||||
{
|
||||
struct ata_host *host = dev_instance;
|
||||
struct ahci_host_priv *hpriv;
|
||||
unsigned int rc = 0;
|
||||
void __iomem *mmio;
|
||||
u32 irq_stat, irq_masked;
|
||||
|
||||
VPRINTK("ENTER\n");
|
||||
|
||||
hpriv = host->private_data;
|
||||
mmio = hpriv->mmio;
|
||||
|
||||
/* sigh. 0xffffffff is a valid return from h/w */
|
||||
irq_stat = readl(mmio + HOST_IRQ_STAT);
|
||||
if (!irq_stat)
|
||||
return IRQ_NONE;
|
||||
|
||||
irq_masked = irq_stat & hpriv->port_map;
|
||||
|
||||
spin_lock(&host->lock);
|
||||
|
||||
/*
|
||||
* HOST_IRQ_STAT behaves as edge triggered latch meaning that
|
||||
* it should be cleared before all the port events are cleared.
|
||||
*/
|
||||
writel(irq_stat, mmio + HOST_IRQ_STAT);
|
||||
|
||||
rc = xgene_ahci_handle_broken_edge_irq(host, irq_masked);
|
||||
|
||||
spin_unlock(&host->lock);
|
||||
|
||||
VPRINTK("EXIT\n");
|
||||
|
||||
return IRQ_RETVAL(rc);
|
||||
}
|
||||
|
||||
static struct ata_port_operations xgene_ahci_v1_ops = {
|
||||
.inherits = &ahci_ops,
|
||||
.host_stop = xgene_ahci_host_stop,
|
||||
|
@ -779,7 +861,8 @@ static int xgene_ahci_probe(struct platform_device *pdev)
|
|||
hpriv->flags = AHCI_HFLAG_NO_NCQ;
|
||||
break;
|
||||
case XGENE_AHCI_V2:
|
||||
hpriv->flags |= AHCI_HFLAG_YES_FBS | AHCI_HFLAG_EDGE_IRQ;
|
||||
hpriv->flags |= AHCI_HFLAG_YES_FBS;
|
||||
hpriv->irq_handler = xgene_ahci_irq_intr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -113,6 +113,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
|
|||
const char *buf, size_t size);
|
||||
static ssize_t ahci_show_em_supported(struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance);
|
||||
|
||||
static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
|
||||
static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
|
||||
|
@ -512,6 +513,9 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
|
|||
|
||||
if (!hpriv->start_engine)
|
||||
hpriv->start_engine = ahci_start_engine;
|
||||
|
||||
if (!hpriv->irq_handler)
|
||||
hpriv->irq_handler = ahci_single_level_irq_intr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ahci_save_initial_config);
|
||||
|
||||
|
@ -1164,8 +1168,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
|
|||
|
||||
/* mark esata ports */
|
||||
tmp = readl(port_mmio + PORT_CMD);
|
||||
if ((tmp & PORT_CMD_HPCP) ||
|
||||
((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
|
||||
if ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))
|
||||
ap->pflags |= ATA_PFLAG_EXTERNAL;
|
||||
}
|
||||
|
||||
|
@ -1846,7 +1849,7 @@ static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
|
||||
u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
|
||||
{
|
||||
unsigned int i, handled = 0;
|
||||
|
||||
|
@ -1872,43 +1875,7 @@ static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
|
|||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance)
|
||||
{
|
||||
struct ata_host *host = dev_instance;
|
||||
struct ahci_host_priv *hpriv;
|
||||
unsigned int rc = 0;
|
||||
void __iomem *mmio;
|
||||
u32 irq_stat, irq_masked;
|
||||
|
||||
VPRINTK("ENTER\n");
|
||||
|
||||
hpriv = host->private_data;
|
||||
mmio = hpriv->mmio;
|
||||
|
||||
/* sigh. 0xffffffff is a valid return from h/w */
|
||||
irq_stat = readl(mmio + HOST_IRQ_STAT);
|
||||
if (!irq_stat)
|
||||
return IRQ_NONE;
|
||||
|
||||
irq_masked = irq_stat & hpriv->port_map;
|
||||
|
||||
spin_lock(&host->lock);
|
||||
|
||||
/*
|
||||
* HOST_IRQ_STAT behaves as edge triggered latch meaning that
|
||||
* it should be cleared before all the port events are cleared.
|
||||
*/
|
||||
writel(irq_stat, mmio + HOST_IRQ_STAT);
|
||||
|
||||
rc = ahci_handle_port_intr(host, irq_masked);
|
||||
|
||||
spin_unlock(&host->lock);
|
||||
|
||||
VPRINTK("EXIT\n");
|
||||
|
||||
return IRQ_RETVAL(rc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ahci_handle_port_intr);
|
||||
|
||||
static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance)
|
||||
{
|
||||
|
@ -2535,14 +2502,18 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht)
|
|||
int irq = hpriv->irq;
|
||||
int rc;
|
||||
|
||||
if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX))
|
||||
if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) {
|
||||
if (hpriv->irq_handler)
|
||||
dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set \
|
||||
and custom irq handler implemented\n");
|
||||
|
||||
rc = ahci_host_activate_multi_irqs(host, sht);
|
||||
else if (hpriv->flags & AHCI_HFLAG_EDGE_IRQ)
|
||||
rc = ata_host_activate(host, irq, ahci_single_edge_irq_intr,
|
||||
IRQF_SHARED, sht);
|
||||
else
|
||||
rc = ata_host_activate(host, irq, ahci_single_level_irq_intr,
|
||||
} else {
|
||||
rc = ata_host_activate(host, irq, hpriv->irq_handler,
|
||||
IRQF_SHARED, sht);
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ahci_host_activate);
|
||||
|
|
|
@ -675,19 +675,18 @@ static int ata_ioc32(struct ata_port *ap)
|
|||
int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
|
||||
int cmd, void __user *arg)
|
||||
{
|
||||
int val = -EINVAL, rc = -EINVAL;
|
||||
unsigned long val;
|
||||
int rc = -EINVAL;
|
||||
unsigned long flags;
|
||||
|
||||
switch (cmd) {
|
||||
case ATA_IOC_GET_IO32:
|
||||
case HDIO_GET_32BIT:
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
val = ata_ioc32(ap);
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
if (copy_to_user(arg, &val, 1))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
return put_user(val, (unsigned long __user *)arg);
|
||||
|
||||
case ATA_IOC_SET_IO32:
|
||||
case HDIO_SET_32BIT:
|
||||
val = (unsigned long) arg;
|
||||
rc = 0;
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <linux/libata.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
||||
#include <asm/mach-rc32434/rb.h>
|
||||
|
||||
#define DRV_NAME "pata-rb532-cf"
|
||||
#define DRV_VERSION "0.1.0"
|
||||
#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
|
||||
|
@ -107,6 +109,7 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
|
|||
int gpio;
|
||||
struct resource *res;
|
||||
struct ata_host *ah;
|
||||
struct cf_device *pdata;
|
||||
struct rb532_cf_info *info;
|
||||
int ret;
|
||||
|
||||
|
@ -122,7 +125,13 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
gpio = irq_to_gpio(irq);
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "no platform data specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio = pdata->gpio_pin;
|
||||
if (gpio < 0) {
|
||||
dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
|
||||
return -ENOENT;
|
||||
|
|
|
@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map)
|
|||
int i, j;
|
||||
int ret;
|
||||
int count;
|
||||
unsigned int val;
|
||||
unsigned int reg, val;
|
||||
void *tmp_buf;
|
||||
|
||||
if (!map->num_reg_defaults_raw)
|
||||
|
@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map)
|
|||
ret = regmap_raw_read(map, 0, tmp_buf,
|
||||
map->num_reg_defaults_raw);
|
||||
map->cache_bypass = cache_bypass;
|
||||
if (ret < 0)
|
||||
goto err_cache_free;
|
||||
|
||||
map->reg_defaults_raw = tmp_buf;
|
||||
map->cache_free = 1;
|
||||
if (ret == 0) {
|
||||
map->reg_defaults_raw = tmp_buf;
|
||||
map->cache_free = 1;
|
||||
} else {
|
||||
kfree(tmp_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* fill the reg_defaults */
|
||||
for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
|
||||
if (regmap_volatile(map, i * map->reg_stride))
|
||||
reg = i * map->reg_stride;
|
||||
|
||||
if (!regmap_readable(map, reg))
|
||||
continue;
|
||||
val = regcache_get_val(map, map->reg_defaults_raw, i);
|
||||
map->reg_defaults[j].reg = i * map->reg_stride;
|
||||
|
||||
if (regmap_volatile(map, reg))
|
||||
continue;
|
||||
|
||||
if (map->reg_defaults_raw) {
|
||||
val = regcache_get_val(map, map->reg_defaults_raw, i);
|
||||
} else {
|
||||
bool cache_bypass = map->cache_bypass;
|
||||
|
||||
map->cache_bypass = true;
|
||||
ret = regmap_read(map, reg, &val);
|
||||
map->cache_bypass = cache_bypass;
|
||||
if (ret != 0) {
|
||||
dev_err(map->dev, "Failed to read %d: %d\n",
|
||||
reg, ret);
|
||||
goto err_free;
|
||||
}
|
||||
}
|
||||
|
||||
map->reg_defaults[j].reg = reg;
|
||||
map->reg_defaults[j].def = val;
|
||||
j++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_cache_free:
|
||||
kfree(tmp_buf);
|
||||
err_free:
|
||||
kfree(map->reg_defaults);
|
||||
|
||||
|
|
|
@ -25,26 +25,14 @@
|
|||
|
||||
struct regmap_mmio_context {
|
||||
void __iomem *regs;
|
||||
unsigned reg_bytes;
|
||||
unsigned val_bytes;
|
||||
unsigned pad_bytes;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static inline void regmap_mmio_regsize_check(size_t reg_size)
|
||||
{
|
||||
switch (reg_size) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
#ifdef CONFIG_64BIT
|
||||
case 8:
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
void (*reg_write)(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg, unsigned int val);
|
||||
unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg);
|
||||
};
|
||||
|
||||
static int regmap_mmio_regbits_check(size_t reg_bits)
|
||||
{
|
||||
|
@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits)
|
|||
return min_stride;
|
||||
}
|
||||
|
||||
static inline void regmap_mmio_count_check(size_t count, u32 offset)
|
||||
static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
BUG_ON(count <= offset);
|
||||
writeb(val, ctx->regs + reg);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
regmap_mmio_get_offset(const void *reg, size_t reg_size)
|
||||
static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
switch (reg_size) {
|
||||
case 1:
|
||||
return *(u8 *)reg;
|
||||
case 2:
|
||||
return *(u16 *)reg;
|
||||
case 4:
|
||||
return *(u32 *)reg;
|
||||
writew(val, ctx->regs + reg);
|
||||
}
|
||||
|
||||
static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
iowrite16be(val, ctx->regs + reg);
|
||||
}
|
||||
|
||||
static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
writel(val, ctx->regs + reg);
|
||||
}
|
||||
|
||||
static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
iowrite32be(val, ctx->regs + reg);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
case 8:
|
||||
return *(u64 *)reg;
|
||||
#endif
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
writeq(val, ctx->regs + reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int regmap_mmio_gather_write(void *context,
|
||||
const void *reg, size_t reg_size,
|
||||
const void *val, size_t val_size)
|
||||
static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
|
||||
{
|
||||
struct regmap_mmio_context *ctx = context;
|
||||
unsigned int offset;
|
||||
int ret;
|
||||
|
||||
regmap_mmio_regsize_check(reg_size);
|
||||
|
||||
if (!IS_ERR(ctx->clk)) {
|
||||
ret = clk_enable(ctx->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
offset = regmap_mmio_get_offset(reg, reg_size);
|
||||
|
||||
while (val_size) {
|
||||
switch (ctx->val_bytes) {
|
||||
case 1:
|
||||
writeb(*(u8 *)val, ctx->regs + offset);
|
||||
break;
|
||||
case 2:
|
||||
writew(*(u16 *)val, ctx->regs + offset);
|
||||
break;
|
||||
case 4:
|
||||
writel(*(u32 *)val, ctx->regs + offset);
|
||||
break;
|
||||
#ifdef CONFIG_64BIT
|
||||
case 8:
|
||||
writeq(*(u64 *)val, ctx->regs + offset);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Should be caught by regmap_mmio_check_config */
|
||||
BUG();
|
||||
}
|
||||
val_size -= ctx->val_bytes;
|
||||
val += ctx->val_bytes;
|
||||
offset += ctx->val_bytes;
|
||||
}
|
||||
ctx->reg_write(ctx, reg, val);
|
||||
|
||||
if (!IS_ERR(ctx->clk))
|
||||
clk_disable(ctx->clk);
|
||||
|
@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int regmap_mmio_write(void *context, const void *data, size_t count)
|
||||
static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg)
|
||||
{
|
||||
struct regmap_mmio_context *ctx = context;
|
||||
unsigned int offset = ctx->reg_bytes + ctx->pad_bytes;
|
||||
|
||||
regmap_mmio_count_check(count, offset);
|
||||
|
||||
return regmap_mmio_gather_write(context, data, ctx->reg_bytes,
|
||||
data + offset, count - offset);
|
||||
return readb(ctx->regs + reg);
|
||||
}
|
||||
|
||||
static int regmap_mmio_read(void *context,
|
||||
const void *reg, size_t reg_size,
|
||||
void *val, size_t val_size)
|
||||
static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg)
|
||||
{
|
||||
return readw(ctx->regs + reg);
|
||||
}
|
||||
|
||||
static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg)
|
||||
{
|
||||
return ioread16be(ctx->regs + reg);
|
||||
}
|
||||
|
||||
static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg)
|
||||
{
|
||||
return readl(ctx->regs + reg);
|
||||
}
|
||||
|
||||
static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg)
|
||||
{
|
||||
return ioread32be(ctx->regs + reg);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
|
||||
unsigned int reg)
|
||||
{
|
||||
return readq(ctx->regs + reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
|
||||
{
|
||||
struct regmap_mmio_context *ctx = context;
|
||||
unsigned int offset;
|
||||
int ret;
|
||||
|
||||
regmap_mmio_regsize_check(reg_size);
|
||||
|
||||
if (!IS_ERR(ctx->clk)) {
|
||||
ret = clk_enable(ctx->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
offset = regmap_mmio_get_offset(reg, reg_size);
|
||||
|
||||
while (val_size) {
|
||||
switch (ctx->val_bytes) {
|
||||
case 1:
|
||||
*(u8 *)val = readb(ctx->regs + offset);
|
||||
break;
|
||||
case 2:
|
||||
*(u16 *)val = readw(ctx->regs + offset);
|
||||
break;
|
||||
case 4:
|
||||
*(u32 *)val = readl(ctx->regs + offset);
|
||||
break;
|
||||
#ifdef CONFIG_64BIT
|
||||
case 8:
|
||||
*(u64 *)val = readq(ctx->regs + offset);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* Should be caught by regmap_mmio_check_config */
|
||||
BUG();
|
||||
}
|
||||
val_size -= ctx->val_bytes;
|
||||
val += ctx->val_bytes;
|
||||
offset += ctx->val_bytes;
|
||||
}
|
||||
*val = ctx->reg_read(ctx, reg);
|
||||
|
||||
if (!IS_ERR(ctx->clk))
|
||||
clk_disable(ctx->clk);
|
||||
|
@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context)
|
|||
kfree(context);
|
||||
}
|
||||
|
||||
static struct regmap_bus regmap_mmio = {
|
||||
static const struct regmap_bus regmap_mmio = {
|
||||
.fast_io = true,
|
||||
.write = regmap_mmio_write,
|
||||
.gather_write = regmap_mmio_gather_write,
|
||||
.read = regmap_mmio_read,
|
||||
.reg_write = regmap_mmio_write,
|
||||
.reg_read = regmap_mmio_read,
|
||||
.free_context = regmap_mmio_free_context,
|
||||
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
||||
};
|
||||
|
||||
static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
|
||||
|
@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
|
|||
if (config->reg_stride < min_stride)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
switch (config->reg_format_endian) {
|
||||
case REGMAP_ENDIAN_DEFAULT:
|
||||
case REGMAP_ENDIAN_NATIVE:
|
||||
break;
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ctx->regs = regs;
|
||||
ctx->val_bytes = config->val_bits / 8;
|
||||
ctx->reg_bytes = config->reg_bits / 8;
|
||||
ctx->pad_bytes = config->pad_bits / 8;
|
||||
ctx->clk = ERR_PTR(-ENODEV);
|
||||
|
||||
switch (config->reg_format_endian) {
|
||||
case REGMAP_ENDIAN_DEFAULT:
|
||||
case REGMAP_ENDIAN_LITTLE:
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
case REGMAP_ENDIAN_NATIVE:
|
||||
#endif
|
||||
switch (config->val_bits) {
|
||||
case 8:
|
||||
ctx->reg_read = regmap_mmio_read8;
|
||||
ctx->reg_write = regmap_mmio_write8;
|
||||
break;
|
||||
case 16:
|
||||
ctx->reg_read = regmap_mmio_read16le;
|
||||
ctx->reg_write = regmap_mmio_write16le;
|
||||
break;
|
||||
case 32:
|
||||
ctx->reg_read = regmap_mmio_read32le;
|
||||
ctx->reg_write = regmap_mmio_write32le;
|
||||
break;
|
||||
#ifdef CONFIG_64BIT
|
||||
case 64:
|
||||
ctx->reg_read = regmap_mmio_read64le;
|
||||
ctx->reg_write = regmap_mmio_write64le;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err_free;
|
||||
}
|
||||
break;
|
||||
case REGMAP_ENDIAN_BIG:
|
||||
#ifdef __BIG_ENDIAN
|
||||
case REGMAP_ENDIAN_NATIVE:
|
||||
#endif
|
||||
switch (config->val_bits) {
|
||||
case 8:
|
||||
ctx->reg_read = regmap_mmio_read8;
|
||||
ctx->reg_write = regmap_mmio_write8;
|
||||
break;
|
||||
case 16:
|
||||
ctx->reg_read = regmap_mmio_read16be;
|
||||
ctx->reg_write = regmap_mmio_write16be;
|
||||
break;
|
||||
case 32:
|
||||
ctx->reg_read = regmap_mmio_read32be;
|
||||
ctx->reg_write = regmap_mmio_write32be;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err_free;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (clk_id == NULL)
|
||||
return ctx;
|
||||
|
||||
|
|
|
@ -557,6 +557,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev,
|
|||
endian = REGMAP_ENDIAN_BIG;
|
||||
else if (of_property_read_bool(np, "little-endian"))
|
||||
endian = REGMAP_ENDIAN_LITTLE;
|
||||
else if (of_property_read_bool(np, "native-endian"))
|
||||
endian = REGMAP_ENDIAN_NATIVE;
|
||||
|
||||
/* If the endianness was specified in DT, use that */
|
||||
if (endian != REGMAP_ENDIAN_DEFAULT)
|
||||
|
@ -1690,100 +1692,63 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
|
|||
EXPORT_SYMBOL_GPL(regmap_raw_write);
|
||||
|
||||
/**
|
||||
* regmap_field_write(): Write a value to a single register field
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @val: Value to be written
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_field_write(struct regmap_field *field, unsigned int val)
|
||||
{
|
||||
return regmap_update_bits(field->regmap, field->reg,
|
||||
field->mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_write);
|
||||
|
||||
/**
|
||||
* regmap_field_update_bits(): Perform a read/modify/write cycle
|
||||
* on the register field
|
||||
* regmap_field_update_bits_base():
|
||||
* Perform a read/modify/write cycle on the register field
|
||||
* with change, async, force option
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @mask: Bitmask to change
|
||||
* @val: Value to be written
|
||||
* @change: Boolean indicating if a write was done
|
||||
* @async: Boolean indicating asynchronously
|
||||
* @force: Boolean indicating use force update
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val)
|
||||
int regmap_field_update_bits_base(struct regmap_field *field,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change, bool async, bool force)
|
||||
{
|
||||
mask = (mask << field->shift) & field->mask;
|
||||
|
||||
return regmap_update_bits(field->regmap, field->reg,
|
||||
mask, val << field->shift);
|
||||
return regmap_update_bits_base(field->regmap, field->reg,
|
||||
mask, val << field->shift,
|
||||
change, async, force);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_field_update_bits);
|
||||
EXPORT_SYMBOL_GPL(regmap_field_update_bits_base);
|
||||
|
||||
/**
|
||||
* regmap_fields_write(): Write a value to a single register field with port ID
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @id: port ID
|
||||
* @val: Value to be written
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_fields_write(struct regmap_field *field, unsigned int id,
|
||||
unsigned int val)
|
||||
{
|
||||
if (id >= field->id_size)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_update_bits(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
field->mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_write);
|
||||
|
||||
int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
|
||||
unsigned int val)
|
||||
{
|
||||
if (id >= field->id_size)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_write_bits(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
field->mask, val << field->shift);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_force_write);
|
||||
|
||||
/**
|
||||
* regmap_fields_update_bits(): Perform a read/modify/write cycle
|
||||
* on the register field
|
||||
* regmap_fields_update_bits_base():
|
||||
* Perform a read/modify/write cycle on the register field
|
||||
* with change, async, force option
|
||||
*
|
||||
* @field: Register field to write to
|
||||
* @id: port ID
|
||||
* @mask: Bitmask to change
|
||||
* @val: Value to be written
|
||||
* @change: Boolean indicating if a write was done
|
||||
* @async: Boolean indicating asynchronously
|
||||
* @force: Boolean indicating use force update
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
*/
|
||||
int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
|
||||
unsigned int mask, unsigned int val)
|
||||
int regmap_fields_update_bits_base(struct regmap_field *field, unsigned int id,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change, bool async, bool force)
|
||||
{
|
||||
if (id >= field->id_size)
|
||||
return -EINVAL;
|
||||
|
||||
mask = (mask << field->shift) & field->mask;
|
||||
|
||||
return regmap_update_bits(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
mask, val << field->shift);
|
||||
return regmap_update_bits_base(field->regmap,
|
||||
field->reg + (field->id_offset * id),
|
||||
mask, val << field->shift,
|
||||
change, async, force);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_update_bits);
|
||||
EXPORT_SYMBOL_GPL(regmap_fields_update_bits_base);
|
||||
|
||||
/*
|
||||
* regmap_bulk_write(): Write multiple registers to the device
|
||||
|
@ -2253,6 +2218,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
|
|||
|
||||
WARN_ON(!map->bus);
|
||||
|
||||
if (!map->bus || !map->bus->read)
|
||||
return -EINVAL;
|
||||
|
||||
range = _regmap_range_lookup(map, reg);
|
||||
if (range) {
|
||||
ret = _regmap_select_page(map, ®, range,
|
||||
|
@ -2648,27 +2616,44 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
|
|||
}
|
||||
|
||||
/**
|
||||
* regmap_update_bits: Perform a read/modify/write cycle on the register map
|
||||
* regmap_update_bits_base:
|
||||
* Perform a read/modify/write cycle on the
|
||||
* register map with change, async, force option
|
||||
*
|
||||
* @map: Register map to update
|
||||
* @reg: Register to update
|
||||
* @mask: Bitmask to change
|
||||
* @val: New value for bitmask
|
||||
* @change: Boolean indicating if a write was done
|
||||
* @async: Boolean indicating asynchronously
|
||||
* @force: Boolean indicating use force update
|
||||
*
|
||||
* if async was true,
|
||||
* With most buses the read must be done synchronously so this is most
|
||||
* useful for devices with a cache which do not need to interact with
|
||||
* the hardware to determine the current register value.
|
||||
*
|
||||
* Returns zero for success, a negative number on error.
|
||||
*/
|
||||
int regmap_update_bits(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
int regmap_update_bits_base(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change, bool async, bool force)
|
||||
{
|
||||
int ret;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
|
||||
|
||||
map->async = async;
|
||||
|
||||
ret = _regmap_update_bits(map, reg, mask, val, change, force);
|
||||
|
||||
map->async = false;
|
||||
|
||||
map->unlock(map->lock_arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_update_bits);
|
||||
EXPORT_SYMBOL_GPL(regmap_update_bits_base);
|
||||
|
||||
/**
|
||||
* regmap_write_bits: Perform a read/modify/write cycle on the register map
|
||||
|
@ -2693,102 +2678,6 @@ int regmap_write_bits(struct regmap *map, unsigned int reg,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_write_bits);
|
||||
|
||||
/**
|
||||
* regmap_update_bits_async: Perform a read/modify/write cycle on the register
|
||||
* map asynchronously
|
||||
*
|
||||
* @map: Register map to update
|
||||
* @reg: Register to update
|
||||
* @mask: Bitmask to change
|
||||
* @val: New value for bitmask
|
||||
*
|
||||
* With most buses the read must be done synchronously so this is most
|
||||
* useful for devices with a cache which do not need to interact with
|
||||
* the hardware to determine the current register value.
|
||||
*
|
||||
* Returns zero for success, a negative number on error.
|
||||
*/
|
||||
int regmap_update_bits_async(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
|
||||
map->async = true;
|
||||
|
||||
ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
|
||||
|
||||
map->async = false;
|
||||
|
||||
map->unlock(map->lock_arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_update_bits_async);
|
||||
|
||||
/**
|
||||
* regmap_update_bits_check: Perform a read/modify/write cycle on the
|
||||
* register map and report if updated
|
||||
*
|
||||
* @map: Register map to update
|
||||
* @reg: Register to update
|
||||
* @mask: Bitmask to change
|
||||
* @val: New value for bitmask
|
||||
* @change: Boolean indicating if a write was done
|
||||
*
|
||||
* Returns zero for success, a negative number on error.
|
||||
*/
|
||||
int regmap_update_bits_check(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change)
|
||||
{
|
||||
int ret;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
ret = _regmap_update_bits(map, reg, mask, val, change, false);
|
||||
map->unlock(map->lock_arg);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_update_bits_check);
|
||||
|
||||
/**
|
||||
* regmap_update_bits_check_async: Perform a read/modify/write cycle on the
|
||||
* register map asynchronously and report if
|
||||
* updated
|
||||
*
|
||||
* @map: Register map to update
|
||||
* @reg: Register to update
|
||||
* @mask: Bitmask to change
|
||||
* @val: New value for bitmask
|
||||
* @change: Boolean indicating if a write was done
|
||||
*
|
||||
* With most buses the read must be done synchronously so this is most
|
||||
* useful for devices with a cache which do not need to interact with
|
||||
* the hardware to determine the current register value.
|
||||
*
|
||||
* Returns zero for success, a negative number on error.
|
||||
*/
|
||||
int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change)
|
||||
{
|
||||
int ret;
|
||||
|
||||
map->lock(map->lock_arg);
|
||||
|
||||
map->async = true;
|
||||
|
||||
ret = _regmap_update_bits(map, reg, mask, val, change, false);
|
||||
|
||||
map->async = false;
|
||||
|
||||
map->unlock(map->lock_arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regmap_update_bits_check_async);
|
||||
|
||||
void regmap_async_complete_cb(struct regmap_async *async, int ret)
|
||||
{
|
||||
struct regmap *map = async->map;
|
||||
|
|
|
@ -296,6 +296,7 @@ endif
|
|||
config QORIQ_CPUFREQ
|
||||
tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
|
||||
depends on OF && COMMON_CLK && (PPC_E500MC || ARM)
|
||||
depends on !CPU_THERMAL || THERMAL
|
||||
select CLK_QORIQ
|
||||
help
|
||||
This adds the CPUFreq driver support for Freescale QorIQ SoCs
|
||||
|
|
|
@ -84,10 +84,10 @@ config ARM_KIRKWOOD_CPUFREQ
|
|||
SoCs.
|
||||
|
||||
config ARM_MT8173_CPUFREQ
|
||||
bool "Mediatek MT8173 CPUFreq support"
|
||||
tristate "Mediatek MT8173 CPUFreq support"
|
||||
depends on ARCH_MEDIATEK && REGULATOR
|
||||
depends on ARM64 || (ARM_CPU_TOPOLOGY && COMPILE_TEST)
|
||||
depends on !CPU_THERMAL || THERMAL=y
|
||||
depends on !CPU_THERMAL || THERMAL
|
||||
select PM_OPP
|
||||
help
|
||||
This adds the CPUFreq driver support for Mediatek MT8173 SoC.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/cpu_cooling.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
|
|
|
@ -583,6 +583,8 @@ static void set_updater_desc(struct pxad_desc_sw *sw_desc,
|
|||
(PXA_DCMD_LENGTH & sizeof(u32));
|
||||
if (flags & DMA_PREP_INTERRUPT)
|
||||
updater->dcmd |= PXA_DCMD_ENDIRQEN;
|
||||
if (sw_desc->cyclic)
|
||||
sw_desc->hw_desc[sw_desc->nb_desc - 2]->ddadr = sw_desc->first;
|
||||
}
|
||||
|
||||
static bool is_desc_completed(struct virt_dma_desc *vd)
|
||||
|
@ -673,6 +675,10 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id)
|
|||
dev_dbg(&chan->vc.chan.dev->device,
|
||||
"%s(): checking txd %p[%x]: completed=%d\n",
|
||||
__func__, vd, vd->tx.cookie, is_desc_completed(vd));
|
||||
if (to_pxad_sw_desc(vd)->cyclic) {
|
||||
vchan_cyclic_callback(vd);
|
||||
break;
|
||||
}
|
||||
if (is_desc_completed(vd)) {
|
||||
list_del(&vd->node);
|
||||
vchan_cookie_complete(vd);
|
||||
|
@ -1080,7 +1086,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dchan,
|
|||
return NULL;
|
||||
|
||||
pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr);
|
||||
dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH | period_len);
|
||||
dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH & period_len);
|
||||
dev_dbg(&chan->vc.chan.dev->device,
|
||||
"%s(): buf_addr=0x%lx len=%zu period=%zu dir=%d flags=%lx\n",
|
||||
__func__, (unsigned long)buf_addr, len, period_len, dir, flags);
|
||||
|
|
|
@ -196,6 +196,44 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_rcar_irq_bus_lock(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = gpiochip_get_data(gc);
|
||||
|
||||
pm_runtime_get_sync(&p->pdev->dev);
|
||||
}
|
||||
|
||||
static void gpio_rcar_irq_bus_sync_unlock(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = gpiochip_get_data(gc);
|
||||
|
||||
pm_runtime_put(&p->pdev->dev);
|
||||
}
|
||||
|
||||
|
||||
static int gpio_rcar_irq_request_resources(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = gpiochip_get_data(gc);
|
||||
int error;
|
||||
|
||||
error = pm_runtime_get_sync(&p->pdev->dev);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpio_rcar_irq_release_resources(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_rcar_priv *p = gpiochip_get_data(gc);
|
||||
|
||||
pm_runtime_put(&p->pdev->dev);
|
||||
}
|
||||
|
||||
static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct gpio_rcar_priv *p = dev_id;
|
||||
|
@ -450,6 +488,10 @@ static int gpio_rcar_probe(struct platform_device *pdev)
|
|||
irq_chip->irq_unmask = gpio_rcar_irq_enable;
|
||||
irq_chip->irq_set_type = gpio_rcar_irq_set_type;
|
||||
irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
|
||||
irq_chip->irq_bus_lock = gpio_rcar_irq_bus_lock;
|
||||
irq_chip->irq_bus_sync_unlock = gpio_rcar_irq_bus_sync_unlock;
|
||||
irq_chip->irq_request_resources = gpio_rcar_irq_request_resources;
|
||||
irq_chip->irq_release_resources = gpio_rcar_irq_release_resources;
|
||||
irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
|
||||
|
||||
ret = gpiochip_add_data(gpio_chip, p);
|
||||
|
|
|
@ -77,7 +77,7 @@ void amdgpu_connector_hotplug(struct drm_connector *connector)
|
|||
} else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) {
|
||||
/* Don't try to start link training before we
|
||||
* have the dpcd */
|
||||
if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
|
||||
if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
|
||||
return;
|
||||
|
||||
/* set it to OFF so that drm_helper_connector_dpms()
|
||||
|
|
|
@ -649,9 +649,6 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
|
|||
/* update display watermarks based on new power state */
|
||||
amdgpu_display_bandwidth_update(adev);
|
||||
|
||||
adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
|
||||
adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
|
||||
|
||||
/* wait for the rings to drain */
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
|
@ -670,6 +667,9 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
|
|||
/* update displays */
|
||||
amdgpu_dpm_display_configuration_changed(adev);
|
||||
|
||||
adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
|
||||
adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
|
||||
|
||||
if (adev->pm.funcs->force_performance_level) {
|
||||
if (adev->pm.dpm.thermal_active) {
|
||||
enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
|
||||
|
|
|
@ -143,8 +143,10 @@ static int amdgpu_pp_late_init(void *handle)
|
|||
adev->powerplay.pp_handle);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_POWERPLAY
|
||||
if (adev->pp_enabled)
|
||||
if (adev->pp_enabled) {
|
||||
amdgpu_pm_sysfs_init(adev);
|
||||
amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2202,8 +2202,7 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
|
|||
AMD_PG_STATE_GATE);
|
||||
|
||||
cz_enable_vce_dpm(adev, false);
|
||||
/* TODO: to figure out why vce can't be poweroff. */
|
||||
/* cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF); */
|
||||
cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF);
|
||||
pi->vce_power_gated = true;
|
||||
} else {
|
||||
cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerON);
|
||||
|
@ -2226,10 +2225,8 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
|
|||
}
|
||||
} else { /*pi->caps_vce_pg*/
|
||||
cz_update_vce_dpm(adev);
|
||||
cz_enable_vce_dpm(adev, true);
|
||||
cz_enable_vce_dpm(adev, !gate);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const struct amd_ip_funcs cz_dpm_ip_funcs = {
|
||||
|
|
|
@ -3628,6 +3628,19 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
|||
unsigned vm_id, uint64_t pd_addr)
|
||||
{
|
||||
int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
|
||||
uint32_t seq = ring->fence_drv.sync_seq;
|
||||
uint64_t addr = ring->fence_drv.gpu_addr;
|
||||
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
|
||||
amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
|
||||
WAIT_REG_MEM_FUNCTION(3) | /* equal */
|
||||
WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */
|
||||
amdgpu_ring_write(ring, addr & 0xfffffffc);
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
|
||||
amdgpu_ring_write(ring, seq);
|
||||
amdgpu_ring_write(ring, 0xffffffff);
|
||||
amdgpu_ring_write(ring, 4); /* poll interval */
|
||||
|
||||
if (usepfp) {
|
||||
/* synce CE with ME to prevent CE fetch CEIB before context switch done */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
|
|
|
@ -4809,7 +4809,8 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
|
|||
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
|
||||
amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
|
||||
WAIT_REG_MEM_FUNCTION(3))); /* equal */
|
||||
WAIT_REG_MEM_FUNCTION(3) | /* equal */
|
||||
WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */
|
||||
amdgpu_ring_write(ring, addr & 0xfffffffc);
|
||||
amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
|
||||
amdgpu_ring_write(ring, seq);
|
||||
|
|
|
@ -402,8 +402,11 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input,
|
|||
|
||||
data.requested_ui_label = power_state_convert(ps);
|
||||
ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AMD_PP_EVENT_COMPLETE_INIT:
|
||||
ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -165,6 +165,7 @@ const struct action_chain resume_action_chain = {
|
|||
};
|
||||
|
||||
static const pem_event_action *complete_init_event[] = {
|
||||
unblock_adjust_power_state_tasks,
|
||||
adjust_power_state_tasks,
|
||||
enable_gfx_clock_gating_tasks,
|
||||
enable_gfx_voltage_island_power_gating_tasks,
|
||||
|
|
|
@ -226,7 +226,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
|
|||
}
|
||||
} else {
|
||||
cz_dpm_update_vce_dpm(hwmgr);
|
||||
cz_enable_disable_vce_dpm(hwmgr, true);
|
||||
cz_enable_disable_vce_dpm(hwmgr, !bgate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ static int ast_get_dram_info(struct drm_device *dev)
|
|||
} while (ast_read32(ast, 0x10000) != 0x01);
|
||||
data = ast_read32(ast, 0x10004);
|
||||
|
||||
if (data & 0x400)
|
||||
if (data & 0x40)
|
||||
ast->dram_bus_width = 16;
|
||||
else
|
||||
ast->dram_bus_width = 32;
|
||||
|
|
|
@ -2303,15 +2303,15 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
|
|||
*/
|
||||
void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
|
||||
skl_display_core_uninit(dev_priv);
|
||||
|
||||
/*
|
||||
* Even if power well support was disabled we still want to disable
|
||||
* power wells while we are system suspended.
|
||||
*/
|
||||
if (!i915.disable_power_well)
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
|
||||
skl_display_core_uninit(dev_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2349,22 +2349,20 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
|
|||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct device *device = &dev->pdev->dev;
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PM))
|
||||
return true;
|
||||
if (IS_ENABLED(CONFIG_PM)) {
|
||||
int ret = pm_runtime_get_if_in_use(device);
|
||||
|
||||
ret = pm_runtime_get_if_in_use(device);
|
||||
|
||||
/*
|
||||
* In cases runtime PM is disabled by the RPM core and we get an
|
||||
* -EINVAL return value we are not supposed to call this function,
|
||||
* since the power state is undefined. This applies atm to the
|
||||
* late/early system suspend/resume handlers.
|
||||
*/
|
||||
WARN_ON_ONCE(ret < 0);
|
||||
if (ret <= 0)
|
||||
return false;
|
||||
/*
|
||||
* In cases runtime PM is disabled by the RPM core and we get
|
||||
* an -EINVAL return value we are not supposed to call this
|
||||
* function, since the power state is undefined. This applies
|
||||
* atm to the late/early system suspend/resume handlers.
|
||||
*/
|
||||
WARN_ON_ONCE(ret < 0);
|
||||
if (ret <= 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
atomic_inc(&dev_priv->pm.wakeref_count);
|
||||
assert_rpm_wakelock_held(dev_priv);
|
||||
|
|
|
@ -1080,10 +1080,6 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
|
|||
/* update display watermarks based on new power state */
|
||||
radeon_bandwidth_update(rdev);
|
||||
|
||||
rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
|
||||
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
|
||||
rdev->pm.dpm.single_display = single_display;
|
||||
|
||||
/* wait for the rings to drain */
|
||||
for (i = 0; i < RADEON_NUM_RINGS; i++) {
|
||||
struct radeon_ring *ring = &rdev->ring[i];
|
||||
|
@ -1102,6 +1098,10 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev)
|
|||
/* update displays */
|
||||
radeon_dpm_display_configuration_changed(rdev);
|
||||
|
||||
rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
|
||||
rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
|
||||
rdev->pm.dpm.single_display = single_display;
|
||||
|
||||
if (rdev->asic->dpm.force_performance_level) {
|
||||
if (rdev->pm.dpm.thermal_active) {
|
||||
enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/host1x.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include "bus.h"
|
||||
#include "dev.h"
|
||||
|
@ -394,6 +395,7 @@ static int host1x_device_add(struct host1x *host1x,
|
|||
device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
|
||||
device->dev.dma_mask = &device->dev.coherent_dma_mask;
|
||||
dev_set_name(&device->dev, "%s", driver->driver.name);
|
||||
of_dma_configure(&device->dev, host1x->dev->of_node);
|
||||
device->dev.release = host1x_device_release;
|
||||
device->dev.bus = &host1x_bus_type;
|
||||
device->dev.parent = host1x->dev;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/host1x.h>
|
||||
|
@ -68,6 +69,7 @@ static const struct host1x_info host1x01_info = {
|
|||
.nb_bases = 8,
|
||||
.init = host1x01_init,
|
||||
.sync_offset = 0x3000,
|
||||
.dma_mask = DMA_BIT_MASK(32),
|
||||
};
|
||||
|
||||
static const struct host1x_info host1x02_info = {
|
||||
|
@ -77,6 +79,7 @@ static const struct host1x_info host1x02_info = {
|
|||
.nb_bases = 12,
|
||||
.init = host1x02_init,
|
||||
.sync_offset = 0x3000,
|
||||
.dma_mask = DMA_BIT_MASK(32),
|
||||
};
|
||||
|
||||
static const struct host1x_info host1x04_info = {
|
||||
|
@ -86,6 +89,7 @@ static const struct host1x_info host1x04_info = {
|
|||
.nb_bases = 64,
|
||||
.init = host1x04_init,
|
||||
.sync_offset = 0x2100,
|
||||
.dma_mask = DMA_BIT_MASK(34),
|
||||
};
|
||||
|
||||
static const struct host1x_info host1x05_info = {
|
||||
|
@ -95,6 +99,7 @@ static const struct host1x_info host1x05_info = {
|
|||
.nb_bases = 64,
|
||||
.init = host1x05_init,
|
||||
.sync_offset = 0x2100,
|
||||
.dma_mask = DMA_BIT_MASK(34),
|
||||
};
|
||||
|
||||
static struct of_device_id host1x_of_match[] = {
|
||||
|
@ -148,6 +153,8 @@ static int host1x_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(host->regs))
|
||||
return PTR_ERR(host->regs);
|
||||
|
||||
dma_set_mask_and_coherent(host->dev, host->info->dma_mask);
|
||||
|
||||
if (host->info->init) {
|
||||
err = host->info->init(host);
|
||||
if (err)
|
||||
|
|
|
@ -96,6 +96,7 @@ struct host1x_info {
|
|||
int nb_mlocks; /* host1x: number of mlocks */
|
||||
int (*init)(struct host1x *); /* initialize per SoC ops */
|
||||
int sync_offset;
|
||||
u64 dma_mask; /* mask of addressable memory */
|
||||
};
|
||||
|
||||
struct host1x {
|
||||
|
|
|
@ -586,8 +586,7 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
|
|||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(struct bsc_regs *),
|
||||
GFP_KERNEL);
|
||||
dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(*dev->bsc_regmap), GFP_KERNEL);
|
||||
if (!dev->bsc_regmap)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue