Merge ff49c86f27 ("Merge tag 'f2fs-for-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs") into android-mainline

Steps on the way to 5.11-rc1

Resolves conflicts in:
	drivers/soc/qcom/rpmh-rsc.c

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Idc5921088554d0eb5bed7eca94c7fd7ca0fa6fb5
This commit is contained in:
Greg Kroah-Hartman
2020-12-21 09:54:59 +01:00
251 changed files with 8616 additions and 3102 deletions

View File

@@ -370,3 +370,10 @@ Date: April 2020
Contact: "Daeho Jeong" <daehojeong@google.com>
Description: Give a way to change iostat_period time. 3secs by default.
The new iostat trace gives stats gap given the period.
What: /sys/fs/f2fs/<disk>/max_io_bytes
Date: December 2020
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description: This gives a control to limit the bio size in f2fs.
Default is zero, which will follow underlying block layer limit,
whereas, if it has a certain bytes value, f2fs won't submit a
bio larger than that size.

View File

@@ -2952,7 +2952,7 @@
mtdset= [ARM]
ARM/S3C2412 JIVE boot control
See arch/arm/mach-s3c2412/mach-jive.c
See arch/arm/mach-s3c/mach-jive.c
mtouchusb.raw_coordinates=
[HW] Make the MicroTouch USB driver use raw coordinates

View File

@@ -29,7 +29,7 @@ GPIOLIB
The following functions now either have a `s3c_` specific variant
or are merged into gpiolib. See the definitions in
arch/arm/plat-samsung/include/plat/gpio-cfg.h:
arch/arm/mach-s3c/gpio-cfg.h:
- s3c2410_gpio_setpin() gpio_set_value() or gpio_direction_output()
- s3c2410_gpio_getpin() gpio_get_value() or gpio_direction_input()
@@ -86,7 +86,7 @@ between the calls.
Headers
-------
See arch/arm/mach-s3c24xx/include/mach/regs-gpio.h for the list
See arch/arm/mach-s3c/regs-gpio-s3c24xx.h for the list
of GPIO pins, and the configuration values for them. This
is included by using #include <mach/regs-gpio.h>

View File

@@ -18,7 +18,7 @@ Introduction
versions.
The S3C2416 and S3C2450 devices are very similar and S3C2450 support is
included under the arch/arm/mach-s3c2416 directory. Note, while core
included under the arch/arm/mach-s3c directory. Note, while core
support for these SoCs is in, work on some of the extra peripherals
and extra interrupts is still ongoing.
@@ -37,19 +37,11 @@ Configuration
Layout
------
The core support files are located in the platform code contained in
arch/arm/plat-s3c24xx with headers in include/asm-arm/plat-s3c24xx.
This directory should be kept to items shared between the platform
code (arch/arm/plat-s3c24xx) and the arch/arm/mach-s3c24* code.
The core support files, register, kernel and paltform data are located in the
platform code contained in arch/arm/mach-s3c with headers in
arch/arm/mach-s3c/include
Each cpu has a directory with the support files for it, and the
machines that carry the device. For example S3C2410 is contained
in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
Register, kernel and platform data definitions are held in the
arch/arm/mach-s3c2410 directory./include/mach
arch/arm/plat-s3c24xx:
arch/arm/mach-s3c:
Files in here are either common to all the s3c24xx family,
or are common to only some of them with names to indicate this
@@ -134,7 +126,7 @@ Adding New Machines
should keep this in mind before altering items outside of their own
machine files.
Machine definitions should be kept in linux/arch/arm/mach-s3c2410,
Machine definitions should be kept in arch/arm/mach-s3c,
and there are a number of examples that can be looked at.
Read the kernel patch submission policies as well as the
@@ -293,7 +285,7 @@ Platform Data
}
Note, since the code is marked as __init, it should not be
exported outside arch/arm/mach-s3c2410/, or exported to
exported outside arch/arm/mach-s3c/, or exported to
modules via EXPORT_SYMBOL() and related functions.

View File

@@ -36,7 +36,7 @@ Board Support
-------------
The driver attaches to a platform device, which will need to be
added by the board specific support file in linux/arch/arm/mach-s3c2410,
added by the board specific support file in arch/arm/mach-s3c,
such as mach-bast.c or mach-smdk2410.c
The platform device's platform_data field is only needed if the
@@ -51,9 +51,9 @@ Board Support
Platform Data
-------------
See arch/arm/mach-s3c2410/include/mach/usb-control.h for the
See include/linux/platform_data/usb-ohci-s3c2410.h for the
descriptions of the platform device data. An implementation
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
can be found in arch/arm/mach-s3c/simtec-usb.c .
The `struct s3c2410_hcd_info` contains a pair of functions
that get called to enable over-current detection, and to

View File

@@ -37,5 +37,4 @@ implementation to configure pins as necessary.
The s3c_gpio_cfgpin() and s3c_gpio_setpull() provide the means for a
driver or machine to change gpio configuration.
See arch/arm/plat-samsung/include/plat/gpio-cfg.h for more information
on these functions.
See arch/arm/mach-s3c/gpio-cfg.h for more information on these functions.

View File

@@ -23,6 +23,7 @@ properties:
enum:
- qcom,sc7180-llcc
- qcom,sdm845-llcc
- qcom,sm8150-llcc
reg:
items:

View File

@@ -18,8 +18,30 @@ clock-names. See ../../clock/clock-bindings.txt for details.
../../reset/reset.txt for details.
- reset-names: Must include the following entries:
- actmon
- operating-points-v2: See ../bindings/opp/opp.txt for details.
- interconnects: Should contain entries for memory clients sitting on
MC->EMC memory interconnect path.
- interconnect-names: Should include name of the interconnect path for each
interconnect entry. Consult TRM documentation for
information about available memory clients, see MEMORY
CONTROLLER section.
For each opp entry in 'operating-points-v2' table:
- opp-supported-hw: bitfield indicating SoC speedo ID mask
- opp-peak-kBps: peak bandwidth of the memory channel
Example:
dfs_opp_table: opp-table {
compatible = "operating-points-v2";
opp@12750000 {
opp-hz = /bits/ 64 <12750000>;
opp-supported-hw = <0x000F>;
opp-peak-kBps = <51000>;
};
...
};
actmon@6000c800 {
compatible = "nvidia,tegra124-actmon";
reg = <0x0 0x6000c800 0x0 0x400>;
@@ -29,4 +51,7 @@ Example:
clock-names = "actmon", "emc";
resets = <&tegra_car 119>;
reset-names = "actmon";
operating-points-v2 = <&dfs_opp_table>;
interconnects = <&mc TEGRA124_MC_MPCORER &emc>;
interconnect-names = "cpu";
};

View File

@@ -20,6 +20,10 @@ Required properties:
- reset-names: Must include the following entries:
- host1x
Each host1x client module having to perform DMA through the Memory Controller
should have the interconnect endpoints set to the Memory Client and External
Memory respectively.
The host1x top-level node defines a number of children, each representing one
of the following host1x client modules:
@@ -36,6 +40,12 @@ of the following host1x client modules:
- reset-names: Must include the following entries:
- mpe
Optional properties:
- interconnects: Must contain entry for the MPE memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
- vi: video input
Required properties:
@@ -113,6 +123,12 @@ of the following host1x client modules:
Required properties:
- remote-endpoint: phandle to vi port 'endpoint' node.
Optional properties:
- interconnects: Must contain entry for the VI memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
- epp: encoder pre-processor
Required properties:
@@ -126,6 +142,12 @@ of the following host1x client modules:
- reset-names: Must include the following entries:
- epp
Optional properties:
- interconnects: Must contain entry for the EPP memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
- isp: image signal processor
Required properties:
@@ -139,6 +161,12 @@ of the following host1x client modules:
- reset-names: Must include the following entries:
- isp
Optional properties:
- interconnects: Must contain entry for the ISP memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
- gr2d: 2D graphics engine
Required properties:
@@ -152,6 +180,12 @@ of the following host1x client modules:
- reset-names: Must include the following entries:
- 2d
Optional properties:
- interconnects: Must contain entry for the GR2D memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
- gr3d: 3D graphics engine
Required properties:
@@ -170,6 +204,12 @@ of the following host1x client modules:
- 3d
- 3d2 (Only required on SoCs with two 3D clocks)
Optional properties:
- interconnects: Must contain entry for the GR3D memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
- dc: display controller
Required properties:
@@ -197,6 +237,10 @@ of the following host1x client modules:
- nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
- nvidia,edid: supplies a binary EDID blob
- nvidia,panel: phandle of a display panel
- interconnects: Must contain entry for the DC memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
- hdmi: High Definition Multimedia Interface
@@ -345,6 +389,12 @@ of the following host1x client modules:
- reset-names: Must include the following entries:
- vic
Optional properties:
- interconnects: Must contain entry for the VIC memory clients.
- interconnect-names: Must include name of the interconnect path for each
interconnect entry. Consult TRM documentation for information about
available memory clients, see MEMORY CONTROLLER section.
Example:
/ {
@@ -498,6 +548,15 @@ Example:
resets = <&tegra_car 27>;
reset-names = "dc";
interconnects = <&mc TEGRA20_MC_DISPLAY0A &emc>,
<&mc TEGRA20_MC_DISPLAY0B &emc>,
<&mc TEGRA20_MC_DISPLAY0C &emc>,
<&mc TEGRA20_MC_DISPLAYHC &emc>;
interconnect-names = "wina",
"winb",
"winc",
"cursor";
rgb {
status = "disabled";
};
@@ -513,6 +572,15 @@ Example:
resets = <&tegra_car 26>;
reset-names = "dc";
interconnects = <&mc TEGRA20_MC_DISPLAY0AB &emc>,
<&mc TEGRA20_MC_DISPLAY0BB &emc>,
<&mc TEGRA20_MC_DISPLAY0CB &emc>,
<&mc TEGRA20_MC_DISPLAYHCB &emc>;
interconnect-names = "wina",
"winb",
"winc",
"cursor";
rgb {
status = "disabled";
};

View File

@@ -1,50 +0,0 @@
SMI (Smart Multimedia Interface) Common
The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
Mediatek SMI have two generations of HW architecture, here is the list
which generation the SoCs use:
generation 1: mt2701 and mt7623.
generation 2: mt2712, mt6779, mt8167, mt8173 and mt8183.
There's slight differences between the two SMI, for generation 2, the
register which control the iommu port is at each larb's register base. But
for generation 1, the register is at smi ao base(smi always on register
base). Besides that, the smi async clock should be prepared and enabled for
SMI generation 1 to transform the smi clock into emi clock domain, but that is
not needed for SMI generation 2.
Required properties:
- compatible : must be one of :
"mediatek,mt2701-smi-common"
"mediatek,mt2712-smi-common"
"mediatek,mt6779-smi-common"
"mediatek,mt7623-smi-common", "mediatek,mt2701-smi-common"
"mediatek,mt8167-smi-common"
"mediatek,mt8173-smi-common"
"mediatek,mt8183-smi-common"
- reg : the register and size of the SMI block.
- power-domains : a phandle to the power domain of this local arbiter.
- clocks : Must contain an entry for each entry in clock-names.
- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
for generation 2 smi HW as follows:
- "apb" : Advanced Peripheral Bus clock, It's the clock for setting
the register.
- "smi" : It's the clock for transfer data and command.
They may be the same if both source clocks are the same.
- "async" : asynchronous clock, it help transform the smi clock into the emi
clock domain, this clock is only needed by generation 1 smi HW.
and these 2 option clocks for generation 2 smi HW:
- "gals0": the path0 clock of GALS(Global Async Local Sync).
- "gals1": the path1 clock of GALS(Global Async Local Sync).
Here is the list which has this GALS: mt6779 and mt8183.
Example:
smi_common: smi@14022000 {
compatible = "mediatek,mt8173-smi-common";
reg = <0 0x14022000 0 0x1000>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
clocks = <&mmsys CLK_MM_SMI_COMMON>,
<&mmsys CLK_MM_SMI_COMMON>;
clock-names = "apb", "smi";
};

View File

@@ -0,0 +1,142 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/mediatek,smi-common.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SMI (Smart Multimedia Interface) Common
maintainers:
- Yong Wu <yong.wu@mediatek.com>
description: |
The hardware block diagram please check bindings/iommu/mediatek,iommu.yaml
MediaTek SMI have two generations of HW architecture, here is the list
which generation the SoCs use:
generation 1: mt2701 and mt7623.
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183 and mt8192.
There's slight differences between the two SMI, for generation 2, the
register which control the iommu port is at each larb's register base. But
for generation 1, the register is at smi ao base(smi always on register
base). Besides that, the smi async clock should be prepared and enabled for
SMI generation 1 to transform the smi clock into emi clock domain, but that is
not needed for SMI generation 2.
properties:
compatible:
oneOf:
- enum:
- mediatek,mt2701-smi-common
- mediatek,mt2712-smi-common
- mediatek,mt6779-smi-common
- mediatek,mt8167-smi-common
- mediatek,mt8173-smi-common
- mediatek,mt8183-smi-common
- mediatek,mt8192-smi-common
- description: for mt7623
items:
- const: mediatek,mt7623-smi-common
- const: mediatek,mt2701-smi-common
reg:
maxItems: 1
power-domains:
maxItems: 1
clocks:
description: |
apb and smi are mandatory. the async is only for generation 1 smi HW.
gals(global async local sync) also is optional, see below.
minItems: 2
maxItems: 4
items:
- description: apb is Advanced Peripheral Bus clock, It's the clock for
setting the register.
- description: smi is the clock for transfer data and command.
- description: async is asynchronous clock, it help transform the smi
clock into the emi clock domain.
- description: gals0 is the path0 clock of gals.
- description: gals1 is the path1 clock of gals.
clock-names:
minItems: 2
maxItems: 4
required:
- compatible
- reg
- power-domains
- clocks
- clock-names
allOf:
- if: # only for gen1 HW
properties:
compatible:
contains:
enum:
- mediatek,mt2701-smi-common
then:
properties:
clock:
items:
minItems: 3
maxItems: 3
clock-names:
items:
- const: apb
- const: smi
- const: async
- if: # for gen2 HW that have gals
properties:
compatible:
enum:
- mediatek,mt6779-smi-common
- mediatek,mt8183-smi-common
- mediatek,mt8192-smi-common
then:
properties:
clock:
items:
minItems: 4
maxItems: 4
clock-names:
items:
- const: apb
- const: smi
- const: gals0
- const: gals1
else: # for gen2 HW that don't have gals
properties:
clock:
items:
minItems: 2
maxItems: 2
clock-names:
items:
- const: apb
- const: smi
additionalProperties: false
examples:
- |+
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/power/mt8173-power.h>
smi_common: smi@14022000 {
compatible = "mediatek,mt8173-smi-common";
reg = <0x14022000 0x1000>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
clocks = <&mmsys CLK_MM_SMI_COMMON>,
<&mmsys CLK_MM_SMI_COMMON>;
clock-names = "apb", "smi";
};

View File

@@ -1,50 +0,0 @@
SMI (Smart Multimedia Interface) Local Arbiter
The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
Required properties:
- compatible : must be one of :
"mediatek,mt2701-smi-larb"
"mediatek,mt2712-smi-larb"
"mediatek,mt6779-smi-larb"
"mediatek,mt7623-smi-larb", "mediatek,mt2701-smi-larb"
"mediatek,mt8167-smi-larb"
"mediatek,mt8173-smi-larb"
"mediatek,mt8183-smi-larb"
- reg : the register and size of this local arbiter.
- mediatek,smi : a phandle to the smi_common node.
- power-domains : a phandle to the power domain of this local arbiter.
- clocks : Must contain an entry for each entry in clock-names.
- clock-names: must contain 2 entries, as follows:
- "apb" : Advanced Peripheral Bus clock, It's the clock for setting
the register.
- "smi" : It's the clock for transfer data and command.
and this optional clock name:
- "gals": the clock for GALS(Global Async Local Sync).
Here is the list which has this GALS: mt8183.
Required property for mt2701, mt2712, mt6779, mt7623 and mt8167:
- mediatek,larb-id :the hardware id of this larb.
Example:
larb1: larb@16010000 {
compatible = "mediatek,mt8173-smi-larb";
reg = <0 0x16010000 0 0x1000>;
mediatek,smi = <&smi_common>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
clocks = <&vdecsys CLK_VDEC_CKEN>,
<&vdecsys CLK_VDEC_LARB_CKEN>;
clock-names = "apb", "smi";
};
Example for mt2701:
larb0: larb@14010000 {
compatible = "mediatek,mt2701-smi-larb";
reg = <0 0x14010000 0 0x1000>;
mediatek,smi = <&smi_common>;
mediatek,larb-id = <0>;
clocks = <&mmsys CLK_MM_SMI_LARB0>,
<&mmsys CLK_MM_SMI_LARB0>;
clock-names = "apb", "smi";
power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>;
};

View File

@@ -0,0 +1,132 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/mediatek,smi-larb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SMI (Smart Multimedia Interface) Local Arbiter
maintainers:
- Yong Wu <yong.wu@mediatek.com>
description: |
The hardware block diagram please check bindings/iommu/mediatek,iommu.yaml
properties:
compatible:
oneOf:
- enum:
- mediatek,mt2701-smi-larb
- mediatek,mt2712-smi-larb
- mediatek,mt6779-smi-larb
- mediatek,mt8167-smi-larb
- mediatek,mt8173-smi-larb
- mediatek,mt8183-smi-larb
- mediatek,mt8192-smi-larb
- description: for mt7623
items:
- const: mediatek,mt7623-smi-larb
- const: mediatek,mt2701-smi-larb
reg:
maxItems: 1
clocks:
description: |
apb and smi are mandatory. gals(global async local sync) is optional.
minItems: 2
maxItems: 3
items:
- description: apb is Advanced Peripheral Bus clock, It's the clock for
setting the register.
- description: smi is the clock for transfer data and command.
- description: the clock for gals.
clock-names:
minItems: 2
maxItems: 3
power-domains:
maxItems: 1
mediatek,smi:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: a phandle to the smi_common node.
mediatek,larb-id:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 31
description: the hardware id of this larb. It's only required when this
hardward id is not consecutive from its M4U point of view.
required:
- compatible
- reg
- clocks
- clock-names
- power-domains
allOf:
- if: # HW has gals
properties:
compatible:
enum:
- mediatek,mt8183-smi-larb
then:
properties:
clock:
items:
minItems: 3
maxItems: 3
clock-names:
items:
- const: apb
- const: smi
- const: gals
else:
properties:
clock:
items:
minItems: 2
maxItems: 2
clock-names:
items:
- const: apb
- const: smi
- if:
properties:
compatible:
contains:
enum:
- mediatek,mt2701-smi-larb
- mediatek,mt2712-smi-larb
- mediatek,mt6779-smi-larb
- mediatek,mt8167-smi-larb
- mediatek,mt8192-smi-larb
then:
required:
- mediatek,larb-id
additionalProperties: false
examples:
- |+
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/power/mt8173-power.h>
larb1: larb@16010000 {
compatible = "mediatek,mt8173-smi-larb";
reg = <0x16010000 0x1000>;
mediatek,smi = <&smi_common>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
clocks = <&vdecsys CLK_VDEC_CKEN>,
<&vdecsys CLK_VDEC_LARB_CKEN>;
clock-names = "apb", "smi";
};

View File

@@ -29,11 +29,23 @@ properties:
items:
- const: emc
"#interconnect-cells":
const: 0
nvidia,memory-controller:
$ref: /schemas/types.yaml#/definitions/phandle
description:
phandle of the memory controller node
core-supply:
description:
Phandle of voltage regulator of the SoC "core" power domain.
operating-points-v2:
description:
Should contain freqs and voltages and opp-supported-hw property, which
is a bitfield indicating SoC speedo ID mask.
patternProperties:
"^emc-timings-[0-9]+$":
type: object
@@ -327,6 +339,8 @@ required:
- clocks
- clock-names
- nvidia,memory-controller
- "#interconnect-cells"
- operating-points-v2
additionalProperties: false
@@ -345,6 +359,7 @@ examples:
#iommu-cells = <1>;
#reset-cells = <1>;
#interconnect-cells = <1>;
};
external-memory-controller@7001b000 {
@@ -354,6 +369,10 @@ examples:
clock-names = "emc";
nvidia,memory-controller = <&mc>;
operating-points-v2 = <&dvfs_opp_table>;
core-supply = <&vdd_core>;
#interconnect-cells = <0>;
emc-timings-0 {
nvidia,ram-code = <3>;

View File

@@ -40,6 +40,9 @@ properties:
"#iommu-cells":
const: 1
"#interconnect-cells":
const: 1
patternProperties:
"^emc-timings-[0-9]+$":
type: object
@@ -104,6 +107,7 @@ required:
- clock-names
- "#reset-cells"
- "#iommu-cells"
- "#interconnect-cells"
additionalProperties: false
@@ -119,6 +123,7 @@ examples:
#iommu-cells = <1>;
#reset-cells = <1>;
#interconnect-cells = <1>;
emc-timings-3 {
nvidia,ram-code = <3>;

View File

@@ -12,18 +12,44 @@ Properties:
irrespective of ram-code configuration.
- interrupts : Should contain EMC General interrupt.
- clocks : Should contain EMC clock.
- nvidia,memory-controller : Phandle of the Memory Controller node.
- #interconnect-cells : Should be 0.
- operating-points-v2: See ../bindings/opp/opp.txt for details.
For each opp entry in 'operating-points-v2' table:
- opp-supported-hw: One bitfield indicating SoC process ID mask
A bitwise AND is performed against this value and if any bit
matches, the OPP gets enabled.
Optional properties:
- core-supply: Phandle of voltage regulator of the SoC "core" power domain.
Child device nodes describe the memory settings for different configurations and clock rates.
Example:
opp_table: opp-table {
compatible = "operating-points-v2";
opp@36000000 {
opp-microvolt = <950000 950000 1300000>;
opp-hz = /bits/ 64 <36000000>;
};
...
};
memory-controller@7000f400 {
#address-cells = < 1 >;
#size-cells = < 0 >;
#interconnect-cells = <0>;
compatible = "nvidia,tegra20-emc";
reg = <0x7000f4000 0x200>;
reg = <0x7000f400 0x400>;
interrupts = <0 78 0x04>;
clocks = <&tegra_car TEGRA20_CLK_EMC>;
nvidia,memory-controller = <&mc>;
core-supply = <&core_vdd_reg>;
operating-points-v2 = <&opp_table>;
}

View File

@@ -16,6 +16,8 @@ Required properties:
IOMMU specifier needed to encode an address. GART supports only a single
address space that is shared by all devices, therefore no additional
information needed for the address encoding.
- #interconnect-cells : Should be 1. This cell represents memory client.
The assignments may be found in header file <dt-bindings/memory/tegra20-mc.h>.
Example:
mc: memory-controller@7000f000 {
@@ -27,6 +29,7 @@ Example:
interrupts = <GIC_SPI 77 0x04>;
#reset-cells = <1>;
#iommu-cells = <0>;
#interconnect-cells = <1>;
};
video-codec@6001a000 {

View File

@@ -31,11 +31,23 @@ properties:
interrupts:
maxItems: 1
"#interconnect-cells":
const: 0
nvidia,memory-controller:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle of the Memory Controller node.
core-supply:
description:
Phandle of voltage regulator of the SoC "core" power domain.
operating-points-v2:
description:
Should contain freqs and voltages and opp-supported-hw property, which
is a bitfield indicating SoC speedo ID mask.
patternProperties:
"^emc-timings-[0-9]+$":
type: object
@@ -214,6 +226,8 @@ required:
- interrupts
- clocks
- nvidia,memory-controller
- "#interconnect-cells"
- operating-points-v2
additionalProperties: false
@@ -226,6 +240,10 @@ examples:
clocks = <&tegra_car 57>;
nvidia,memory-controller = <&mc>;
operating-points-v2 = <&dvfs_opp_table>;
core-supply = <&vdd_core>;
#interconnect-cells = <0>;
emc-timings-1 {
nvidia,ram-code = <1>;

View File

@@ -57,6 +57,9 @@ properties:
"#iommu-cells":
const: 1
"#interconnect-cells":
const: 1
patternProperties:
"^emc-timings-[0-9]+$":
type: object
@@ -120,6 +123,7 @@ required:
- clock-names
- "#reset-cells"
- "#iommu-cells"
- "#interconnect-cells"
additionalProperties: false
@@ -135,6 +139,7 @@ examples:
#iommu-cells = <1>;
#reset-cells = <1>;
#interconnect-cells = <1>;
emc-timings-1 {
nvidia,ram-code = <1>;

View File

@@ -46,6 +46,7 @@ Required properties
- compatible: One of:
"aspeed,ast2400-lpc", "simple-mfd"
"aspeed,ast2500-lpc", "simple-mfd"
"aspeed,ast2600-lpc", "simple-mfd"
- reg: contains the physical address and length values of the Aspeed
LPC memory region.
@@ -64,6 +65,7 @@ BMC Node
- compatible: One of:
"aspeed,ast2400-lpc-bmc"
"aspeed,ast2500-lpc-bmc"
"aspeed,ast2600-lpc-bmc"
- reg: contains the physical address and length values of the
H8S/2168-compatible LPC controller memory region
@@ -74,6 +76,7 @@ Host Node
- compatible: One of:
"aspeed,ast2400-lpc-host", "simple-mfd", "syscon"
"aspeed,ast2500-lpc-host", "simple-mfd", "syscon"
"aspeed,ast2600-lpc-host", "simple-mfd", "syscon"
- reg: contains the address and length values of the host-related
register space for the Aspeed LPC controller
@@ -128,6 +131,7 @@ Required properties:
- compatible: One of:
"aspeed,ast2400-lpc-ctrl";
"aspeed,ast2500-lpc-ctrl";
"aspeed,ast2600-lpc-ctrl";
- reg: contains offset/length values of the host interface controller
memory regions
@@ -168,6 +172,7 @@ Required properties:
- compatible: One of:
"aspeed,ast2400-lhc";
"aspeed,ast2500-lhc";
"aspeed,ast2600-lhc";
- reg: contains offset/length values of the LHC memory regions. In the
AST2400 and AST2500 there are two regions.
@@ -187,7 +192,8 @@ state of the LPC bus. Some systems may chose to modify this configuration.
Required properties:
- compatible: "aspeed,ast2500-lpc-reset" or
- compatible: "aspeed,ast2600-lpc-reset" or
"aspeed,ast2500-lpc-reset"
"aspeed,ast2400-lpc-reset"
- reg: offset and length of the IP in the LHC memory region
- #reset-controller indicates the number of reset cells expected

View File

@@ -20,3 +20,29 @@ syscon: syscon@1e6e2000 {
#clock-cells = <1>;
#reset-cells = <1>;
};
Silicon ID
-----------------
Families have unique hardware silicon identifiers within the SoC.
Required properties:
- compatible: "aspeed,silicon-id" or:
"aspeed,ast2400-silicon-id" or
"aspeed,ast2500-silicon-id" or
"aspeed,ast2600-silicon-id"
- reg: offset and length of the silicon id information
optionally, a second offset and length describes the unique chip id
The reg should be the unique silicon id register, and
not backwards compatible one in eg. the 2600.
Example:
silicon-id@7c {
compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
reg = <0x7c 0x4 0x150 0x8>;
};

View File

@@ -16,12 +16,16 @@ description:
properties:
compatible:
enum:
- qcom,msm8916-rpmpd
- qcom,msm8939-rpmpd
- qcom,msm8976-rpmpd
- qcom,msm8996-rpmpd
- qcom,msm8998-rpmpd
- qcom,qcs404-rpmpd
- qcom,sdm660-rpmpd
- qcom,sc7180-rpmhpd
- qcom,sdm845-rpmhpd
- qcom,sdx55-rpmhpd
- qcom,sm8150-rpmhpd
- qcom,sm8250-rpmhpd

View File

@@ -0,0 +1,58 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# # Copyright 2020 MediaTek Inc.
%YAML 1.2
---
$id: "http://devicetree.org/schemas/soc/mediatek/devapc.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: MediaTek Device Access Permission Control driver
description: |
MediaTek bus fabric provides TrustZone security support and data
protection to prevent slaves from being accessed by unexpected masters.
The security violation is logged and sent to the processor for further
analysis and countermeasures.
maintainers:
- Neal Liu <neal.liu@mediatek.com>
properties:
compatible:
enum:
- mediatek,mt6779-devapc
reg:
description: The base address of devapc register bank
maxItems: 1
interrupts:
description: A single interrupt specifier
maxItems: 1
clocks:
description: Contains module clock source and clock names
maxItems: 1
clock-names:
description: Names of the clocks list in clocks property
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/mt6779-clk.h>
devapc: devapc@10207000 {
compatible = "mediatek,mt6779-devapc";
reg = <0x10207000 0x1000>;
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg_ao CLK_INFRA_DEVICE_APC>;
clock-names = "devapc-infra-clock";
};

View File

@@ -0,0 +1,34 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/xilinx/xlnx,vcu-settings.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Xilinx VCU Settings
maintainers:
- Michael Tretter <kernel@pengutronix.de>
description: |
The Xilinx VCU Settings provides information about the configuration of the
video codec unit.
properties:
compatible:
items:
- const: xlnx,vcu-settings
- const: syscon
reg:
maxItems: 1
required:
- compatible
- reg
examples:
- |
xlnx_vcu: vcu@a0041000 {
compatible = "xlnx,vcu-settings", "syscon";
reg = <0x0 0xa0041000 0x0 0x1000>;
};

View File

@@ -12,10 +12,7 @@ Required properties:
- compatible: shall be one of:
"xlnx,vcu"
"xlnx,vcu-logicoreip-1.0"
- reg, reg-names: There are two sets of registers need to provide.
1. vcu slcr
2. Logicore
reg-names should contain name for the each register sequence.
- reg : The base offset and size of the VCU_PL_SLCR register space.
- clocks: phandle for aclk and pll_ref clocksource
- clock-names: The identification string, "aclk", is always required for
the axi clock. "pll_ref" is required for pll.
@@ -23,9 +20,7 @@ Example:
xlnx_vcu: vcu@a0040000 {
compatible = "xlnx,vcu-logicoreip-1.0";
reg = <0x0 0xa0040000 0x0 0x1000>,
<0x0 0xa0041000 0x0 0x1000>;
reg-names = "vcu_slcr", "logicore";
reg = <0x0 0xa0040000 0x0 0x1000>;
clocks = <&si570_1>, <&clkc 71>;
clock-names = "pll_ref", "aclk";
};

View File

@@ -1,6 +1,7 @@
.. SPDX-License-Identifier: GPL-2.0
==============================
The Second Extended Filesystem
==============================

View File

@@ -260,6 +260,14 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab
For other files, we can still enable compression via ioctl.
Note that, there is one reserved special extension '*', it
can be set to enable compression for all files.
compress_chksum Support verifying chksum of raw data in compressed cluster.
compress_mode=%s Control file compression mode. This supports "fs" and "user"
modes. In "fs" mode (default), f2fs does automatic compression
on the compression enabled files. In "user" mode, f2fs disables
the automaic compression and gives the user discretion of
choosing the target file and the timing. The user can do manual
compression/decompression on the compression enabled files using
ioctls.
inlinecrypt When possible, encrypt/decrypt the contents of encrypted
files using the blk-crypto framework rather than
filesystem-layer encryption. This allows the use of
@@ -810,6 +818,34 @@ Compress metadata layout::
| data length | data chksum | reserved | compressed data |
+-------------+-------------+----------+----------------------------+
Compression mode
--------------------------
f2fs supports "fs" and "user" compression modes with "compression_mode" mount option.
With this option, f2fs provides a choice to select the way how to compress the
compression enabled files (refer to "Compression implementation" section for how to
enable compression on a regular inode).
1) compress_mode=fs
This is the default option. f2fs does automatic compression in the writeback of the
compression enabled files.
2) compress_mode=user
This disables the automaic compression and gives the user discretion of choosing the
target file and the timing. The user can do manual compression/decompression on the
compression enabled files using F2FS_IOC_DECOMPRESS_FILE and F2FS_IOC_COMPRESS_FILE
ioctls like the below.
To decompress a file,
fd = open(filename, O_WRONLY, 0);
ret = ioctl(fd, F2FS_IOC_DECOMPRESS_FILE);
To compress a file,
fd = open(filename, O_WRONLY, 0);
ret = ioctl(fd, F2FS_IOC_COMPRESS_FILE);
NVMe Zoned Namespace devices
----------------------------

View File

@@ -34,7 +34,7 @@ These resources should be specified in that order, as the ordering of the
two address regions is important (the driver expects these to be address
and then data).
An example from arch/arm/mach-s3c2410/mach-bast.c is::
An example from arch/arm/mach-s3c/mach-bast.c is::
static struct resource bast_dm9k_resource[] = {
[0] = {

View File

@@ -2074,7 +2074,7 @@ M: Matthias Brugger <matthias.bgg@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
W: https://mtk.bcnfs.org/
W: https://mtk.wiki.kernel.org/
C: irc://chat.freenode.net/linux-mediatek
F: arch/arm/boot/dts/mt6*
F: arch/arm/boot/dts/mt7*
@@ -6746,6 +6746,7 @@ F: Documentation/filesystems/f2fs.rst
F: fs/f2fs/
F: include/linux/f2fs_fs.h
F: include/trace/events/f2fs.h
F: include/uapi/linux/f2fs.h
F71805F HARDWARE MONITORING DRIVER
M: Jean Delvare <jdelvare@suse.com>
@@ -11436,6 +11437,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl.git
F: Documentation/devicetree/bindings/memory-controllers/
F: drivers/memory/
F: include/dt-bindings/memory/
MEMORY FREQUENCY SCALING DRIVERS FOR NVIDIA TEGRA
M: Dmitry Osipenko <digetx@gmail.com>

View File

@@ -238,7 +238,6 @@
&gpmc {
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";
status = "okay";
gpmc,num-waitpins = <2>;
pinctrl-names = "default";

View File

@@ -1,5 +1,8 @@
&l4_wkup { /* 0x44c00000 */
compatible = "ti,am33xx-l4-wkup", "simple-bus";
compatible = "ti,am33xx-l4-wkup", "simple-pm-bus";
power-domains = <&prm_wkup>;
clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_L4_WKUP_CLKCTRL 0>;
clock-names = "fck";
reg = <0x44c00000 0x800>,
<0x44c00800 0x800>,
<0x44c01000 0x400>,
@@ -12,7 +15,7 @@
<0x00200000 0x44e00000 0x100000>; /* segment 2 */
segment@0 { /* 0x44c00000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */
@@ -22,7 +25,7 @@
};
segment@100000 { /* 0x44d00000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00100000 0x004000>, /* ap 4 */
@@ -34,23 +37,27 @@
compatible = "ti,sysc-omap4", "ti,sysc";
reg = <0x0 0x4>;
reg-names = "rev";
clocks = <&l4_wkup_aon_clkctrl AM3_L4_WKUP_AON_WKUP_M3_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x4000>;
status = "disabled";
};
ranges = <0x00000000 0x00000000 0x4000>,
<0x00080000 0x00080000 0x2000>;
target-module@80000 { /* 0x44d80000, ap 6 10.0 */
compatible = "ti,sysc";
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x80000 0x2000>;
wkup_m3: cpu@0 {
compatible = "ti,am3352-wkup-m3";
reg = <0x00000000 0x4000>,
<0x00080000 0x2000>;
reg-names = "umem", "dmem";
resets = <&prm_wkup 3>;
reset-names = "rstctrl";
ti,pm-firmware = "am335x-pm-firmware.elf";
};
};
};
segment@200000 { /* 0x44e00000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00200000 0x002000>, /* ap 8 */
@@ -274,6 +281,9 @@
compatible = "ti,sysc-omap4", "ti,sysc";
reg = <0x10000 0x4>;
reg-names = "rev";
clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_CONTROL_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00010000 0x00010000>,
@@ -433,6 +443,7 @@
<SYSC_IDLE_SMART>,
<SYSC_IDLE_SMART_WKUP>;
/* Domains (P, C): rtc_pwrdm, l4_rtc_clkdm */
power-domains = <&prm_rtc>;
clocks = <&l4_rtc_clkctrl AM3_L4_RTC_RTC_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
@@ -658,7 +669,10 @@
};
&l4_fast { /* 0x4a000000 */
compatible = "ti,am33xx-l4-fast", "simple-bus";
compatible = "ti,am33xx-l4-fast", "simple-pm-bus";
power-domains = <&prm_per>;
clocks = <&l4hs_clkctrl AM3_L4HS_L4_HS_CLKCTRL 0>;
clock-names = "fck";
reg = <0x4a000000 0x800>,
<0x4a000800 0x800>,
<0x4a001000 0x400>;
@@ -668,7 +682,7 @@
ranges = <0x00000000 0x4a000000 0x1000000>; /* segment 0 */
segment@0 { /* 0x4a000000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */
@@ -837,7 +851,10 @@
};
&l4_per { /* 0x48000000 */
compatible = "ti,am33xx-l4-per", "simple-bus";
compatible = "ti,am33xx-l4-per", "simple-pm-bus";
power-domains = <&prm_per>;
clocks = <&l4ls_clkctrl AM3_L4LS_L4_LS_CLKCTRL 0>;
clock-names = "fck";
reg = <0x48000000 0x800>,
<0x48000800 0x800>,
<0x48001000 0x400>,
@@ -855,7 +872,7 @@
<0x46400000 0x46400000 0x400000>; /* l3 data port */
segment@0 { /* 0x48000000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */
@@ -1466,7 +1483,7 @@
};
segment@100000 { /* 0x48100000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0008c000 0x0018c000 0x001000>, /* ap 42 */
@@ -1850,13 +1867,31 @@
};
segment@200000 { /* 0x48200000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00200000 0x010000>;
target-module@0 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
power-domains = <&prm_mpu>;
clocks = <&mpu_clkctrl AM3_MPU_MPU_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 0x10000>;
mpu@0 {
compatible = "ti,omap3-mpu";
pm-sram = <&pm_sram_code
&pm_sram_data>;
};
};
};
segment@300000 { /* 0x48300000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00300000 0x001000>, /* ap 66 */

View File

@@ -144,11 +144,28 @@
};
};
pmu@4b000000 {
compatible = "arm,cortex-a8-pmu";
interrupts = <3>;
reg = <0x4b000000 0x1000000>;
ti,hwmods = "debugss";
target-module@4b000000 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
clocks = <&l3_clkctrl AM3_L3_L3_INSTR_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x4b000000 0x1000000>;
target-module@140000 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
clocks = <&l3_aon_clkctrl AM3_L3_AON_DEBUGSS_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x140000 0xec0000>;
pmu@0 {
compatible = "arm,cortex-a8-pmu";
interrupts = <3>;
};
};
};
/*
@@ -157,12 +174,6 @@
*/
soc {
compatible = "ti,omap-infra";
mpu {
compatible = "ti,omap3-mpu";
ti,hwmods = "mpu";
pm-sram = <&pm_sram_code
&pm_sram_data>;
};
};
/*
@@ -173,21 +184,15 @@
* the whole bus hierarchy.
*/
ocp: ocp {
compatible = "simple-bus";
compatible = "simple-pm-bus";
power-domains = <&prm_per>;
clocks = <&l3_clkctrl AM3_L3_L3_MAIN_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges;
ti,hwmods = "l3_main";
l4_wkup: interconnect@44c00000 {
wkup_m3: wkup_m3@100000 {
compatible = "ti,am3352-wkup-m3";
reg = <0x100000 0x4000>,
<0x180000 0x2000>;
reg-names = "umem", "dmem";
ti,hwmods = "wkup_m3";
ti,pm-firmware = "am335x-pm-firmware.elf";
};
};
l4_per: interconnect@48000000 {
};
@@ -458,53 +463,89 @@
};
};
ocmcram: sram@40300000 {
compatible = "mmio-sram";
reg = <0x40300000 0x10000>; /* 64k */
ranges = <0x0 0x40300000 0x10000>;
target-module@40300000 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
clocks = <&l3_clkctrl AM3_L3_OCMCRAM_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x40300000 0x10000>;
pm_sram_code: pm-code-sram@0 {
compatible = "ti,sram";
reg = <0x0 0x1000>;
protect-exec;
};
ocmcram: sram@0 {
compatible = "mmio-sram";
reg = <0 0x10000>; /* 64k */
ranges = <0 0 0x10000>;
#address-cells = <1>;
#size-cells = <1>;
pm_sram_data: pm-data-sram@1000 {
compatible = "ti,sram";
reg = <0x1000 0x1000>;
pool;
pm_sram_code: pm-code-sram@0 {
compatible = "ti,sram";
reg = <0x0 0x1000>;
protect-exec;
};
pm_sram_data: pm-data-sram@1000 {
compatible = "ti,sram";
reg = <0x1000 0x1000>;
pool;
};
};
};
emif: emif@4c000000 {
compatible = "ti,emif-am3352";
reg = <0x4c000000 0x1000000>;
ti,hwmods = "emif";
interrupts = <101>;
sram = <&pm_sram_code
&pm_sram_data>;
target-module@4c000000 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
reg = <0x4c000000 0x4>;
reg-names = "rev";
clocks = <&l3_clkctrl AM3_L3_EMIF_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x4c000000 0x1000000>;
emif: emif@0 {
compatible = "ti,emif-am3352";
reg = <0 0x1000000>;
interrupts = <101>;
sram = <&pm_sram_code
&pm_sram_data>;
};
};
gpmc: gpmc@50000000 {
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";
ti,no-idle-on-init;
reg = <0x50000000 0x2000>;
interrupts = <100>;
dmas = <&edma 52 0>;
dma-names = "rxtx";
gpmc,num-cs = <7>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
target-module@50000000 {
compatible = "ti,sysc-omap2", "ti,sysc";
reg = <0x50000000 4>,
<0x50000010 4>,
<0x50000014 4>;
reg-names = "rev", "sysc", "syss";
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
ti,syss-mask = <1>;
clocks = <&l3s_clkctrl AM3_L3S_GPMC_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
ranges = <0x50000000 0x50000000 0x00001000>, /* regs */
<0x00000000 0x00000000 0x40000000>; /* data */
gpmc: gpmc@50000000 {
compatible = "ti,am3352-gpmc";
reg = <0x50000000 0x2000>;
interrupts = <100>;
dmas = <&edma 52 0>;
dma-names = "rxtx";
gpmc,num-cs = <7>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
#size-cells = <1>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
};
};
sham_target: target-module@53100000 {
@@ -601,12 +642,20 @@
compatible = "ti,am3-prm-inst", "ti,omap-prm-inst";
reg = <0xc00 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_wkup: prm@d00 {
compatible = "ti,am3-prm-inst", "ti,omap-prm-inst";
reg = <0xd00 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_mpu: prm@e00 {
compatible = "ti,am3-prm-inst", "ti,omap-prm-inst";
reg = <0xe00 0x100>;
#power-domain-cells = <0>;
};
prm_device: prm@f00 {
@@ -615,16 +664,31 @@
#reset-cells = <1>;
};
prm_rtc: prm@1000 {
compatible = "ti,am3-prm-inst", "ti,omap-prm-inst";
reg = <0x1000 0x100>;
#power-domain-cells = <0>;
};
prm_gfx: prm@1100 {
compatible = "ti,am3-prm-inst", "ti,omap-prm-inst";
reg = <0x1100 0x100>;
#power-domain-cells = <0>;
#reset-cells = <1>;
};
prm_cefuse: prm@1200 {
compatible = "ti,am3-prm-inst", "ti,omap-prm-inst";
reg = <0x1200 0x100>;
#power-domain-cells = <0>;
};
};
/* Preferred always-on timer for clocksource */
&timer1_target {
clocks = <&l4_wkup_clkctrl AM3_L4_WKUP_TIMER1_CLKCTRL 0>,
<&l4_wkup_clkctrl AM3_L4_WKUP_L4_WKUP_CLKCTRL 0>;
clock-names = "fck", "ick";
ti,no-reset-on-init;
ti,no-idle;
timer@0 {
@@ -635,6 +699,9 @@
/* Preferred timer for clockevent */
&timer2_target {
clocks = <&l4ls_clkctrl AM3_L4LS_TIMER2_CLKCTRL 0>,
<&l4ls_clkctrl AM3_L4LS_L4_LS_CLKCTRL 0>;
clock-names = "fck", "ick";
ti,no-reset-on-init;
ti,no-idle;
timer@0 {

View File

@@ -107,12 +107,6 @@
soc {
compatible = "ti,omap-infra";
mpu {
compatible = "ti,omap4-mpu";
ti,hwmods = "mpu";
pm-sram = <&pm_sram_code
&pm_sram_data>;
};
};
gic: interrupt-controller@48241000 {
@@ -161,40 +155,48 @@
};
ocp@44000000 {
compatible = "ti,am4372-l3-noc", "simple-bus";
compatible = "simple-pm-bus";
power-domains = <&prm_per>;
clocks = <&l3_clkctrl AM4_L3_L3_MAIN_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges;
ti,hwmods = "l3_main";
ti,no-idle;
reg = <0x44000000 0x400000
0x44800000 0x400000>;
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
l3-noc@44000000 {
compatible = "ti,am4372-l3-noc";
reg = <0x44000000 0x400000>,
<0x44800000 0x400000>;
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
};
l4_wkup: interconnect@44c00000 {
wkup_m3: wkup_m3@100000 {
compatible = "ti,am4372-wkup-m3";
reg = <0x100000 0x4000>,
<0x180000 0x2000>;
reg-names = "umem", "dmem";
ti,hwmods = "wkup_m3";
ti,pm-firmware = "am335x-pm-firmware.elf";
};
};
l4_per: interconnect@48000000 {
};
l4_fast: interconnect@4a000000 {
};
emif: emif@4c000000 {
compatible = "ti,emif-am4372";
reg = <0x4c000000 0x1000000>;
ti,hwmods = "emif";
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
target-module@4c000000 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
reg = <0x4c000000 0x4>;
reg-names = "rev";
clocks = <&emif_clkctrl AM4_EMIF_EMIF_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
sram = <&pm_sram_code
&pm_sram_data>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x4c000000 0x1000000>;
emif: emif@0 {
compatible = "ti,emif-am4372";
reg = <0 0x1000000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
sram = <&pm_sram_code
&pm_sram_data>;
};
};
target-module@49000000 {
@@ -434,24 +436,41 @@
ranges = <0x0 0x54400000 0x80000>;
};
gpmc: gpmc@50000000 {
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";
dmas = <&edma 52 0>;
dma-names = "rxtx";
clocks = <&l3s_gclk>;
target-module@50000000 {
compatible = "ti,sysc-omap2", "ti,sysc";
reg = <0x50000000 4>,
<0x50000010 4>,
<0x50000014 4>;
reg-names = "rev", "sysc", "syss";
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
ti,syss-mask = <1>;
clocks = <&l3s_clkctrl AM4_L3S_GPMC_CLKCTRL 0>;
clock-names = "fck";
reg = <0x50000000 0x2000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
gpmc,num-cs = <7>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
#address-cells = <1>;
#size-cells = <1>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
ranges = <0x50000000 0x50000000 0x00001000>, /* regs */
<0x00000000 0x00000000 0x40000000>; /* data */
gpmc: gpmc@50000000 {
compatible = "ti,am3352-gpmc";
dmas = <&edma 52 0>;
dma-names = "rxtx";
clocks = <&l3s_gclk>;
clock-names = "fck";
reg = <0x50000000 0x2000>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
gpmc,num-cs = <7>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
#size-cells = <1>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
};
};
target-module@47900000 {
@@ -484,23 +503,33 @@
};
};
ocmcram: sram@40300000 {
compatible = "mmio-sram";
reg = <0x40300000 0x40000>; /* 256k */
ranges = <0x0 0x40300000 0x40000>;
target-module@40300000 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
clocks = <&l3_clkctrl AM4_L3_OCMCRAM_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x40300000 0x40000>;
pm_sram_code: pm-code-sram@0 {
compatible = "ti,sram";
reg = <0x0 0x1000>;
protect-exec;
};
ocmcram: sram@0 {
compatible = "mmio-sram";
reg = <0 0x40000>; /* 256k */
ranges = <0 0 0x40000>;
#address-cells = <1>;
#size-cells = <1>;
pm_sram_data: pm-data-sram@1000 {
compatible = "ti,sram";
reg = <0x1000 0x1000>;
pool;
pm_sram_code: pm-code-sram@0 {
compatible = "ti,sram";
reg = <0x0 0x1000>;
protect-exec;
};
pm_sram_data: pm-data-sram@1000 {
compatible = "ti,sram";
reg = <0x1000 0x1000>;
pool;
};
};
};
@@ -531,6 +560,12 @@
#include "am43xx-clocks.dtsi"
&prcm {
prm_mpu: prm@300 {
compatible = "ti,am4-prm-inst", "ti,omap-prm-inst";
reg = <0x300 0x100>;
#power-domain-cells = <0>;
};
prm_gfx: prm@400 {
compatible = "ti,am4-prm-inst", "ti,omap-prm-inst";
reg = <0x400 0x100>;
@@ -538,16 +573,36 @@
#reset-cells = <1>;
};
prm_rtc: prm@500 {
compatible = "ti,am4-prm-inst", "ti,omap-prm-inst";
reg = <0x500 0x100>;
#power-domain-cells = <0>;
};
prm_tamper: prm@600 {
compatible = "ti,am4-prm-inst", "ti,omap-prm-inst";
reg = <0x600 0x100>;
#power-domain-cells = <0>;
};
prm_cefuse: prm@700 {
compatible = "ti,am4-prm-inst", "ti,omap-prm-inst";
reg = <0x700 0x100>;
#power-domain-cells = <0>;
};
prm_per: prm@800 {
compatible = "ti,am4-prm-inst", "ti,omap-prm-inst";
reg = <0x800 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_wkup: prm@2000 {
compatible = "ti,am4-prm-inst", "ti,omap-prm-inst";
reg = <0x2000 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_device: prm@4000 {
@@ -561,6 +616,9 @@
&timer1_target {
ti,no-reset-on-init;
ti,no-idle;
clocks = <&l4_wkup_clkctrl AM4_L4_WKUP_TIMER1_CLKCTRL 0>,
<&l4_wkup_clkctrl AM4_L4_WKUP_L4_WKUP_CLKCTRL 0>;
clock-names = "fck", "ick";
timer@0 {
assigned-clocks = <&timer1_fck>;
assigned-clock-parents = <&sys_clkin_ck>;
@@ -571,6 +629,9 @@
&timer2_target {
ti,no-reset-on-init;
ti,no-idle;
clocks = <&l4ls_clkctrl AM4_L4LS_TIMER2_CLKCTRL 0>,
<&l4ls_clkctrl AM4_L4LS_L4_LS_CLKCTRL 0>;
clock-names = "fck", "ick";
timer@0 {
assigned-clocks = <&timer2_fck>;
assigned-clock-parents = <&sys_clkin_ck>;

View File

@@ -1,5 +1,8 @@
&l4_wkup { /* 0x44c00000 */
compatible = "ti,am4-l4-wkup", "simple-bus";
compatible = "ti,am4-l4-wkup", "simple-pm-bus";
power-domains = <&prm_wkup>;
clocks = <&l4_wkup_clkctrl AM4_L4_WKUP_L4_WKUP_CLKCTRL 0>;
clock-names = "fck";
reg = <0x44c00000 0x800>,
<0x44c00800 0x800>,
<0x44c01000 0x400>,
@@ -12,7 +15,7 @@
<0x00200000 0x44e00000 0x100000>; /* segment 2 */
segment@0 { /* 0x44c00000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */
@@ -22,7 +25,7 @@
};
segment@100000 { /* 0x44d00000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00100000 0x004000>, /* ap 4 */
@@ -32,19 +35,25 @@
<0x000f0000 0x001f0000 0x010000>; /* ap 8 */
target-module@0 { /* 0x44d00000, ap 4 28.0 */
compatible = "ti,sysc";
status = "disabled";
compatible = "ti,sysc-omap4", "ti,sysc";
reg = <0x0 0x4>;
reg-names = "rev";
clocks = <&l4_wkup_aon_clkctrl AM4_L4_WKUP_AON_WKUP_M3_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x0 0x4000>;
};
ranges = <0x00000000 0x00000000 0x4000>,
<0x00080000 0x00080000 0x2000>;
target-module@80000 { /* 0x44d80000, ap 6 10.0 */
compatible = "ti,sysc";
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x80000 0x2000>;
wkup_m3: cpu@0 {
compatible = "ti,am4372-wkup-m3";
reg = <0x00000000 0x4000>,
<0x00080000 0x2000>;
reg-names = "umem", "dmem";
resets = <&prm_wkup 3>;
reset-names = "rstctrl";
ti,pm-firmware = "am335x-pm-firmware.elf";
};
};
target-module@f0000 { /* 0x44df0000, ap 8 58.0 */
@@ -75,7 +84,7 @@
};
segment@200000 { /* 0x44e00000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00200000 0x001000>, /* ap 9 */
@@ -265,6 +274,9 @@
compatible = "ti,sysc-omap4", "ti,sysc";
reg = <0x10000 0x4>;
reg-names = "rev";
clocks = <&l4_wkup_clkctrl AM4_L4_WKUP_CONTROL_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x10000 0x10000>;
@@ -419,6 +431,7 @@
<SYSC_IDLE_SMART>,
<SYSC_IDLE_SMART_WKUP>;
/* Domains (P, C): rtc_pwrdm, l4_rtc_clkdm */
power-domains = <&prm_rtc>;
clocks = <&l4_rtc_clkctrl AM4_L4_RTC_RTC_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
@@ -479,7 +492,10 @@
};
&l4_fast { /* 0x4a000000 */
compatible = "ti,am4-l4-fast", "simple-bus";
compatible = "ti,am4-l4-fast", "simple-pm-bus";
power-domains = <&prm_per>;
clocks = <&l3_clkctrl AM4_L3_L4_HS_CLKCTRL 0>;
clock-names = "fck";
reg = <0x4a000000 0x800>,
<0x4a000800 0x800>,
<0x4a001000 0x400>;
@@ -489,7 +505,7 @@
ranges = <0x00000000 0x4a000000 0x1000000>; /* segment 0 */
segment@0 { /* 0x4a000000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */
@@ -594,7 +610,10 @@
};
&l4_per { /* 0x48000000 */
compatible = "ti,am4-l4-per", "simple-bus";
compatible = "ti,am4-l4-per", "simple-pm-bus";
power-domains = <&prm_per>;
clocks = <&l4ls_clkctrl AM4_L4LS_L4_LS_CLKCTRL 0>;
clock-names = "fck";
reg = <0x48000000 0x800>,
<0x48000800 0x800>,
<0x48001000 0x400>,
@@ -612,7 +631,7 @@
<0x46400000 0x46400000 0x400000>; /* l3 data port */
segment@0 { /* 0x48000000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00000000 0x000800>, /* ap 0 */
@@ -1187,7 +1206,7 @@
};
segment@100000 { /* 0x48100000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0008c000 0x0018c000 0x001000>, /* ap 34 */
@@ -1618,13 +1637,31 @@
};
segment@200000 { /* 0x48200000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00200000 0x010000>;
target-module@0 {
compatible = "ti,sysc-omap4-simple", "ti,sysc";
power-domains = <&prm_mpu>;
clocks = <&mpu_clkctrl AM4_MPU_MPU_CLKCTRL 0>;
clock-names = "fck";
ti,no-idle;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0 0x10000>;
mpu@0 {
compatible = "ti,omap4-mpu";
pm-sram = <&pm_sram_code
&pm_sram_data>;
};
};
};
segment@300000 { /* 0x48300000 */
compatible = "simple-bus";
compatible = "simple-pm-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00300000 0x001000>, /* ap 56 */

View File

@@ -192,6 +192,11 @@
status = "disabled";
};
silicon-id@7c {
compatible = "aspeed,ast2400-silicon-id", "aspeed,silicon-id";
reg = <0x7c 0x4>;
};
pinctrl: pinctrl@80 {
reg = <0x80 0x18>, <0xa0 0x10>;
compatible = "aspeed,ast2400-pinctrl";

View File

@@ -239,6 +239,11 @@
status = "disabled";
};
silicon-id@7c {
compatible = "aspeed,ast2500-silicon-id", "aspeed,silicon-id";
reg = <0x7c 0x4 0x150 0x8>;
};
pinctrl: pinctrl@80 {
compatible = "aspeed,ast2500-pinctrl";
reg = <0x80 0x18>, <0xa0 0x10>;

View File

@@ -317,6 +317,11 @@
compatible = "aspeed,ast2600-pinctrl";
};
silicon-id@14 {
compatible = "aspeed,ast2600-silicon-id", "aspeed,silicon-id";
reg = <0x14 0x4 0x5b0 0x8>;
};
smp-memram@180 {
compatible = "aspeed,ast2600-smpmem";
reg = <0x180 0x40>;

View File

@@ -724,22 +724,40 @@
/* OCP2SCP1 */
/* IRQ for DWC3_3 and DWC3_4 need IRQ crossbar */
gpmc: gpmc@50000000 {
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";
reg = <0x50000000 0x37c>; /* device IO registers */
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&edma_xbar 4 0>;
dma-names = "rxtx";
gpmc,num-cs = <8>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
target-module@50000000 {
compatible = "ti,sysc-omap2", "ti,sysc";
reg = <0x50000000 4>,
<0x50000010 4>,
<0x50000014 4>;
reg-names = "rev", "sysc", "syss";
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
ti,syss-mask = <1>;
clocks = <&l3main1_clkctrl DRA7_L3MAIN1_GPMC_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
ranges = <0x50000000 0x50000000 0x00001000>, /* regs */
<0x00000000 0x00000000 0x40000000>; /* data */
gpmc: gpmc@50000000 {
compatible = "ti,am3352-gpmc";
reg = <0x50000000 0x37c>; /* device IO registers */
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&edma_xbar 4 0>;
dma-names = "rxtx";
gpmc,num-cs = <8>;
gpmc,num-waitpins = <2>;
#address-cells = <2>;
#size-cells = <1>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
};
};
target-module@56000000 {
@@ -992,6 +1010,32 @@
};
};
iva_hd_target: target-module@5a000000 {
compatible = "ti,sysc-omap4", "ti,sysc";
reg = <0x5a05a400 0x4>,
<0x5a05a410 0x4>;
reg-names = "rev", "sysc";
ti,sysc-midle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
power-domains = <&prm_iva>;
resets = <&prm_iva 2>;
reset-names = "rstctrl";
clocks = <&iva_clkctrl DRA7_IVA_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x5a000000 0x5a000000 0x1000000>,
<0x5b000000 0x5b000000 0x1000000>;
iva {
compatible = "ti,ivahd";
};
};
opp_supply_mpu: opp-supply@4a003b20 {
compatible = "ti,omap5-opp-supply";
reg = <0x4a003b20 0xc>;
@@ -1061,53 +1105,130 @@
#include "dra7xx-clocks.dtsi"
&prm {
prm_mpu: prm@300 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x300 0x100>;
#power-domain-cells = <0>;
};
prm_dsp1: prm@400 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x400 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_ipu: prm@500 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x500 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_coreaon: prm@628 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x628 0xd8>;
#power-domain-cells = <0>;
};
prm_core: prm@700 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x700 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_iva: prm@f00 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0xf00 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_cam: prm@1000 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1000 0x100>;
#power-domain-cells = <0>;
};
prm_dss: prm@1100 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1100 0x100>;
#power-domain-cells = <0>;
};
prm_gpu: prm@1200 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1200 0x100>;
#power-domain-cells = <0>;
};
prm_l3init: prm@1300 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1300 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_l4per: prm@1400 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1400 0x100>;
#power-domain-cells = <0>;
};
prm_custefuse: prm@1600 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1600 0x100>;
#power-domain-cells = <0>;
};
prm_wkupaon: prm@1724 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1724 0x100>;
#power-domain-cells = <0>;
};
prm_dsp2: prm@1b00 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1b00 0x40>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_eve1: prm@1b40 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1b40 0x40>;
#power-domain-cells = <0>;
};
prm_eve2: prm@1b80 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1b80 0x40>;
#power-domain-cells = <0>;
};
prm_eve3: prm@1bc0 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1bc0 0x40>;
#power-domain-cells = <0>;
};
prm_eve4: prm@1c00 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1c00 0x60>;
#power-domain-cells = <0>;
};
prm_rtc: prm@1c60 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1c60 0x20>;
#power-domain-cells = <0>;
};
prm_vpe: prm@1c80 {
compatible = "ti,dra7-prm-inst", "ti,omap-prm-inst";
reg = <0x1c80 0x80>;
#power-domain-cells = <0>;
};
};

View File

@@ -1726,6 +1726,20 @@
};
};
iva_cm: iva-cm@f00 {
compatible = "ti,omap4-cm";
reg = <0xf00 0x100>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0xf00 0x100>;
iva_clkctrl: iva-clkctrl@20 {
compatible = "ti,clkctrl";
reg = <0x20 0xc>;
#clock-cells = <2>;
};
};
cam_cm: cam-cm@1000 {
compatible = "ti,omap4-cm";
reg = <0x1000 0x100>;

View File

@@ -330,6 +330,7 @@
/* Domains (V, P, C): iva, tesla_pwrdm, tesla_clkdm */
clocks = <&tesla_clkctrl OMAP4_DSP_CLKCTRL 0>;
clock-names = "fck";
power-domains = <&prm_tesla>;
resets = <&prm_tesla 1>;
reset-names = "rstctrl";
#address-cells = <1>;

View File

@@ -107,11 +107,6 @@
ti,hwmods = "mpu";
sram = <&ocmcram>;
};
iva {
compatible = "ti,ivahd";
ti,hwmods = "iva";
};
};
/*
@@ -150,24 +145,41 @@
reg = <0x40304000 0xa000>; /* 40k */
};
gpmc: gpmc@50000000 {
compatible = "ti,omap4430-gpmc";
reg = <0x50000000 0x1000>;
#address-cells = <2>;
#size-cells = <1>;
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 4>;
dma-names = "rxtx";
gpmc,num-cs = <8>;
gpmc,num-waitpins = <4>;
ti,hwmods = "gpmc";
target-module@50000000 {
compatible = "ti,sysc-omap2", "ti,sysc";
reg = <0x50000000 4>,
<0x50000010 4>,
<0x50000014 4>;
reg-names = "rev", "sysc", "syss";
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
ti,syss-mask = <1>;
ti,no-idle-on-init;
clocks = <&l3_div_ck>;
clocks = <&l3_2_clkctrl OMAP4_GPMC_CLKCTRL 0>;
clock-names = "fck";
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x50000000 0x50000000 0x00001000>, /* regs */
<0x00000000 0x00000000 0x40000000>; /* data */
gpmc: gpmc@50000000 {
compatible = "ti,omap4430-gpmc";
reg = <0x50000000 0x1000>;
#address-cells = <2>;
#size-cells = <1>;
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&sdma 4>;
dma-names = "rxtx";
gpmc,num-cs = <8>;
gpmc,num-waitpins = <4>;
clocks = <&l3_div_ck>;
clock-names = "fck";
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
};
};
target-module@52000000 {
@@ -445,6 +457,7 @@
<0x58000014 4>;
reg-names = "rev", "syss";
ti,syss-mask = <1>;
power-domains = <&prm_dss>;
clocks = <&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 0>,
<&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 9>,
<&l3_dss_clkctrl OMAP4_DSS_CORE_CLKCTRL 10>,
@@ -650,6 +663,32 @@
};
};
};
iva_hd_target: target-module@5a000000 {
compatible = "ti,sysc-omap4", "ti,sysc";
reg = <0x5a05a400 0x4>,
<0x5a05a410 0x4>;
reg-names = "rev", "sysc";
ti,sysc-midle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
ti,sysc-sidle = <SYSC_IDLE_FORCE>,
<SYSC_IDLE_NO>,
<SYSC_IDLE_SMART>;
power-domains = <&prm_ivahd>;
resets = <&prm_ivahd 2>;
reset-names = "rstctrl";
clocks = <&ivahd_clkctrl OMAP4_IVA_CLKCTRL 0>;
clock-names = "fck";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x5a000000 0x5a000000 0x1000000>,
<0x5b000000 0x5b000000 0x1000000>;
iva {
compatible = "ti,ivahd";
};
};
};
};
@@ -658,10 +697,17 @@
#include "omap44xx-clocks.dtsi"
&prm {
prm_mpu: prm@300 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x300 0x100>;
#power-domain-cells = <0>;
};
prm_tesla: prm@400 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x400 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_abe: prm@500 {
@@ -670,16 +716,78 @@
#power-domain-cells = <0>;
};
prm_always_on_core: prm@600 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x600 0x100>;
#power-domain-cells = <0>;
};
prm_core: prm@700 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x700 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_ivahd: prm@f00 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0xf00 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_cam: prm@1000 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1000 0x100>;
#power-domain-cells = <0>;
};
prm_dss: prm@1100 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1100 0x100>;
#power-domain-cells = <0>;
};
prm_gfx: prm@1200 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1200 0x100>;
#power-domain-cells = <0>;
};
prm_l3init: prm@1300 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1300 0x100>;
#power-domain-cells = <0>;
};
prm_l4per: prm@1400 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1400 0x100>;
#power-domain-cells = <0>;
};
prm_cefuse: prm@1600 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1600 0x100>;
#power-domain-cells = <0>;
};
prm_wkup: prm@1700 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1700 0x100>;
#power-domain-cells = <0>;
};
prm_emu: prm@1900 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1900 0x100>;
#power-domain-cells = <0>;
};
prm_dss: prm@1100 {
compatible = "ti,omap4-prm-inst", "ti,omap-prm-inst";
reg = <0x1100 0x40>;
#power-domain-cells = <0>;
};
prm_device: prm@1b00 {

View File

@@ -410,6 +410,7 @@
<0x58000014 4>;
reg-names = "rev", "syss";
ti,syss-mask = <1>;
power-domains = <&prm_dss>;
clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 0>,
<&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 9>,
<&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>,
@@ -670,10 +671,17 @@
#include "omap54xx-clocks.dtsi"
&prm {
prm_mpu: prm@300 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x300 0x100>;
#power-domain-cells = <0>;
};
prm_dsp: prm@400 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x400 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_abe: prm@500 {
@@ -682,16 +690,66 @@
#power-domain-cells = <0>;
};
prm_coreaon: prm@600 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x600 0x100>;
#power-domain-cells = <0>;
};
prm_core: prm@700 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x700 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_iva: prm@1200 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1200 0x100>;
#reset-cells = <1>;
#power-domain-cells = <0>;
};
prm_cam: prm@1300 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1300 0x100>;
#power-domain-cells = <0>;
};
prm_dss: prm@1400 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1400 0x100>;
#power-domain-cells = <0>;
};
prm_gpu: prm@1500 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1500 0x100>;
#power-domain-cells = <0>;
};
prm_l3init: prm@1600 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1600 0x100>;
#power-domain-cells = <0>;
};
prm_custefuse: prm@1700 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1700 0x100>;
#power-domain-cells = <0>;
};
prm_wkupaon: prm@1800 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1800 0x100>;
#power-domain-cells = <0>;
};
prm_emu: prm@1a00 {
compatible = "ti,omap5-prm-inst", "ti,omap-prm-inst";
reg = <0x1a00 0x100>;
#power-domain-cells = <0>;
};
prm_device: prm@1c00 {

View File

@@ -8,7 +8,7 @@
*/
#include <linux/io.h>
#include <linux/of.h>
#include <linux/dma-mapping.h>
#include <linux/dma-map-ops.h>
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>

View File

@@ -9,7 +9,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/dma-map-ops.h>
#include <linux/io.h>
#include <asm/irq.h>

View File

@@ -2,11 +2,15 @@
menu "TI OMAP/AM/DM/DRA Family"
depends on ARCH_MULTI_V6 || ARCH_MULTI_V7
config OMAP_HWMOD
bool
config ARCH_OMAP2
bool "TI OMAP2"
depends on ARCH_MULTI_V6
select ARCH_OMAP2PLUS
select CPU_V6
select OMAP_HWMOD
select SOC_HAS_OMAP2_SDRC
config ARCH_OMAP3
@@ -14,6 +18,7 @@ config ARCH_OMAP3
depends on ARCH_MULTI_V7
select ARCH_OMAP2PLUS
select ARM_CPU_SUSPEND if PM
select OMAP_HWMOD
select OMAP_INTERCONNECT
select PM_OPP if PM
select PM if CPU_IDLE
@@ -30,6 +35,7 @@ config ARCH_OMAP4
select ARM_GIC
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
select OMAP_HWMOD
select OMAP_INTERCONNECT
select OMAP_INTERCONNECT_BARRIER
select PL310_ERRATA_588369 if CACHE_L2X0
@@ -49,6 +55,7 @@ config SOC_OMAP5
select HAVE_ARM_SCU if SMP
select HAVE_ARM_ARCH_TIMER
select ARM_ERRATA_798181 if SMP
select OMAP_HWMOD
select OMAP_INTERCONNECT
select OMAP_INTERCONNECT_BARRIER
select PM_OPP if PM
@@ -84,6 +91,7 @@ config SOC_DRA7XX
select HAVE_ARM_ARCH_TIMER
select IRQ_CROSSBAR
select ARM_ERRATA_798181 if SMP
select OMAP_HWMOD
select OMAP_INTERCONNECT
select OMAP_INTERCONNECT_BARRIER
select PM_OPP if PM

View File

@@ -8,20 +8,22 @@ ccflags-y := -I$(srctree)/$(src)/include \
# Common support
obj-y := id.o io.o control.o devices.o fb.o pm.o \
common.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
omap_device.o omap-headsmp.o sram.o
common.o dma.o omap-headsmp.o sram.o
hwmod-common = omap_hwmod.o omap_hwmod_reset.o \
omap_hwmod_common_data.o
omap_hwmod_common_data.o \
omap_hwmod_common_ipblock_data.o \
omap_device.o display.o hdq1w.o \
i2c.o wd_timer.o
clock-common = clock.o
secure-common = omap-smc.o omap-secure.o
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
obj-$(CONFIG_ARCH_OMAP4) += $(hwmod-common) $(secure-common)
obj-$(CONFIG_SOC_AM33XX) += $(hwmod-common) $(secure-common)
obj-$(CONFIG_SOC_AM33XX) += $(secure-common)
obj-$(CONFIG_SOC_OMAP5) += $(hwmod-common) $(secure-common)
obj-$(CONFIG_SOC_AM43XX) += $(hwmod-common) $(secure-common)
obj-$(CONFIG_SOC_AM43XX) += $(secure-common)
obj-$(CONFIG_SOC_DRA7XX) += $(hwmod-common) $(secure-common)
ifneq ($(CONFIG_SND_SOC_OMAP_MCBSP),)
@@ -194,7 +196,6 @@ obj-$(CONFIG_SOC_OMAP2420) += opp2420_data.o
obj-$(CONFIG_SOC_OMAP2430) += opp2430_data.o
# hwmod data
obj-y += omap_hwmod_common_ipblock_data.o
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_ipblock_data.o
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_3xxx_ipblock_data.o
obj-$(CONFIG_SOC_OMAP2420) += omap_hwmod_2xxx_interconnect_data.o
@@ -205,12 +206,6 @@ obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2xxx_interconnect_data.o
obj-$(CONFIG_SOC_OMAP2430) += omap_hwmod_2430_data.o
obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_2xxx_3xxx_ipblock_data.o
obj-$(CONFIG_ARCH_OMAP3) += omap_hwmod_3xxx_data.o
obj-$(CONFIG_SOC_AM33XX) += omap_hwmod_33xx_data.o
obj-$(CONFIG_SOC_AM33XX) += omap_hwmod_33xx_43xx_interconnect_data.o
obj-$(CONFIG_SOC_AM33XX) += omap_hwmod_33xx_43xx_ipblock_data.o
obj-$(CONFIG_SOC_AM43XX) += omap_hwmod_43xx_data.o
obj-$(CONFIG_SOC_AM43XX) += omap_hwmod_33xx_43xx_interconnect_data.o
obj-$(CONFIG_SOC_AM43XX) += omap_hwmod_33xx_43xx_ipblock_data.o
obj-$(CONFIG_SOC_TI81XX) += omap_hwmod_81xx_data.o
obj-$(CONFIG_ARCH_OMAP4) += omap_hwmod_44xx_data.o
obj-$(CONFIG_SOC_OMAP5) += omap_hwmod_54xx_data.o

View File

@@ -567,8 +567,6 @@ void __init am33xx_init_early(void)
omap2_prcm_base_init();
am33xx_powerdomains_init();
am33xx_clockdomains_init();
am33xx_hwmod_init();
omap_hwmod_init_postsetup();
omap_clk_soc_init = am33xx_dt_clk_init;
omap_secure_init();
}
@@ -590,8 +588,6 @@ void __init am43xx_init_early(void)
omap2_prcm_base_init();
am43xx_powerdomains_init();
am43xx_clockdomains_init();
am43xx_hwmod_init();
omap_hwmod_init_postsetup();
omap_l2_cache_init();
omap_clk_soc_init = am43xx_dt_clk_init;
omap_secure_init();

View File

@@ -627,6 +627,9 @@ static struct clockdomain *_get_clkdm(struct omap_hwmod *oh)
{
struct clk_hw_omap *clk;
if (!oh)
return NULL;
if (oh->clkdm) {
return oh->clkdm;
} else if (oh->_clk) {
@@ -3677,6 +3680,9 @@ static void __init omap_hwmod_setup_earlycon_flags(void)
*/
static int __init omap_hwmod_setup_all(void)
{
if (!inited)
return 0;
_ensure_mpu_hwmod_is_setup(NULL);
omap_hwmod_for_each(_init, NULL);

View File

@@ -1,57 +0,0 @@
/*
*
* Copyright (C) 2013 Texas Instruments Incorporated
*
* Data common for AM335x and AM43x
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_33XX_43XX_COMMON_DATA_H
#define __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_33XX_43XX_COMMON_DATA_H
extern struct omap_hwmod_ocp_if am33xx_mpu__l3_main;
extern struct omap_hwmod_ocp_if am33xx_l3_main__l3_s;
extern struct omap_hwmod_ocp_if am33xx_l3_s__l4_ls;
extern struct omap_hwmod_ocp_if am33xx_l3_s__l4_wkup;
extern struct omap_hwmod_ocp_if am33xx_l3_main__l3_instr;
extern struct omap_hwmod_ocp_if am33xx_mpu__prcm;
extern struct omap_hwmod_ocp_if am33xx_l3_s__l3_main;
extern struct omap_hwmod_ocp_if am33xx_gfx__l3_main;
extern struct omap_hwmod_ocp_if am33xx_l3_main__gfx;
extern struct omap_hwmod_ocp_if am33xx_l3_s__gpmc;
extern struct omap_hwmod_ocp_if am33xx_l4_ls__timer2;
extern struct omap_hwmod_ocp_if am33xx_l3_main__ocmc;
extern struct omap_hwmod am33xx_l3_main_hwmod;
extern struct omap_hwmod am33xx_l3_s_hwmod;
extern struct omap_hwmod am33xx_l3_instr_hwmod;
extern struct omap_hwmod am33xx_l4_ls_hwmod;
extern struct omap_hwmod am33xx_l4_wkup_hwmod;
extern struct omap_hwmod am33xx_mpu_hwmod;
extern struct omap_hwmod am33xx_gfx_hwmod;
extern struct omap_hwmod am33xx_prcm_hwmod;
extern struct omap_hwmod am33xx_ocmcram_hwmod;
extern struct omap_hwmod am33xx_smartreflex0_hwmod;
extern struct omap_hwmod am33xx_smartreflex1_hwmod;
extern struct omap_hwmod am33xx_gpmc_hwmod;
extern struct omap_hwmod_class am33xx_emif_hwmod_class;
extern struct omap_hwmod_class am33xx_l4_hwmod_class;
extern struct omap_hwmod_class am33xx_wkup_m3_hwmod_class;
extern struct omap_hwmod_class am33xx_control_hwmod_class;
extern struct omap_hwmod_class am33xx_timer_hwmod_class;
extern struct omap_hwmod_class am33xx_ehrpwm_hwmod_class;
extern struct omap_hwmod_class am33xx_spi_hwmod_class;
void omap_hwmod_am33xx_reg(void);
void omap_hwmod_am43xx_reg(void);
#endif

View File

@@ -1,90 +0,0 @@
/*
*
* Copyright (C) 2013 Texas Instruments Incorporated
*
* Interconnects common for AM335x and AM43x
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/sizes.h>
#include "omap_hwmod.h"
#include "omap_hwmod_33xx_43xx_common_data.h"
/* mpu -> l3 main */
struct omap_hwmod_ocp_if am33xx_mpu__l3_main = {
.master = &am33xx_mpu_hwmod,
.slave = &am33xx_l3_main_hwmod,
.clk = "dpll_mpu_m2_ck",
.user = OCP_USER_MPU,
};
/* l3 main -> l3 s */
struct omap_hwmod_ocp_if am33xx_l3_main__l3_s = {
.master = &am33xx_l3_main_hwmod,
.slave = &am33xx_l3_s_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3 s -> l4 per/ls */
struct omap_hwmod_ocp_if am33xx_l3_s__l4_ls = {
.master = &am33xx_l3_s_hwmod,
.slave = &am33xx_l4_ls_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3 s -> l4 wkup */
struct omap_hwmod_ocp_if am33xx_l3_s__l4_wkup = {
.master = &am33xx_l3_s_hwmod,
.slave = &am33xx_l4_wkup_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3 main -> l3 instr */
struct omap_hwmod_ocp_if am33xx_l3_main__l3_instr = {
.master = &am33xx_l3_main_hwmod,
.slave = &am33xx_l3_instr_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* mpu -> prcm */
struct omap_hwmod_ocp_if am33xx_mpu__prcm = {
.master = &am33xx_mpu_hwmod,
.slave = &am33xx_prcm_hwmod,
.clk = "dpll_mpu_m2_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3 s -> l3 main*/
struct omap_hwmod_ocp_if am33xx_l3_s__l3_main = {
.master = &am33xx_l3_s_hwmod,
.slave = &am33xx_l3_main_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3s cfg -> gpmc */
struct omap_hwmod_ocp_if am33xx_l3_s__gpmc = {
.master = &am33xx_l3_s_hwmod,
.slave = &am33xx_gpmc_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU,
};
/* l3 main -> ocmc */
struct omap_hwmod_ocp_if am33xx_l3_main__ocmc = {
.master = &am33xx_l3_main_hwmod,
.slave = &am33xx_ocmcram_hwmod,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};

View File

@@ -1,290 +0,0 @@
/*
*
* Copyright (C) 2013 Texas Instruments Incorporated
*
* Hwmod common for AM335x and AM43x
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/types.h>
#include "omap_hwmod.h"
#include "cm33xx.h"
#include "prm33xx.h"
#include "omap_hwmod_33xx_43xx_common_data.h"
#include "prcm43xx.h"
#include "common.h"
#define CLKCTRL(oh, clkctrl) ((oh).prcm.omap4.clkctrl_offs = (clkctrl))
#define RSTCTRL(oh, rstctrl) ((oh).prcm.omap4.rstctrl_offs = (rstctrl))
#define RSTST(oh, rstst) ((oh).prcm.omap4.rstst_offs = (rstst))
/*
* 'l3' class
* instance(s): l3_main, l3_s, l3_instr
*/
static struct omap_hwmod_class am33xx_l3_hwmod_class = {
.name = "l3",
};
struct omap_hwmod am33xx_l3_main_hwmod = {
.name = "l3_main",
.class = &am33xx_l3_hwmod_class,
.clkdm_name = "l3_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "l3_gclk",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/* l3_s */
struct omap_hwmod am33xx_l3_s_hwmod = {
.name = "l3_s",
.class = &am33xx_l3_hwmod_class,
.clkdm_name = "l3s_clkdm",
};
/* l3_instr */
struct omap_hwmod am33xx_l3_instr_hwmod = {
.name = "l3_instr",
.class = &am33xx_l3_hwmod_class,
.clkdm_name = "l3_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "l3_gclk",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/*
* 'l4' class
* instance(s): l4_ls, l4_hs, l4_wkup, l4_fw
*/
struct omap_hwmod_class am33xx_l4_hwmod_class = {
.name = "l4",
};
/* l4_ls */
struct omap_hwmod am33xx_l4_ls_hwmod = {
.name = "l4_ls",
.class = &am33xx_l4_hwmod_class,
.clkdm_name = "l4ls_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "l4ls_gclk",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/* l4_wkup */
struct omap_hwmod am33xx_l4_wkup_hwmod = {
.name = "l4_wkup",
.class = &am33xx_l4_hwmod_class,
.clkdm_name = "l4_wkup_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/*
* 'mpu' class
*/
static struct omap_hwmod_class am33xx_mpu_hwmod_class = {
.name = "mpu",
};
struct omap_hwmod am33xx_mpu_hwmod = {
.name = "mpu",
.class = &am33xx_mpu_hwmod_class,
.clkdm_name = "mpu_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "dpll_mpu_m2_ck",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/*
* 'wakeup m3' class
* Wakeup controller sub-system under wakeup domain
*/
struct omap_hwmod_class am33xx_wkup_m3_hwmod_class = {
.name = "wkup_m3",
};
/*
* 'prcm' class
* power and reset manager (whole prcm infrastructure)
*/
static struct omap_hwmod_class am33xx_prcm_hwmod_class = {
.name = "prcm",
};
/* prcm */
struct omap_hwmod am33xx_prcm_hwmod = {
.name = "prcm",
.class = &am33xx_prcm_hwmod_class,
.clkdm_name = "l4_wkup_clkdm",
};
/*
* 'emif' class
* instance(s): emif
*/
static struct omap_hwmod_class_sysconfig am33xx_emif_sysc = {
.rev_offs = 0x0000,
};
struct omap_hwmod_class am33xx_emif_hwmod_class = {
.name = "emif",
.sysc = &am33xx_emif_sysc,
};
/* ocmcram */
static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = {
.name = "ocmcram",
};
struct omap_hwmod am33xx_ocmcram_hwmod = {
.name = "ocmcram",
.class = &am33xx_ocmcram_hwmod_class,
.clkdm_name = "l3_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "l3_gclk",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/* 'smartreflex' class */
static struct omap_hwmod_class am33xx_smartreflex_hwmod_class = {
.name = "smartreflex",
};
/* smartreflex0 */
struct omap_hwmod am33xx_smartreflex0_hwmod = {
.name = "smartreflex0",
.class = &am33xx_smartreflex_hwmod_class,
.clkdm_name = "l4_wkup_clkdm",
.main_clk = "smartreflex0_fck",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/* smartreflex1 */
struct omap_hwmod am33xx_smartreflex1_hwmod = {
.name = "smartreflex1",
.class = &am33xx_smartreflex_hwmod_class,
.clkdm_name = "l4_wkup_clkdm",
.main_clk = "smartreflex1_fck",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/*
* 'control' module class
*/
struct omap_hwmod_class am33xx_control_hwmod_class = {
.name = "control",
};
/* gpmc */
static struct omap_hwmod_class_sysconfig gpmc_sysc = {
.rev_offs = 0x0,
.sysc_offs = 0x10,
.syss_offs = 0x14,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
.sysc_fields = &omap_hwmod_sysc_type1,
};
static struct omap_hwmod_class am33xx_gpmc_hwmod_class = {
.name = "gpmc",
.sysc = &gpmc_sysc,
};
struct omap_hwmod am33xx_gpmc_hwmod = {
.name = "gpmc",
.class = &am33xx_gpmc_hwmod_class,
.clkdm_name = "l3s_clkdm",
/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
.flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS,
.main_clk = "l3s_gclk",
.prcm = {
.omap4 = {
.modulemode = MODULEMODE_SWCTRL,
},
},
};
static void omap_hwmod_am33xx_clkctrl(void)
{
CLKCTRL(am33xx_smartreflex0_hwmod,
AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET);
CLKCTRL(am33xx_smartreflex1_hwmod,
AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET);
CLKCTRL(am33xx_gpmc_hwmod, AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l4_ls_hwmod, AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l4_wkup_hwmod, AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l3_main_hwmod, AM33XX_CM_PER_L3_CLKCTRL_OFFSET);
CLKCTRL(am33xx_mpu_hwmod , AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l3_instr_hwmod , AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET);
CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET);
}
void omap_hwmod_am33xx_reg(void)
{
omap_hwmod_am33xx_clkctrl();
}
static void omap_hwmod_am43xx_clkctrl(void)
{
CLKCTRL(am33xx_smartreflex0_hwmod,
AM43XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET);
CLKCTRL(am33xx_smartreflex1_hwmod,
AM43XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET);
CLKCTRL(am33xx_gpmc_hwmod, AM43XX_CM_PER_GPMC_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l4_ls_hwmod, AM43XX_CM_PER_L4LS_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l4_wkup_hwmod, AM43XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l3_main_hwmod, AM43XX_CM_PER_L3_CLKCTRL_OFFSET);
CLKCTRL(am33xx_mpu_hwmod , AM43XX_CM_MPU_MPU_CLKCTRL_OFFSET);
CLKCTRL(am33xx_l3_instr_hwmod , AM43XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET);
CLKCTRL(am33xx_ocmcram_hwmod , AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET);
}
void omap_hwmod_am43xx_reg(void)
{
omap_hwmod_am43xx_clkctrl();
}

View File

@@ -1,294 +0,0 @@
/*
* omap_hwmod_33xx_data.c: Hardware modules present on the AM33XX chips
*
* Copyright (C) {2012} Texas Instruments Incorporated - https://www.ti.com/
*
* This file is automatically generated from the AM33XX hardware databases.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "omap_hwmod.h"
#include "omap_hwmod_common_data.h"
#include "control.h"
#include "cm33xx.h"
#include "prm33xx.h"
#include "prm-regbits-33xx.h"
#include "omap_hwmod_33xx_43xx_common_data.h"
/*
* IP blocks
*/
/* emif */
static struct omap_hwmod am33xx_emif_hwmod = {
.name = "emif",
.class = &am33xx_emif_hwmod_class,
.clkdm_name = "l3_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "dpll_ddr_m2_div2_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/* l4_hs */
static struct omap_hwmod am33xx_l4_hs_hwmod = {
.name = "l4_hs",
.class = &am33xx_l4_hwmod_class,
.clkdm_name = "l4hs_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "l4hs_gclk",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_PER_L4HS_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
static struct omap_hwmod_rst_info am33xx_wkup_m3_resets[] = {
{ .name = "wkup_m3", .rst_shift = 3, .st_shift = 5 },
};
/* wkup_m3 */
static struct omap_hwmod am33xx_wkup_m3_hwmod = {
.name = "wkup_m3",
.class = &am33xx_wkup_m3_hwmod_class,
.clkdm_name = "l4_wkup_aon_clkdm",
/* Keep hardreset asserted */
.flags = HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST,
.main_clk = "dpll_core_m4_div2_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET,
.rstctrl_offs = AM33XX_RM_WKUP_RSTCTRL_OFFSET,
.rstst_offs = AM33XX_RM_WKUP_RSTST_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
.rst_lines = am33xx_wkup_m3_resets,
.rst_lines_cnt = ARRAY_SIZE(am33xx_wkup_m3_resets),
};
/*
* Modules omap_hwmod structures
*
* The following IPs are excluded for the moment because:
* - They do not need an explicit SW control using omap_hwmod API.
* - They still need to be validated with the driver
* properly adapted to omap_hwmod / omap_device
*
* - cEFUSE (doesn't fall under any ocp_if)
* - clkdiv32k
* - ocp watch point
*/
#if 0
/*
* 'cefuse' class
*/
static struct omap_hwmod_class am33xx_cefuse_hwmod_class = {
.name = "cefuse",
};
static struct omap_hwmod am33xx_cefuse_hwmod = {
.name = "cefuse",
.class = &am33xx_cefuse_hwmod_class,
.clkdm_name = "l4_cefuse_clkdm",
.main_clk = "cefuse_fck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/*
* 'clkdiv32k' class
*/
static struct omap_hwmod_class am33xx_clkdiv32k_hwmod_class = {
.name = "clkdiv32k",
};
static struct omap_hwmod am33xx_clkdiv32k_hwmod = {
.name = "clkdiv32k",
.class = &am33xx_clkdiv32k_hwmod_class,
.clkdm_name = "clk_24mhz_clkdm",
.main_clk = "clkdiv32k_ick",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_PER_CLKDIV32K_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/* ocpwp */
static struct omap_hwmod_class am33xx_ocpwp_hwmod_class = {
.name = "ocpwp",
};
static struct omap_hwmod am33xx_ocpwp_hwmod = {
.name = "ocpwp",
.class = &am33xx_ocpwp_hwmod_class,
.clkdm_name = "l4ls_clkdm",
.main_clk = "l4ls_gclk",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_PER_OCPWP_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
#endif
/*
* 'debugss' class
* debug sub system
*/
static struct omap_hwmod_opt_clk debugss_opt_clks[] = {
{ .role = "dbg_sysclk", .clk = "dbg_sysclk_ck" },
{ .role = "dbg_clka", .clk = "dbg_clka_ck" },
};
static struct omap_hwmod_class am33xx_debugss_hwmod_class = {
.name = "debugss",
};
static struct omap_hwmod am33xx_debugss_hwmod = {
.name = "debugss",
.class = &am33xx_debugss_hwmod_class,
.clkdm_name = "l3_aon_clkdm",
.main_clk = "trace_clk_div_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_WKUP_DEBUGSS_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
.opt_clks = debugss_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(debugss_opt_clks),
};
static struct omap_hwmod am33xx_control_hwmod = {
.name = "control",
.class = &am33xx_control_hwmod_class,
.clkdm_name = "l4_wkup_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "dpll_core_m4_div2_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/*
* Interfaces
*/
/* l3 main -> emif */
static struct omap_hwmod_ocp_if am33xx_l3_main__emif = {
.master = &am33xx_l3_main_hwmod,
.slave = &am33xx_emif_hwmod,
.clk = "dpll_core_m4_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3 main -> l4 hs */
static struct omap_hwmod_ocp_if am33xx_l3_main__l4_hs = {
.master = &am33xx_l3_main_hwmod,
.slave = &am33xx_l4_hs_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* wkup m3 -> l4 wkup */
static struct omap_hwmod_ocp_if am33xx_wkup_m3__l4_wkup = {
.master = &am33xx_wkup_m3_hwmod,
.slave = &am33xx_l4_wkup_hwmod,
.clk = "dpll_core_m4_div2_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l4 wkup -> wkup m3 */
static struct omap_hwmod_ocp_if am33xx_l4_wkup__wkup_m3 = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am33xx_wkup_m3_hwmod,
.clk = "dpll_core_m4_div2_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3_main -> debugss */
static struct omap_hwmod_ocp_if am33xx_l3_main__debugss = {
.master = &am33xx_l3_main_hwmod,
.slave = &am33xx_debugss_hwmod,
.clk = "dpll_core_m4_ck",
.user = OCP_USER_MPU,
};
/* l4 wkup -> smartreflex0 */
static struct omap_hwmod_ocp_if am33xx_l4_wkup__smartreflex0 = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am33xx_smartreflex0_hwmod,
.clk = "dpll_core_m4_div2_ck",
.user = OCP_USER_MPU,
};
/* l4 wkup -> smartreflex1 */
static struct omap_hwmod_ocp_if am33xx_l4_wkup__smartreflex1 = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am33xx_smartreflex1_hwmod,
.clk = "dpll_core_m4_div2_ck",
.user = OCP_USER_MPU,
};
/* l4 wkup -> control */
static struct omap_hwmod_ocp_if am33xx_l4_wkup__control = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am33xx_control_hwmod,
.clk = "dpll_core_m4_div2_ck",
.user = OCP_USER_MPU,
};
static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
&am33xx_l3_main__emif,
&am33xx_mpu__l3_main,
&am33xx_mpu__prcm,
&am33xx_l3_s__l4_ls,
&am33xx_l3_s__l4_wkup,
&am33xx_l3_main__l4_hs,
&am33xx_l3_main__l3_s,
&am33xx_l3_main__l3_instr,
&am33xx_l3_s__l3_main,
&am33xx_wkup_m3__l4_wkup,
&am33xx_l3_main__debugss,
&am33xx_l4_wkup__wkup_m3,
&am33xx_l4_wkup__control,
&am33xx_l4_wkup__smartreflex0,
&am33xx_l4_wkup__smartreflex1,
&am33xx_l3_s__gpmc,
&am33xx_l3_main__ocmc,
NULL,
};
int __init am33xx_hwmod_init(void)
{
omap_hwmod_am33xx_reg();
omap_hwmod_init();
return omap_hwmod_register_links(am33xx_hwmod_ocp_ifs);
}

View File

@@ -1,167 +0,0 @@
/*
* Copyright (C) 2013 Texas Instruments Incorporated
*
* Hwmod present only in AM43x and those that differ other than register
* offsets as compared to AM335x.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "omap_hwmod.h"
#include "omap_hwmod_33xx_43xx_common_data.h"
#include "prcm43xx.h"
#include "omap_hwmod_common_data.h"
/* IP blocks */
static struct omap_hwmod am43xx_emif_hwmod = {
.name = "emif",
.class = &am33xx_emif_hwmod_class,
.clkdm_name = "emif_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "dpll_ddr_m2_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
static struct omap_hwmod am43xx_l4_hs_hwmod = {
.name = "l4_hs",
.class = &am33xx_l4_hwmod_class,
.clkdm_name = "l3_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "l4hs_gclk",
.prcm = {
.omap4 = {
.clkctrl_offs = AM43XX_CM_PER_L4HS_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
static struct omap_hwmod_rst_info am33xx_wkup_m3_resets[] = {
{ .name = "wkup_m3", .rst_shift = 3, .st_shift = 5 },
};
static struct omap_hwmod am43xx_wkup_m3_hwmod = {
.name = "wkup_m3",
.class = &am33xx_wkup_m3_hwmod_class,
.clkdm_name = "l4_wkup_aon_clkdm",
/* Keep hardreset asserted */
.flags = HWMOD_INIT_NO_RESET | HWMOD_NO_IDLEST,
.main_clk = "sys_clkin_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM43XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET,
.rstctrl_offs = AM43XX_RM_WKUP_RSTCTRL_OFFSET,
.rstst_offs = AM43XX_RM_WKUP_RSTST_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
.rst_lines = am33xx_wkup_m3_resets,
.rst_lines_cnt = ARRAY_SIZE(am33xx_wkup_m3_resets),
};
static struct omap_hwmod am43xx_control_hwmod = {
.name = "control",
.class = &am33xx_control_hwmod_class,
.clkdm_name = "l4_wkup_clkdm",
.flags = HWMOD_INIT_NO_IDLE,
.main_clk = "sys_clkin_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = AM43XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
};
/* Interfaces */
static struct omap_hwmod_ocp_if am43xx_l3_main__emif = {
.master = &am33xx_l3_main_hwmod,
.slave = &am43xx_emif_hwmod,
.clk = "dpll_core_m4_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
static struct omap_hwmod_ocp_if am43xx_l3_main__l4_hs = {
.master = &am33xx_l3_main_hwmod,
.slave = &am43xx_l4_hs_hwmod,
.clk = "l3s_gclk",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
static struct omap_hwmod_ocp_if am43xx_wkup_m3__l4_wkup = {
.master = &am43xx_wkup_m3_hwmod,
.slave = &am33xx_l4_wkup_hwmod,
.clk = "sys_clkin_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
static struct omap_hwmod_ocp_if am43xx_l4_wkup__wkup_m3 = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am43xx_wkup_m3_hwmod,
.clk = "sys_clkin_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
static struct omap_hwmod_ocp_if am43xx_l4_wkup__smartreflex0 = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am33xx_smartreflex0_hwmod,
.clk = "sys_clkin_ck",
.user = OCP_USER_MPU,
};
static struct omap_hwmod_ocp_if am43xx_l4_wkup__smartreflex1 = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am33xx_smartreflex1_hwmod,
.clk = "sys_clkin_ck",
.user = OCP_USER_MPU,
};
static struct omap_hwmod_ocp_if am43xx_l4_wkup__control = {
.master = &am33xx_l4_wkup_hwmod,
.slave = &am43xx_control_hwmod,
.clk = "sys_clkin_ck",
.user = OCP_USER_MPU,
};
static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
&am33xx_mpu__l3_main,
&am33xx_mpu__prcm,
&am33xx_l3_s__l4_ls,
&am33xx_l3_s__l4_wkup,
&am43xx_l3_main__l4_hs,
&am33xx_l3_main__l3_s,
&am33xx_l3_main__l3_instr,
&am33xx_l3_s__l3_main,
&am43xx_l3_main__emif,
&am43xx_wkup_m3__l4_wkup,
&am43xx_l4_wkup__wkup_m3,
&am43xx_l4_wkup__control,
&am43xx_l4_wkup__smartreflex0,
&am43xx_l4_wkup__smartreflex1,
&am33xx_l3_s__gpmc,
&am33xx_l3_main__ocmc,
NULL,
};
int __init am43xx_hwmod_init(void)
{
int ret;
omap_hwmod_am43xx_reg();
omap_hwmod_init();
ret = omap_hwmod_register_links(am43xx_hwmod_ocp_ifs);
return ret;
}

View File

@@ -353,42 +353,6 @@ static struct omap_hwmod omap44xx_emif2_hwmod = {
},
};
/*
* 'gpmc' class
* general purpose memory controller
*/
static struct omap_hwmod_class_sysconfig omap44xx_gpmc_sysc = {
.rev_offs = 0x0000,
.sysc_offs = 0x0010,
.syss_offs = 0x0014,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
.sysc_fields = &omap_hwmod_sysc_type1,
};
static struct omap_hwmod_class omap44xx_gpmc_hwmod_class = {
.name = "gpmc",
.sysc = &omap44xx_gpmc_sysc,
};
/* gpmc */
static struct omap_hwmod omap44xx_gpmc_hwmod = {
.name = "gpmc",
.class = &omap44xx_gpmc_hwmod_class,
.clkdm_name = "l3_2_clkdm",
/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
.flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS,
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET,
.context_offs = OMAP4_RM_L3_2_GPMC_CONTEXT_OFFSET,
.modulemode = MODULEMODE_HWCTRL,
},
},
};
/*
* 'iss' class
* external images sensor pixel data processor
@@ -440,39 +404,6 @@ static struct omap_hwmod omap44xx_iss_hwmod = {
.opt_clks_cnt = ARRAY_SIZE(iss_opt_clks),
};
/*
* 'iva' class
* multi-standard video encoder/decoder hardware accelerator
*/
static struct omap_hwmod_class omap44xx_iva_hwmod_class = {
.name = "iva",
};
/* iva */
static struct omap_hwmod_rst_info omap44xx_iva_resets[] = {
{ .name = "seq0", .rst_shift = 0 },
{ .name = "seq1", .rst_shift = 1 },
{ .name = "logic", .rst_shift = 2 },
};
static struct omap_hwmod omap44xx_iva_hwmod = {
.name = "iva",
.class = &omap44xx_iva_hwmod_class,
.clkdm_name = "ivahd_clkdm",
.rst_lines = omap44xx_iva_resets,
.rst_lines_cnt = ARRAY_SIZE(omap44xx_iva_resets),
.main_clk = "dpll_iva_m5x2_ck",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET,
.rstctrl_offs = OMAP4_RM_IVAHD_RSTCTRL_OFFSET,
.context_offs = OMAP4_RM_IVAHD_IVAHD_CONTEXT_OFFSET,
.modulemode = MODULEMODE_HWCTRL,
},
},
};
/*
* 'mpu' class
* mpu sub-system
@@ -644,14 +575,6 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
.user = OCP_USER_MPU,
};
/* iva -> l3_instr */
static struct omap_hwmod_ocp_if omap44xx_iva__l3_instr = {
.master = &omap44xx_iva_hwmod,
.slave = &omap44xx_l3_instr_hwmod,
.clk = "l3_div_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3_main_3 -> l3_instr */
static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
.master = &omap44xx_l3_main_3_hwmod,
@@ -708,14 +631,6 @@ static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* iva -> l3_main_2 */
static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
.master = &omap44xx_iva_hwmod,
.slave = &omap44xx_l3_main_2_hwmod,
.clk = "l3_div_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3_main_1 -> l3_main_2 */
static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
.master = &omap44xx_l3_main_1_hwmod,
@@ -836,14 +751,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_instr__debugss = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3_main_2 -> gpmc */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__gpmc = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_gpmc_hwmod,
.clk = "l3_div_ck",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3_main_2 -> iss */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
.master = &omap44xx_l3_main_2_hwmod,
@@ -852,22 +759,6 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* iva -> sl2if */
static struct omap_hwmod_ocp_if __maybe_unused omap44xx_iva__sl2if = {
.master = &omap44xx_iva_hwmod,
.slave = &omap44xx_sl2if_hwmod,
.clk = "dpll_iva_m5x2_ck",
.user = OCP_USER_IVA,
};
/* l3_main_2 -> iva */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
.master = &omap44xx_l3_main_2_hwmod,
.slave = &omap44xx_iva_hwmod,
.clk = "l3_div_ck",
.user = OCP_USER_MPU,
};
/* l3_main_2 -> ocmc_ram */
static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ocmc_ram = {
.master = &omap44xx_l3_main_2_hwmod,
@@ -943,7 +834,6 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__emif2 = {
static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
&omap44xx_l3_main_1__dmm,
&omap44xx_mpu__dmm,
&omap44xx_iva__l3_instr,
&omap44xx_l3_main_3__l3_instr,
&omap44xx_ocp_wp_noc__l3_instr,
&omap44xx_l3_main_2__l3_main_1,
@@ -951,7 +841,6 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
&omap44xx_mpu__l3_main_1,
&omap44xx_debugss__l3_main_2,
&omap44xx_iss__l3_main_2,
&omap44xx_iva__l3_main_2,
&omap44xx_l3_main_1__l3_main_2,
&omap44xx_l4_cfg__l3_main_2,
&omap44xx_l3_main_1__l3_main_3,
@@ -967,10 +856,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
&omap44xx_l4_wkup__ctrl_module_wkup,
&omap44xx_l4_wkup__ctrl_module_pad_wkup,
&omap44xx_l3_instr__debugss,
&omap44xx_l3_main_2__gpmc,
&omap44xx_l3_main_2__iss,
/* &omap44xx_iva__sl2if, */
&omap44xx_l3_main_2__iva,
&omap44xx_l3_main_2__ocmc_ram,
&omap44xx_mpu_private__prcm_mpu,
&omap44xx_l4_wkup__cm_core_aon,

View File

@@ -242,46 +242,6 @@ static struct omap_hwmod dra7xx_ctrl_module_wkup_hwmod = {
},
};
/*
* 'gpmc' class
*
*/
static struct omap_hwmod_class_sysconfig dra7xx_gpmc_sysc = {
.rev_offs = 0x0000,
.sysc_offs = 0x0010,
.syss_offs = 0x0014,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
.sysc_fields = &omap_hwmod_sysc_type1,
};
static struct omap_hwmod_class dra7xx_gpmc_hwmod_class = {
.name = "gpmc",
.sysc = &dra7xx_gpmc_sysc,
};
/* gpmc */
static struct omap_hwmod dra7xx_gpmc_hwmod = {
.name = "gpmc",
.class = &dra7xx_gpmc_hwmod_class,
.clkdm_name = "l3main1_clkdm",
/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
.flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS,
.main_clk = "l3_iclk_div",
.prcm = {
.omap4 = {
.clkctrl_offs = DRA7XX_CM_L3MAIN1_GPMC_CLKCTRL_OFFSET,
.context_offs = DRA7XX_RM_L3MAIN1_GPMC_CONTEXT_OFFSET,
.modulemode = MODULEMODE_HWCTRL,
},
},
};
/*
* 'mpu' class
*
@@ -611,14 +571,6 @@ static struct omap_hwmod_ocp_if dra7xx_l4_wkup__ctrl_module_wkup = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l3_main_1 -> gpmc */
static struct omap_hwmod_ocp_if dra7xx_l3_main_1__gpmc = {
.master = &dra7xx_l3_main_1_hwmod,
.slave = &dra7xx_gpmc_hwmod,
.clk = "l3_iclk_div",
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* l4_cfg -> mpu */
static struct omap_hwmod_ocp_if dra7xx_l4_cfg__mpu = {
.master = &dra7xx_l4_cfg_hwmod,
@@ -722,7 +674,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
&dra7xx_l4_per2__atl,
&dra7xx_l3_main_1__bb2d,
&dra7xx_l4_wkup__ctrl_module_wkup,
&dra7xx_l3_main_1__gpmc,
&dra7xx_l4_cfg__mpu,
&dra7xx_l3_main_1__pciess1,
&dra7xx_l4_cfg__pciess1,

View File

@@ -94,6 +94,7 @@ static void __init hsmmc2_internal_input_clk(void)
omap_ctrl_writel(reg, OMAP343X_CONTROL_DEVCONF1);
}
#ifdef CONFIG_OMAP_HWMOD
static struct iommu_platform_data omap3_iommu_pdata = {
.reset_name = "mmu",
.assert_reset = omap_device_assert_hardreset,
@@ -106,6 +107,7 @@ static struct iommu_platform_data omap3_iommu_isp_pdata = {
.device_enable = omap_device_enable,
.device_idle = omap_device_idle,
};
#endif
static int omap3_sbc_t3730_twl_callback(struct device *dev,
unsigned gpio,
@@ -272,14 +274,6 @@ static void __init omap3_pandora_legacy_init(void)
}
#endif /* CONFIG_ARCH_OMAP3 */
#if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
static struct wkup_m3_platform_data wkup_m3_data = {
.reset_name = "wkup_m3",
.assert_reset = omap_device_assert_hardreset,
.deassert_reset = omap_device_deassert_hardreset,
};
#endif
#ifdef CONFIG_SOC_OMAP5
static void __init omap5_uevm_legacy_init(void)
{
@@ -370,6 +364,7 @@ static void ti_sysc_clkdm_allow_idle(struct device *dev,
clkdm_allow_idle(cookie->clkdm);
}
#ifdef CONFIG_OMAP_HWMOD
static int ti_sysc_enable_module(struct device *dev,
const struct ti_sysc_cookie *cookie)
{
@@ -396,6 +391,7 @@ static int ti_sysc_shutdown_module(struct device *dev,
return omap_hwmod_shutdown(cookie->data);
}
#endif /* CONFIG_OMAP_HWMOD */
static bool ti_sysc_soc_type_gp(void)
{
@@ -410,10 +406,12 @@ static struct ti_sysc_platform_data ti_sysc_pdata = {
.init_clockdomain = ti_sysc_clkdm_init,
.clkdm_deny_idle = ti_sysc_clkdm_deny_idle,
.clkdm_allow_idle = ti_sysc_clkdm_allow_idle,
#ifdef CONFIG_OMAP_HWMOD
.init_module = omap_hwmod_init_module,
.enable_module = ti_sysc_enable_module,
.idle_module = ti_sysc_idle_module,
.shutdown_module = ti_sysc_shutdown_module,
#endif
};
static struct pcs_pdata pcs_pdata;
@@ -501,14 +499,6 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49024000, "49024000.mcbsp", &mcbsp_pdata),
#endif
#endif
#ifdef CONFIG_SOC_AM33XX
OF_DEV_AUXDATA("ti,am3352-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
&wkup_m3_data),
#endif
#ifdef CONFIG_SOC_AM43XX
OF_DEV_AUXDATA("ti,am4372-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
&wkup_m3_data),
#endif
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
OF_DEV_AUXDATA("ti,omap4-smartreflex-iva", 0x4a0db000,
"4a0db000.smartreflex", &omap_sr_pdata[OMAP_SR_IVA]),
@@ -580,6 +570,8 @@ static void pdata_quirks_check(struct pdata_init *quirks)
void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
{
struct device_node *np;
/*
* We still need this for omap2420 and omap3 PM to work, others are
* using drivers/misc/sram.c already.
@@ -591,6 +583,15 @@ void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
if (of_machine_is_compatible("ti,omap3"))
omap3_mcbsp_init();
pdata_quirks_check(auxdata_quirks);
/* Populate always-on PRCM in l4_wkup to probe l4_wkup */
np = of_find_node_by_name(NULL, "prcm");
if (!np)
np = of_find_node_by_name(NULL, "prm");
if (np)
of_platform_populate(np, omap_dt_match_table,
omap_auxdata_lookup, NULL);
of_platform_populate(NULL, omap_dt_match_table,
omap_auxdata_lookup, NULL);
pdata_quirks_check(pdata_quirks);

View File

@@ -12,7 +12,7 @@
#include <linux/io.h>
#include <linux/async.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dma-map-ops.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/sh_clk.h>

View File

@@ -11,7 +11,8 @@
#include <linux/pci_ids.h>
#include <linux/export.h>
#include <linux/list.h>
#include <linux/dma-direct.h>
#include <linux/dma-map-ops.h>
#include <linux/swiotlb.h>
#include <asm/iommu.h>
#define STA2X11_SWIOTLB_SIZE (4*1024*1024)

View File

@@ -853,8 +853,12 @@ static int sysc_ioremap(struct sysc *ddata)
*/
static int sysc_map_and_check_registers(struct sysc *ddata)
{
struct device_node *np = ddata->dev->of_node;
int error;
if (!of_get_property(np, "reg", NULL))
return 0;
error = sysc_parse_and_check_child_range(ddata);
if (error)
return error;
@@ -1222,10 +1226,10 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
ddata->enabled = false;
err_allow_idle:
reset_control_assert(ddata->rsts);
sysc_clkdm_allow_idle(ddata);
reset_control_assert(ddata->rsts);
return error;
}
@@ -1379,6 +1383,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK_CLKDM_NOAUTO),
SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff,
SYSC_QUIRK_CLKDM_NOAUTO),
SYSC_QUIRK("gpmc", 0, 0, 0x10, 0x14, 0x00000060, 0xffffffff,
SYSC_QUIRK_GPMC_DEBUG),
SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff,
SYSC_QUIRK_OPT_CLKS_NEEDED),
SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff,
@@ -1814,6 +1820,14 @@ static void sysc_init_module_quirks(struct sysc *ddata)
return;
}
#ifdef CONFIG_OMAP_GPMC_DEBUG
if (ddata->cfg.quirks & SYSC_QUIRK_GPMC_DEBUG) {
ddata->cfg.quirks |= SYSC_QUIRK_NO_RESET_ON_INIT;
return;
}
#endif
if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) {
ddata->pre_reset_quirk = sysc_pre_reset_quirk_i2c;
ddata->post_reset_quirk = sysc_post_reset_quirk_i2c;
@@ -1945,6 +1959,7 @@ static int sysc_reset(struct sysc *ddata)
*/
static int sysc_init_module(struct sysc *ddata)
{
bool rstctrl_deasserted = false;
int error = 0;
error = sysc_clockdomain_init(ddata);
@@ -1969,6 +1984,7 @@ static int sysc_init_module(struct sysc *ddata)
error = reset_control_deassert(ddata->rsts);
if (error)
goto err_main_clocks;
rstctrl_deasserted = true;
}
ddata->revision = sysc_read_revision(ddata);
@@ -1978,13 +1994,13 @@ static int sysc_init_module(struct sysc *ddata)
if (ddata->legacy_mode) {
error = sysc_legacy_init(ddata);
if (error)
goto err_reset;
goto err_main_clocks;
}
if (!ddata->legacy_mode) {
error = sysc_enable_module(ddata->dev);
if (error)
goto err_reset;
goto err_main_clocks;
}
error = sysc_reset(ddata);
@@ -1994,10 +2010,6 @@ static int sysc_init_module(struct sysc *ddata)
if (error && !ddata->legacy_mode)
sysc_disable_module(ddata->dev);
err_reset:
if (error && !(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT))
reset_control_assert(ddata->rsts);
err_main_clocks:
if (error)
sysc_disable_main_clocks(ddata);
@@ -2008,6 +2020,10 @@ err_opt_clocks:
sysc_clkdm_allow_idle(ddata);
}
if (error && rstctrl_deasserted &&
!(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT))
reset_control_assert(ddata->rsts);
return error;
}
@@ -2909,6 +2925,9 @@ static int sysc_probe(struct platform_device *pdev)
if (!ddata)
return -ENOMEM;
ddata->offsets[SYSC_REVISION] = -ENODEV;
ddata->offsets[SYSC_SYSCONFIG] = -ENODEV;
ddata->offsets[SYSC_SYSSTATUS] = -ENODEV;
ddata->dev = &pdev->dev;
platform_set_drvdata(pdev, ddata);
@@ -2975,9 +2994,6 @@ static int sysc_probe(struct platform_device *pdev)
}
/* Balance use counts as PM runtime should have enabled these all */
if (!(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT))
reset_control_assert(ddata->rsts);
if (!(ddata->cfg.quirks &
(SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT))) {
sysc_disable_main_clocks(ddata);
@@ -2985,6 +3001,9 @@ static int sysc_probe(struct platform_device *pdev)
sysc_clkdm_allow_idle(ddata);
}
if (!(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT))
reset_control_assert(ddata->rsts);
sysc_show_registers(ddata);
ddata->dev->type = &sysc_device_type;

View File

@@ -19,6 +19,16 @@ config EXYNOS_AUDSS_CLK_CON
on some Exynos SoC variants. Choose M or Y here if you want to
use audio devices such as I2S, PCM, etc.
config EXYNOS_CLKOUT
tristate "Samsung Exynos clock output driver"
depends on COMMON_CLK_SAMSUNG
default y if ARCH_EXYNOS
help
Support for the clock output (XCLKOUT) present on some of Exynos SoC
variants. Usually the XCLKOUT is used to monitor the status of the
certains clocks from SoC, but it could also be tied to other devices
as an input clock.
# For S3C24XX platforms, select following symbols:
config S3C2410_COMMON_CLK
bool "Samsung S3C2410 clock controller support" if COMPILE_TEST

View File

@@ -15,7 +15,7 @@ obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_EXYNOS_CLKOUT) += clk-exynos-clkout.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o
obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o

View File

@@ -9,10 +9,13 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#define EXYNOS_CLKOUT_NR_CLKS 1
#define EXYNOS_CLKOUT_PARENTS 32
@@ -28,41 +31,103 @@ struct exynos_clkout {
struct clk_mux mux;
spinlock_t slock;
void __iomem *reg;
struct device_node *np;
u32 pmu_debug_save;
struct clk_hw_onecell_data data;
};
static struct exynos_clkout *clkout;
struct exynos_clkout_variant {
u32 mux_mask;
};
static int exynos_clkout_suspend(void)
static const struct exynos_clkout_variant exynos_clkout_exynos4 = {
.mux_mask = EXYNOS4_CLKOUT_MUX_MASK,
};
static const struct exynos_clkout_variant exynos_clkout_exynos5 = {
.mux_mask = EXYNOS5_CLKOUT_MUX_MASK,
};
static const struct of_device_id exynos_clkout_ids[] = {
{
.compatible = "samsung,exynos3250-pmu",
.data = &exynos_clkout_exynos4,
}, {
.compatible = "samsung,exynos4210-pmu",
.data = &exynos_clkout_exynos4,
}, {
.compatible = "samsung,exynos4412-pmu",
.data = &exynos_clkout_exynos4,
}, {
.compatible = "samsung,exynos5250-pmu",
.data = &exynos_clkout_exynos5,
}, {
.compatible = "samsung,exynos5410-pmu",
.data = &exynos_clkout_exynos5,
}, {
.compatible = "samsung,exynos5420-pmu",
.data = &exynos_clkout_exynos5,
}, {
.compatible = "samsung,exynos5433-pmu",
.data = &exynos_clkout_exynos5,
}, { }
};
MODULE_DEVICE_TABLE(of, exynos_clkout_ids);
/*
* Device will be instantiated as child of PMU device without its own
* device node. Therefore match compatibles against parent.
*/
static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask)
{
clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG);
const struct exynos_clkout_variant *variant;
const struct of_device_id *match;
if (!dev->parent) {
dev_err(dev, "not instantiated from MFD\n");
return -EINVAL;
}
match = of_match_device(exynos_clkout_ids, dev->parent);
if (!match) {
dev_err(dev, "cannot match parent device\n");
return -EINVAL;
}
variant = match->data;
*mux_mask = variant->mux_mask;
return 0;
}
static void exynos_clkout_resume(void)
{
writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG);
}
static struct syscore_ops exynos_clkout_syscore_ops = {
.suspend = exynos_clkout_suspend,
.resume = exynos_clkout_resume,
};
static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
static int exynos_clkout_probe(struct platform_device *pdev)
{
const char *parent_names[EXYNOS_CLKOUT_PARENTS];
struct clk *parents[EXYNOS_CLKOUT_PARENTS];
int parent_count;
int ret;
int i;
struct exynos_clkout *clkout;
int parent_count, ret, i;
u32 mux_mask;
clkout = kzalloc(struct_size(clkout, data.hws, EXYNOS_CLKOUT_NR_CLKS),
GFP_KERNEL);
clkout = devm_kzalloc(&pdev->dev,
struct_size(clkout, data.hws, EXYNOS_CLKOUT_NR_CLKS),
GFP_KERNEL);
if (!clkout)
return;
return -ENOMEM;
ret = exynos_clkout_match_parent_dev(&pdev->dev, &mux_mask);
if (ret)
return ret;
clkout->np = pdev->dev.of_node;
if (!clkout->np) {
/*
* pdev->dev.parent was checked by exynos_clkout_match_parent_dev()
* so it is not NULL.
*/
clkout->np = pdev->dev.parent->of_node;
}
platform_set_drvdata(pdev, clkout);
spin_lock_init(&clkout->slock);
@@ -71,7 +136,7 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
char name[] = "clkoutXX";
snprintf(name, sizeof(name), "clkout%d", i);
parents[i] = of_clk_get_by_name(node, name);
parents[i] = of_clk_get_by_name(clkout->np, name);
if (IS_ERR(parents[i])) {
parent_names[i] = "none";
continue;
@@ -82,11 +147,13 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
}
if (!parent_count)
goto free_clkout;
return -EINVAL;
clkout->reg = of_iomap(node, 0);
if (!clkout->reg)
clkout->reg = of_iomap(clkout->np, 0);
if (!clkout->reg) {
ret = -ENODEV;
goto clks_put;
}
clkout->gate.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG;
clkout->gate.bit_idx = EXYNOS_CLKOUT_DISABLE_SHIFT;
@@ -103,17 +170,17 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
&clk_mux_ops, NULL, NULL, &clkout->gate.hw,
&clk_gate_ops, CLK_SET_RATE_PARENT
| CLK_SET_RATE_NO_REPARENT);
if (IS_ERR(clkout->data.hws[0]))
if (IS_ERR(clkout->data.hws[0])) {
ret = PTR_ERR(clkout->data.hws[0]);
goto err_unmap;
}
clkout->data.num = EXYNOS_CLKOUT_NR_CLKS;
ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, &clkout->data);
ret = of_clk_add_hw_provider(clkout->np, of_clk_hw_onecell_get, &clkout->data);
if (ret)
goto err_clk_unreg;
register_syscore_ops(&exynos_clkout_syscore_ops);
return;
return 0;
err_clk_unreg:
clk_hw_unregister(clkout->data.hws[0]);
@@ -123,38 +190,56 @@ clks_put:
for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i)
if (!IS_ERR(parents[i]))
clk_put(parents[i]);
free_clkout:
kfree(clkout);
pr_err("%s: failed to register clkout clock\n", __func__);
dev_err(&pdev->dev, "failed to register clkout clock\n");
return ret;
}
/*
* We use CLK_OF_DECLARE_DRIVER initialization method to avoid setting
* the OF_POPULATED flag on the pmu device tree node, so later the
* Exynos PMU platform device can be properly probed with PMU driver.
*/
static void __init exynos4_clkout_init(struct device_node *node)
static int exynos_clkout_remove(struct platform_device *pdev)
{
exynos_clkout_init(node, EXYNOS4_CLKOUT_MUX_MASK);
}
CLK_OF_DECLARE_DRIVER(exynos4210_clkout, "samsung,exynos4210-pmu",
exynos4_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos4412_clkout, "samsung,exynos4412-pmu",
exynos4_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos3250_clkout, "samsung,exynos3250-pmu",
exynos4_clkout_init);
struct exynos_clkout *clkout = platform_get_drvdata(pdev);
static void __init exynos5_clkout_init(struct device_node *node)
{
exynos_clkout_init(node, EXYNOS5_CLKOUT_MUX_MASK);
of_clk_del_provider(clkout->np);
clk_hw_unregister(clkout->data.hws[0]);
iounmap(clkout->reg);
return 0;
}
CLK_OF_DECLARE_DRIVER(exynos5250_clkout, "samsung,exynos5250-pmu",
exynos5_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos5410_clkout, "samsung,exynos5410-pmu",
exynos5_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos5420_clkout, "samsung,exynos5420-pmu",
exynos5_clkout_init);
CLK_OF_DECLARE_DRIVER(exynos5433_clkout, "samsung,exynos5433-pmu",
exynos5_clkout_init);
static int __maybe_unused exynos_clkout_suspend(struct device *dev)
{
struct exynos_clkout *clkout = dev_get_drvdata(dev);
clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG);
return 0;
}
static int __maybe_unused exynos_clkout_resume(struct device *dev)
{
struct exynos_clkout *clkout = dev_get_drvdata(dev);
writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG);
return 0;
}
static SIMPLE_DEV_PM_OPS(exynos_clkout_pm_ops, exynos_clkout_suspend,
exynos_clkout_resume);
static struct platform_driver exynos_clkout_driver = {
.driver = {
.name = "exynos-clkout",
.of_match_table = exynos_clkout_ids,
.pm = &exynos_clkout_pm_ops,
},
.probe = exynos_clkout_probe,
.remove = exynos_clkout_remove,
};
module_platform_driver(exynos_clkout_driver);
MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
MODULE_AUTHOR("Tomasz Figa <tomasz.figa@gmail.com>");
MODULE_DESCRIPTION("Samsung Exynos clock output driver");
MODULE_LICENSE("GPL");

View File

@@ -266,6 +266,8 @@ static const char *enable_init_clks[] = {
"dpll_ddr_m2_ck",
"dpll_mpu_m2_ck",
"l3_gclk",
/* AM3_L3_L3_MAIN_CLKCTRL, needed during suspend */
"l3-clkctrl:00bc:0",
"l4hs_gclk",
"l4fw_gclk",
"l4ls_gclk",

View File

@@ -272,6 +272,11 @@ static struct ti_dt_clk am43xx_clks[] = {
{ .node_name = NULL },
};
static const char *enable_init_clks[] = {
/* AM4_L3_L3_MAIN_CLKCTRL, needed during suspend */
"l3-clkctrl:0000:0",
};
int __init am43xx_dt_clk_init(void)
{
struct clk *clk1, *clk2;
@@ -283,6 +288,9 @@ int __init am43xx_dt_clk_init(void)
omap2_clk_disable_autoidle_all();
omap2_clk_enable_init_clocks(enable_init_clks,
ARRAY_SIZE(enable_init_clks));
ti_clk_add_aliases();
/*

View File

@@ -255,7 +255,7 @@ static const struct omap_clkctrl_reg_data omap4_l3_instr_clkctrl_regs[] __initco
};
static const struct omap_clkctrl_reg_data omap4_ivahd_clkctrl_regs[] __initconst = {
{ OMAP4_IVA_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_m5x2_ck" },
{ OMAP4_IVA_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_iva_m5x2_ck" },
{ OMAP4_SL2IF_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_m5x2_ck" },
{ 0 },
};

View File

@@ -252,6 +252,12 @@ static const struct omap_clkctrl_reg_data dra7_l3instr_clkctrl_regs[] __initcons
{ 0 },
};
static const struct omap_clkctrl_reg_data dra7_iva_clkctrl_regs[] __initconst = {
{ DRA7_IVA_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_iva_h12x2_ck" },
{ DRA7_SL2IF_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_h12x2_ck" },
{ 0 },
};
static const char * const dra7_dss_dss_clk_parents[] __initconst = {
"dpll_per_h12x2_ck",
NULL,
@@ -827,6 +833,7 @@ const struct omap_clkctrl_data dra7_clkctrl_data[] __initconst = {
{ 0x4a008c00, dra7_atl_clkctrl_regs },
{ 0x4a008d20, dra7_l4cfg_clkctrl_regs },
{ 0x4a008e20, dra7_l3instr_clkctrl_regs },
{ 0x4a008f20, dra7_iva_clkctrl_regs },
{ 0x4a009020, dra7_cam_clkctrl_regs },
{ 0x4a009120, dra7_dss_clkctrl_regs },
{ 0x4a009220, dra7_gpu_clkctrl_regs },

View File

@@ -155,8 +155,7 @@ static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
static const struct of_device_id compatible_machine_match[] = {
{ .compatible = "arm,vexpress,v2p-ca15_a7" },
{ .compatible = "samsung,exynos5420" },
{ .compatible = "samsung,exynos5800" },
{ .compatible = "google,peach" },
{},
};

View File

@@ -1474,17 +1474,17 @@ int scmi_notification_init(struct scmi_handle *handle)
ni->gid = gid;
ni->handle = handle;
ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTO,
sizeof(char *), GFP_KERNEL);
if (!ni->registered_protocols)
goto err;
ni->notify_wq = alloc_workqueue(dev_name(handle->dev),
WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS,
0);
if (!ni->notify_wq)
goto err;
ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTO,
sizeof(char *), GFP_KERNEL);
if (!ni->registered_protocols)
goto err;
mutex_init(&ni->pending_mtx);
hash_init(ni->pending_events_handlers);

View File

@@ -2,21 +2,30 @@
/*
* System Control and Management Interface (SCMI) Sensor Protocol
*
* Copyright (C) 2018 ARM Ltd.
* Copyright (C) 2018-2020 ARM Ltd.
*/
#define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt
#include <linux/bitfield.h>
#include <linux/scmi_protocol.h>
#include "common.h"
#include "notify.h"
#define SCMI_MAX_NUM_SENSOR_AXIS 63
#define SCMIv2_SENSOR_PROTOCOL 0x10000
enum scmi_sensor_protocol_cmd {
SENSOR_DESCRIPTION_GET = 0x3,
SENSOR_TRIP_POINT_NOTIFY = 0x4,
SENSOR_TRIP_POINT_CONFIG = 0x5,
SENSOR_READING_GET = 0x6,
SENSOR_AXIS_DESCRIPTION_GET = 0x7,
SENSOR_LIST_UPDATE_INTERVALS = 0x8,
SENSOR_CONFIG_GET = 0x9,
SENSOR_CONFIG_SET = 0xA,
SENSOR_CONTINUOUS_UPDATE_NOTIFY = 0xB,
};
struct scmi_msg_resp_sensor_attributes {
@@ -28,29 +37,106 @@ struct scmi_msg_resp_sensor_attributes {
__le32 reg_size;
};
/* v3 attributes_low macros */
#define SUPPORTS_UPDATE_NOTIFY(x) FIELD_GET(BIT(30), (x))
#define SENSOR_TSTAMP_EXP(x) FIELD_GET(GENMASK(14, 10), (x))
#define SUPPORTS_TIMESTAMP(x) FIELD_GET(BIT(9), (x))
#define SUPPORTS_EXTEND_ATTRS(x) FIELD_GET(BIT(8), (x))
/* v2 attributes_high macros */
#define SENSOR_UPDATE_BASE(x) FIELD_GET(GENMASK(31, 27), (x))
#define SENSOR_UPDATE_SCALE(x) FIELD_GET(GENMASK(26, 22), (x))
/* v3 attributes_high macros */
#define SENSOR_AXIS_NUMBER(x) FIELD_GET(GENMASK(21, 16), (x))
#define SUPPORTS_AXIS(x) FIELD_GET(BIT(8), (x))
/* v3 resolution macros */
#define SENSOR_RES(x) FIELD_GET(GENMASK(26, 0), (x))
#define SENSOR_RES_EXP(x) FIELD_GET(GENMASK(31, 27), (x))
struct scmi_msg_resp_attrs {
__le32 min_range_low;
__le32 min_range_high;
__le32 max_range_low;
__le32 max_range_high;
};
struct scmi_msg_resp_sensor_description {
__le16 num_returned;
__le16 num_remaining;
struct {
struct scmi_sensor_descriptor {
__le32 id;
__le32 attributes_low;
#define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31))
#define NUM_TRIP_POINTS(x) ((x) & 0xff)
/* Common attributes_low macros */
#define SUPPORTS_ASYNC_READ(x) FIELD_GET(BIT(31), (x))
#define NUM_TRIP_POINTS(x) FIELD_GET(GENMASK(7, 0), (x))
__le32 attributes_high;
#define SENSOR_TYPE(x) ((x) & 0xff)
#define SENSOR_SCALE(x) (((x) >> 11) & 0x1f)
#define SENSOR_SCALE_SIGN BIT(4)
#define SENSOR_SCALE_EXTEND GENMASK(7, 5)
#define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f)
#define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f)
u8 name[SCMI_MAX_STR_SIZE];
} desc[0];
/* Common attributes_high macros */
#define SENSOR_SCALE(x) FIELD_GET(GENMASK(15, 11), (x))
#define SENSOR_SCALE_SIGN BIT(4)
#define SENSOR_SCALE_EXTEND GENMASK(31, 5)
#define SENSOR_TYPE(x) FIELD_GET(GENMASK(7, 0), (x))
u8 name[SCMI_MAX_STR_SIZE];
/* only for version > 2.0 */
__le32 power;
__le32 resolution;
struct scmi_msg_resp_attrs scalar_attrs;
} desc[];
};
struct scmi_msg_sensor_trip_point_notify {
/* Base scmi_sensor_descriptor size excluding extended attrs after name */
#define SCMI_MSG_RESP_SENS_DESCR_BASE_SZ 28
/* Sign extend to a full s32 */
#define S32_EXT(v) \
({ \
int __v = (v); \
\
if (__v & SENSOR_SCALE_SIGN) \
__v |= SENSOR_SCALE_EXTEND; \
__v; \
})
struct scmi_msg_sensor_axis_description_get {
__le32 id;
__le32 axis_desc_index;
};
struct scmi_msg_resp_sensor_axis_description {
__le32 num_axis_flags;
#define NUM_AXIS_RETURNED(x) FIELD_GET(GENMASK(5, 0), (x))
#define NUM_AXIS_REMAINING(x) FIELD_GET(GENMASK(31, 26), (x))
struct scmi_axis_descriptor {
__le32 id;
__le32 attributes_low;
__le32 attributes_high;
u8 name[SCMI_MAX_STR_SIZE];
__le32 resolution;
struct scmi_msg_resp_attrs attrs;
} desc[];
};
/* Base scmi_axis_descriptor size excluding extended attrs after name */
#define SCMI_MSG_RESP_AXIS_DESCR_BASE_SZ 28
struct scmi_msg_sensor_list_update_intervals {
__le32 id;
__le32 index;
};
struct scmi_msg_resp_sensor_list_update_intervals {
__le32 num_intervals_flags;
#define NUM_INTERVALS_RETURNED(x) FIELD_GET(GENMASK(11, 0), (x))
#define SEGMENTED_INTVL_FORMAT(x) FIELD_GET(BIT(12), (x))
#define NUM_INTERVALS_REMAINING(x) FIELD_GET(GENMASK(31, 16), (x))
__le32 intervals[];
};
struct scmi_msg_sensor_request_notify {
__le32 id;
__le32 event_control;
#define SENSOR_TP_NOTIFY_ALL BIT(0)
#define SENSOR_NOTIFY_ALL BIT(0)
};
struct scmi_msg_set_sensor_trip_point {
@@ -66,18 +152,46 @@ struct scmi_msg_set_sensor_trip_point {
__le32 value_high;
};
struct scmi_msg_sensor_config_set {
__le32 id;
__le32 sensor_config;
};
struct scmi_msg_sensor_reading_get {
__le32 id;
__le32 flags;
#define SENSOR_READ_ASYNC BIT(0)
};
struct scmi_resp_sensor_reading_complete {
__le32 id;
__le64 readings;
};
struct scmi_sensor_reading_resp {
__le32 sensor_value_low;
__le32 sensor_value_high;
__le32 timestamp_low;
__le32 timestamp_high;
};
struct scmi_resp_sensor_reading_complete_v3 {
__le32 id;
struct scmi_sensor_reading_resp readings[];
};
struct scmi_sensor_trip_notify_payld {
__le32 agent_id;
__le32 sensor_id;
__le32 trip_point_desc;
};
struct scmi_sensor_update_notify_payld {
__le32 agent_id;
__le32 sensor_id;
struct scmi_sensor_reading_resp readings[];
};
struct sensors_info {
u32 version;
int num_sensors;
@@ -114,6 +228,194 @@ static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
return ret;
}
static inline void scmi_parse_range_attrs(struct scmi_range_attrs *out,
struct scmi_msg_resp_attrs *in)
{
out->min_range = get_unaligned_le64((void *)&in->min_range_low);
out->max_range = get_unaligned_le64((void *)&in->max_range_low);
}
static int scmi_sensor_update_intervals(const struct scmi_handle *handle,
struct scmi_sensor_info *s)
{
int ret, cnt;
u32 desc_index = 0;
u16 num_returned, num_remaining;
struct scmi_xfer *ti;
struct scmi_msg_resp_sensor_list_update_intervals *buf;
struct scmi_msg_sensor_list_update_intervals *msg;
ret = scmi_xfer_get_init(handle, SENSOR_LIST_UPDATE_INTERVALS,
SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &ti);
if (ret)
return ret;
buf = ti->rx.buf;
do {
u32 flags;
msg = ti->tx.buf;
/* Set the number of sensors to be skipped/already read */
msg->id = cpu_to_le32(s->id);
msg->index = cpu_to_le32(desc_index);
ret = scmi_do_xfer(handle, ti);
if (ret)
break;
flags = le32_to_cpu(buf->num_intervals_flags);
num_returned = NUM_INTERVALS_RETURNED(flags);
num_remaining = NUM_INTERVALS_REMAINING(flags);
/*
* Max intervals is not declared previously anywhere so we
* assume it's returned+remaining.
*/
if (!s->intervals.count) {
s->intervals.segmented = SEGMENTED_INTVL_FORMAT(flags);
s->intervals.count = num_returned + num_remaining;
/* segmented intervals are reported in one triplet */
if (s->intervals.segmented &&
(num_remaining || num_returned != 3)) {
dev_err(handle->dev,
"Sensor ID:%d advertises an invalid segmented interval (%d)\n",
s->id, s->intervals.count);
s->intervals.segmented = false;
s->intervals.count = 0;
ret = -EINVAL;
break;
}
/* Direct allocation when exceeding pre-allocated */
if (s->intervals.count >= SCMI_MAX_PREALLOC_POOL) {
s->intervals.desc =
devm_kcalloc(handle->dev,
s->intervals.count,
sizeof(*s->intervals.desc),
GFP_KERNEL);
if (!s->intervals.desc) {
s->intervals.segmented = false;
s->intervals.count = 0;
ret = -ENOMEM;
break;
}
}
} else if (desc_index + num_returned > s->intervals.count) {
dev_err(handle->dev,
"No. of update intervals can't exceed %d\n",
s->intervals.count);
ret = -EINVAL;
break;
}
for (cnt = 0; cnt < num_returned; cnt++)
s->intervals.desc[desc_index + cnt] =
le32_to_cpu(buf->intervals[cnt]);
desc_index += num_returned;
scmi_reset_rx_to_maxsz(handle, ti);
/*
* check for both returned and remaining to avoid infinite
* loop due to buggy firmware
*/
} while (num_returned && num_remaining);
scmi_xfer_put(handle, ti);
return ret;
}
static int scmi_sensor_axis_description(const struct scmi_handle *handle,
struct scmi_sensor_info *s)
{
int ret, cnt;
u32 desc_index = 0;
u16 num_returned, num_remaining;
struct scmi_xfer *te;
struct scmi_msg_resp_sensor_axis_description *buf;
struct scmi_msg_sensor_axis_description_get *msg;
s->axis = devm_kcalloc(handle->dev, s->num_axis,
sizeof(*s->axis), GFP_KERNEL);
if (!s->axis)
return -ENOMEM;
ret = scmi_xfer_get_init(handle, SENSOR_AXIS_DESCRIPTION_GET,
SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &te);
if (ret)
return ret;
buf = te->rx.buf;
do {
u32 flags;
struct scmi_axis_descriptor *adesc;
msg = te->tx.buf;
/* Set the number of sensors to be skipped/already read */
msg->id = cpu_to_le32(s->id);
msg->axis_desc_index = cpu_to_le32(desc_index);
ret = scmi_do_xfer(handle, te);
if (ret)
break;
flags = le32_to_cpu(buf->num_axis_flags);
num_returned = NUM_AXIS_RETURNED(flags);
num_remaining = NUM_AXIS_REMAINING(flags);
if (desc_index + num_returned > s->num_axis) {
dev_err(handle->dev, "No. of axis can't exceed %d\n",
s->num_axis);
break;
}
adesc = &buf->desc[0];
for (cnt = 0; cnt < num_returned; cnt++) {
u32 attrh, attrl;
struct scmi_sensor_axis_info *a;
size_t dsize = SCMI_MSG_RESP_AXIS_DESCR_BASE_SZ;
attrl = le32_to_cpu(adesc->attributes_low);
a = &s->axis[desc_index + cnt];
a->id = le32_to_cpu(adesc->id);
a->extended_attrs = SUPPORTS_EXTEND_ATTRS(attrl);
attrh = le32_to_cpu(adesc->attributes_high);
a->scale = S32_EXT(SENSOR_SCALE(attrh));
a->type = SENSOR_TYPE(attrh);
strlcpy(a->name, adesc->name, SCMI_MAX_STR_SIZE);
if (a->extended_attrs) {
unsigned int ares =
le32_to_cpu(adesc->resolution);
a->resolution = SENSOR_RES(ares);
a->exponent =
S32_EXT(SENSOR_RES_EXP(ares));
dsize += sizeof(adesc->resolution);
scmi_parse_range_attrs(&a->attrs,
&adesc->attrs);
dsize += sizeof(adesc->attrs);
}
adesc = (typeof(adesc))((u8 *)adesc + dsize);
}
desc_index += num_returned;
scmi_reset_rx_to_maxsz(handle, te);
/*
* check for both returned and remaining to avoid infinite
* loop due to buggy firmware
*/
} while (num_returned && num_remaining);
scmi_xfer_put(handle, te);
return ret;
}
static int scmi_sensor_description_get(const struct scmi_handle *handle,
struct sensors_info *si)
{
@@ -131,9 +433,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
buf = t->rx.buf;
do {
struct scmi_sensor_descriptor *sdesc;
/* Set the number of sensors to be skipped/already read */
put_unaligned_le32(desc_index, t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (ret)
break;
@@ -147,22 +450,97 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
break;
}
sdesc = &buf->desc[0];
for (cnt = 0; cnt < num_returned; cnt++) {
u32 attrh, attrl;
struct scmi_sensor_info *s;
size_t dsize = SCMI_MSG_RESP_SENS_DESCR_BASE_SZ;
attrl = le32_to_cpu(buf->desc[cnt].attributes_low);
attrh = le32_to_cpu(buf->desc[cnt].attributes_high);
s = &si->sensors[desc_index + cnt];
s->id = le32_to_cpu(buf->desc[cnt].id);
s->type = SENSOR_TYPE(attrh);
s->scale = SENSOR_SCALE(attrh);
/* Sign extend to a full s8 */
if (s->scale & SENSOR_SCALE_SIGN)
s->scale |= SENSOR_SCALE_EXTEND;
s->id = le32_to_cpu(sdesc->id);
attrl = le32_to_cpu(sdesc->attributes_low);
/* common bitfields parsing */
s->async = SUPPORTS_ASYNC_READ(attrl);
s->num_trip_points = NUM_TRIP_POINTS(attrl);
strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE);
/**
* only SCMIv3.0 specific bitfield below.
* Such bitfields are assumed to be zeroed on non
* relevant fw versions...assuming fw not buggy !
*/
s->update = SUPPORTS_UPDATE_NOTIFY(attrl);
s->timestamped = SUPPORTS_TIMESTAMP(attrl);
if (s->timestamped)
s->tstamp_scale =
S32_EXT(SENSOR_TSTAMP_EXP(attrl));
s->extended_scalar_attrs =
SUPPORTS_EXTEND_ATTRS(attrl);
attrh = le32_to_cpu(sdesc->attributes_high);
/* common bitfields parsing */
s->scale = S32_EXT(SENSOR_SCALE(attrh));
s->type = SENSOR_TYPE(attrh);
/* Use pre-allocated pool wherever possible */
s->intervals.desc = s->intervals.prealloc_pool;
if (si->version == SCMIv2_SENSOR_PROTOCOL) {
s->intervals.segmented = false;
s->intervals.count = 1;
/*
* Convert SCMIv2.0 update interval format to
* SCMIv3.0 to be used as the common exposed
* descriptor, accessible via common macros.
*/
s->intervals.desc[0] =
(SENSOR_UPDATE_BASE(attrh) << 5) |
SENSOR_UPDATE_SCALE(attrh);
} else {
/*
* From SCMIv3.0 update intervals are retrieved
* via a dedicated (optional) command.
* Since the command is optional, on error carry
* on without any update interval.
*/
if (scmi_sensor_update_intervals(handle, s))
dev_dbg(handle->dev,
"Update Intervals not available for sensor ID:%d\n",
s->id);
}
/**
* only > SCMIv2.0 specific bitfield below.
* Such bitfields are assumed to be zeroed on non
* relevant fw versions...assuming fw not buggy !
*/
s->num_axis = min_t(unsigned int,
SUPPORTS_AXIS(attrh) ?
SENSOR_AXIS_NUMBER(attrh) : 0,
SCMI_MAX_NUM_SENSOR_AXIS);
strlcpy(s->name, sdesc->name, SCMI_MAX_STR_SIZE);
if (s->extended_scalar_attrs) {
s->sensor_power = le32_to_cpu(sdesc->power);
dsize += sizeof(sdesc->power);
/* Only for sensors reporting scalar values */
if (s->num_axis == 0) {
unsigned int sres =
le32_to_cpu(sdesc->resolution);
s->resolution = SENSOR_RES(sres);
s->exponent =
S32_EXT(SENSOR_RES_EXP(sres));
dsize += sizeof(sdesc->resolution);
scmi_parse_range_attrs(&s->scalar_attrs,
&sdesc->scalar_attrs);
dsize += sizeof(sdesc->scalar_attrs);
}
}
if (s->num_axis > 0) {
ret = scmi_sensor_axis_description(handle, s);
if (ret)
goto out;
}
sdesc = (typeof(sdesc))((u8 *)sdesc + dsize);
}
desc_index += num_returned;
@@ -174,19 +552,21 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
*/
} while (num_returned && num_remaining);
out:
scmi_xfer_put(handle, t);
return ret;
}
static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle,
u32 sensor_id, bool enable)
static inline int
scmi_sensor_request_notify(const struct scmi_handle *handle, u32 sensor_id,
u8 message_id, bool enable)
{
int ret;
u32 evt_cntl = enable ? SENSOR_TP_NOTIFY_ALL : 0;
u32 evt_cntl = enable ? SENSOR_NOTIFY_ALL : 0;
struct scmi_xfer *t;
struct scmi_msg_sensor_trip_point_notify *cfg;
struct scmi_msg_sensor_request_notify *cfg;
ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_NOTIFY,
ret = scmi_xfer_get_init(handle, message_id,
SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
if (ret)
return ret;
@@ -201,6 +581,23 @@ static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle,
return ret;
}
static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle,
u32 sensor_id, bool enable)
{
return scmi_sensor_request_notify(handle, sensor_id,
SENSOR_TRIP_POINT_NOTIFY,
enable);
}
static int
scmi_sensor_continuous_update_notify(const struct scmi_handle *handle,
u32 sensor_id, bool enable)
{
return scmi_sensor_request_notify(handle, sensor_id,
SENSOR_CONTINUOUS_UPDATE_NOTIFY,
enable);
}
static int
scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id,
u8 trip_id, u64 trip_value)
@@ -227,6 +624,75 @@ scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id,
return ret;
}
static int scmi_sensor_config_get(const struct scmi_handle *handle,
u32 sensor_id, u32 *sensor_config)
{
int ret;
struct scmi_xfer *t;
ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_GET,
SCMI_PROTOCOL_SENSOR, sizeof(__le32),
sizeof(__le32), &t);
if (ret)
return ret;
put_unaligned_le32(cpu_to_le32(sensor_id), t->tx.buf);
ret = scmi_do_xfer(handle, t);
if (!ret) {
struct sensors_info *si = handle->sensor_priv;
struct scmi_sensor_info *s = si->sensors + sensor_id;
*sensor_config = get_unaligned_le64(t->rx.buf);
s->sensor_config = *sensor_config;
}
scmi_xfer_put(handle, t);
return ret;
}
static int scmi_sensor_config_set(const struct scmi_handle *handle,
u32 sensor_id, u32 sensor_config)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_config_set *msg;
ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
SCMI_PROTOCOL_SENSOR, sizeof(*msg), 0, &t);
if (ret)
return ret;
msg = t->tx.buf;
msg->id = cpu_to_le32(sensor_id);
msg->sensor_config = cpu_to_le32(sensor_config);
ret = scmi_do_xfer(handle, t);
if (!ret) {
struct sensors_info *si = handle->sensor_priv;
struct scmi_sensor_info *s = si->sensors + sensor_id;
s->sensor_config = sensor_config;
}
scmi_xfer_put(handle, t);
return ret;
}
/**
* scmi_sensor_reading_get - Read scalar sensor value
* @handle: Platform handle
* @sensor_id: Sensor ID
* @value: The 64bit value sensor reading
*
* This function returns a single 64 bit reading value representing the sensor
* value; if the platform SCMI Protocol implementation and the sensor support
* multiple axis and timestamped-reads, this just returns the first axis while
* dropping the timestamp value.
* Use instead the @scmi_sensor_reading_get_timestamped to retrieve the array of
* timestamped multi-axis values.
*
* Return: 0 on Success
*/
static int scmi_sensor_reading_get(const struct scmi_handle *handle,
u32 sensor_id, u64 *value)
{
@@ -237,20 +703,24 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
struct scmi_sensor_info *s = si->sensors + sensor_id;
ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
sizeof(u64), &t);
SCMI_PROTOCOL_SENSOR, sizeof(*sensor), 0, &t);
if (ret)
return ret;
sensor = t->tx.buf;
sensor->id = cpu_to_le32(sensor_id);
if (s->async) {
sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
ret = scmi_do_xfer_with_response(handle, t);
if (!ret)
*value = get_unaligned_le64((void *)
((__le32 *)t->rx.buf + 1));
if (!ret) {
struct scmi_resp_sensor_reading_complete *resp;
resp = t->rx.buf;
if (le32_to_cpu(resp->id) == sensor_id)
*value = get_unaligned_le64(&resp->readings);
else
ret = -EPROTO;
}
} else {
sensor->flags = cpu_to_le32(0);
ret = scmi_do_xfer(handle, t);
@@ -262,6 +732,84 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
return ret;
}
static inline void
scmi_parse_sensor_readings(struct scmi_sensor_reading *out,
const struct scmi_sensor_reading_resp *in)
{
out->value = get_unaligned_le64((void *)&in->sensor_value_low);
out->timestamp = get_unaligned_le64((void *)&in->timestamp_low);
}
/**
* scmi_sensor_reading_get_timestamped - Read multiple-axis timestamped values
* @handle: Platform handle
* @sensor_id: Sensor ID
* @count: The length of the provided @readings array
* @readings: An array of elements each representing a timestamped per-axis
* reading of type @struct scmi_sensor_reading.
* Returned readings are ordered as the @axis descriptors array
* included in @struct scmi_sensor_info and the max number of
* returned elements is min(@count, @num_axis); ideally the provided
* array should be of length @count equal to @num_axis.
*
* Return: 0 on Success
*/
static int
scmi_sensor_reading_get_timestamped(const struct scmi_handle *handle,
u32 sensor_id, u8 count,
struct scmi_sensor_reading *readings)
{
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
struct sensors_info *si = handle->sensor_priv;
struct scmi_sensor_info *s = si->sensors + sensor_id;
if (!count || !readings ||
(!s->num_axis && count > 1) || (s->num_axis && count > s->num_axis))
return -EINVAL;
ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
SCMI_PROTOCOL_SENSOR, sizeof(*sensor), 0, &t);
if (ret)
return ret;
sensor = t->tx.buf;
sensor->id = cpu_to_le32(sensor_id);
if (s->async) {
sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
ret = scmi_do_xfer_with_response(handle, t);
if (!ret) {
int i;
struct scmi_resp_sensor_reading_complete_v3 *resp;
resp = t->rx.buf;
/* Retrieve only the number of requested axis anyway */
if (le32_to_cpu(resp->id) == sensor_id)
for (i = 0; i < count; i++)
scmi_parse_sensor_readings(&readings[i],
&resp->readings[i]);
else
ret = -EPROTO;
}
} else {
sensor->flags = cpu_to_le32(0);
ret = scmi_do_xfer(handle, t);
if (!ret) {
int i;
struct scmi_sensor_reading_resp *resp_readings;
resp_readings = t->rx.buf;
for (i = 0; i < count; i++)
scmi_parse_sensor_readings(&readings[i],
&resp_readings[i]);
}
}
scmi_xfer_put(handle, t);
return ret;
}
static const struct scmi_sensor_info *
scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id)
{
@@ -282,6 +830,9 @@ static const struct scmi_sensor_ops sensor_ops = {
.info_get = scmi_sensor_info_get,
.trip_point_config = scmi_sensor_trip_point_config,
.reading_get = scmi_sensor_reading_get,
.reading_get_timestamped = scmi_sensor_reading_get_timestamped,
.config_get = scmi_sensor_config_get,
.config_set = scmi_sensor_config_set,
};
static int scmi_sensor_set_notify_enabled(const struct scmi_handle *handle,
@@ -289,7 +840,19 @@ static int scmi_sensor_set_notify_enabled(const struct scmi_handle *handle,
{
int ret;
ret = scmi_sensor_trip_point_notify(handle, src_id, enable);
switch (evt_id) {
case SCMI_EVENT_SENSOR_TRIP_POINT_EVENT:
ret = scmi_sensor_trip_point_notify(handle, src_id, enable);
break;
case SCMI_EVENT_SENSOR_UPDATE:
ret = scmi_sensor_continuous_update_notify(handle, src_id,
enable);
break;
default:
ret = -EINVAL;
break;
}
if (ret)
pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
evt_id, src_id, ret);
@@ -302,20 +865,59 @@ static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle,
const void *payld, size_t payld_sz,
void *report, u32 *src_id)
{
const struct scmi_sensor_trip_notify_payld *p = payld;
struct scmi_sensor_trip_point_report *r = report;
void *rep = NULL;
if (evt_id != SCMI_EVENT_SENSOR_TRIP_POINT_EVENT ||
sizeof(*p) != payld_sz)
return NULL;
switch (evt_id) {
case SCMI_EVENT_SENSOR_TRIP_POINT_EVENT:
{
const struct scmi_sensor_trip_notify_payld *p = payld;
struct scmi_sensor_trip_point_report *r = report;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
r->sensor_id = le32_to_cpu(p->sensor_id);
r->trip_point_desc = le32_to_cpu(p->trip_point_desc);
*src_id = r->sensor_id;
if (sizeof(*p) != payld_sz)
break;
return r;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
r->sensor_id = le32_to_cpu(p->sensor_id);
r->trip_point_desc = le32_to_cpu(p->trip_point_desc);
*src_id = r->sensor_id;
rep = r;
break;
}
case SCMI_EVENT_SENSOR_UPDATE:
{
int i;
struct scmi_sensor_info *s;
const struct scmi_sensor_update_notify_payld *p = payld;
struct scmi_sensor_update_report *r = report;
struct sensors_info *sinfo = handle->sensor_priv;
/* payld_sz is variable for this event */
r->sensor_id = le32_to_cpu(p->sensor_id);
if (r->sensor_id >= sinfo->num_sensors)
break;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
s = &sinfo->sensors[r->sensor_id];
/*
* The generated report r (@struct scmi_sensor_update_report)
* was pre-allocated to contain up to SCMI_MAX_NUM_SENSOR_AXIS
* readings: here it is filled with the effective @num_axis
* readings defined for this sensor or 1 for scalar sensors.
*/
r->readings_count = s->num_axis ?: 1;
for (i = 0; i < r->readings_count; i++)
scmi_parse_sensor_readings(&r->readings[i],
&p->readings[i]);
*src_id = r->sensor_id;
rep = r;
break;
}
default:
break;
}
return rep;
}
static const struct scmi_event sensor_events[] = {
@@ -324,6 +926,16 @@ static const struct scmi_event sensor_events[] = {
.max_payld_sz = sizeof(struct scmi_sensor_trip_notify_payld),
.max_report_sz = sizeof(struct scmi_sensor_trip_point_report),
},
{
.id = SCMI_EVENT_SENSOR_UPDATE,
.max_payld_sz =
sizeof(struct scmi_sensor_update_notify_payld) +
SCMI_MAX_NUM_SENSOR_AXIS *
sizeof(struct scmi_sensor_reading_resp),
.max_report_sz = sizeof(struct scmi_sensor_update_report) +
SCMI_MAX_NUM_SENSOR_AXIS *
sizeof(struct scmi_sensor_reading),
},
};
static const struct scmi_event_ops sensor_event_ops = {
@@ -334,6 +946,7 @@ static const struct scmi_event_ops sensor_event_ops = {
static int scmi_sensors_protocol_init(struct scmi_handle *handle)
{
u32 version;
int ret;
struct sensors_info *sinfo;
scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version);
@@ -344,15 +957,19 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle)
sinfo = devm_kzalloc(handle->dev, sizeof(*sinfo), GFP_KERNEL);
if (!sinfo)
return -ENOMEM;
sinfo->version = version;
scmi_sensor_attributes_get(handle, sinfo);
ret = scmi_sensor_attributes_get(handle, sinfo);
if (ret)
return ret;
sinfo->sensors = devm_kcalloc(handle->dev, sinfo->num_sensors,
sizeof(*sinfo->sensors), GFP_KERNEL);
if (!sinfo->sensors)
return -ENOMEM;
scmi_sensor_description_get(handle, sinfo);
ret = scmi_sensor_description_get(handle, sinfo);
if (ret)
return ret;
scmi_register_protocol_events(handle,
SCMI_PROTOCOL_SENSOR, SCMI_PROTO_QUEUE_SZ,
@@ -360,9 +977,8 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle)
ARRAY_SIZE(sensor_events),
sinfo->num_sensors);
sinfo->version = version;
handle->sensor_ops = &sensor_ops;
handle->sensor_priv = sinfo;
handle->sensor_ops = &sensor_ops;
return 0;
}

View File

@@ -60,22 +60,40 @@ static void imx_dsp_handle_rx(struct mbox_client *c, void *msg)
}
}
static int imx_dsp_probe(struct platform_device *pdev)
struct mbox_chan *imx_dsp_request_channel(struct imx_dsp_ipc *dsp_ipc, int idx)
{
struct device *dev = &pdev->dev;
struct imx_dsp_ipc *dsp_ipc;
struct imx_dsp_chan *dsp_chan;
if (idx >= DSP_MU_CHAN_NUM)
return ERR_PTR(-EINVAL);
dsp_chan = &dsp_ipc->chans[idx];
dsp_chan->ch = mbox_request_channel_byname(&dsp_chan->cl, dsp_chan->name);
return dsp_chan->ch;
}
EXPORT_SYMBOL(imx_dsp_request_channel);
void imx_dsp_free_channel(struct imx_dsp_ipc *dsp_ipc, int idx)
{
struct imx_dsp_chan *dsp_chan;
if (idx >= DSP_MU_CHAN_NUM)
return;
dsp_chan = &dsp_ipc->chans[idx];
mbox_free_channel(dsp_chan->ch);
}
EXPORT_SYMBOL(imx_dsp_free_channel);
static int imx_dsp_setup_channels(struct imx_dsp_ipc *dsp_ipc)
{
struct device *dev = dsp_ipc->dev;
struct imx_dsp_chan *dsp_chan;
struct mbox_client *cl;
char *chan_name;
int ret;
int i, j;
device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
if (!dsp_ipc)
return -ENOMEM;
for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
if (i < 2)
chan_name = kasprintf(GFP_KERNEL, "txdb%d", i);
@@ -86,6 +104,7 @@ static int imx_dsp_probe(struct platform_device *pdev)
return -ENOMEM;
dsp_chan = &dsp_ipc->chans[i];
dsp_chan->name = chan_name;
cl = &dsp_chan->cl;
cl->dev = dev;
cl->tx_block = false;
@@ -104,25 +123,41 @@ static int imx_dsp_probe(struct platform_device *pdev)
}
dev_dbg(dev, "request mbox chan %s\n", chan_name);
/* chan_name is not used anymore by framework */
kfree(chan_name);
}
dsp_ipc->dev = dev;
return 0;
out:
for (j = 0; j < i; j++) {
dsp_chan = &dsp_ipc->chans[j];
mbox_free_channel(dsp_chan->ch);
kfree(dsp_chan->name);
}
return ret;
}
static int imx_dsp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct imx_dsp_ipc *dsp_ipc;
int ret;
device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
dsp_ipc = devm_kzalloc(dev, sizeof(*dsp_ipc), GFP_KERNEL);
if (!dsp_ipc)
return -ENOMEM;
dsp_ipc->dev = dev;
dev_set_drvdata(dev, dsp_ipc);
ret = imx_dsp_setup_channels(dsp_ipc);
if (ret < 0)
return ret;
dev_info(dev, "NXP i.MX DSP IPC initialized\n");
return 0;
out:
kfree(chan_name);
for (j = 0; j < i; j++) {
dsp_chan = &dsp_ipc->chans[j];
mbox_free_channel(dsp_chan->ch);
}
return ret;
}
static int imx_dsp_remove(struct platform_device *pdev)
@@ -136,6 +171,7 @@ static int imx_dsp_remove(struct platform_device *pdev)
for (i = 0; i < DSP_MU_CHAN_NUM; i++) {
dsp_chan = &dsp_ipc->chans[i];
mbox_free_channel(dsp_chan->ch);
kfree(dsp_chan->name);
}
return 0;

View File

@@ -160,12 +160,18 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, false, 0 },
{ "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, true, 0 },
{ "mipi1", IMX_SC_R_MIPI_1, 1, false, 0 },
{ "mipi1-pwm0", IMX_SC_R_MIPI_1_PWM_0, 1, false, 0 },
{ "mipi1-i2c", IMX_SC_R_MIPI_1_I2C_0, 2, true, 0 },
/* LVDS SS */
{ "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
{ "lvds1", IMX_SC_R_LVDS_1, 1, false, 0 },
/* DC SS */
{ "dc0", IMX_SC_R_DC_0, 1, false, 0 },
{ "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
{ "dc0-video", IMX_SC_R_DC_0_VIDEO0, 2, true, 0 },
/* CM40 SS */
{ "cm40-i2c", IMX_SC_R_M4_0_I2C, 1, false, 0 },
@@ -180,6 +186,12 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
{ "cm41-pid", IMX_SC_R_M4_1_PID0, 5, true, 0},
{ "cm41-mu-a1", IMX_SC_R_M4_1_MU_1A, 1, false, 0},
{ "cm41-lpuart", IMX_SC_R_M4_1_UART, 1, false, 0},
/* IMAGE SS */
{ "img-jpegdec-mp", IMX_SC_R_MJPEG_DEC_MP, 1, false, 0 },
{ "img-jpegdec-s0", IMX_SC_R_MJPEG_DEC_S0, 4, true, 0 },
{ "img-jpegenc-mp", IMX_SC_R_MJPEG_ENC_MP, 1, false, 0 },
{ "img-jpegenc-s0", IMX_SC_R_MJPEG_ENC_S0, 4, true, 0 },
};
static const struct imx_sc_pd_soc imx8qxp_scu_pd = {

View File

@@ -3,8 +3,9 @@
# Amlogic Secure Monitor driver
#
config MESON_SM
bool
default ARCH_MESON
tristate "Amlogic Secure Monitor driver"
depends on ARCH_MESON || COMPILE_TEST
default y
depends on ARM64_4K_PAGES
help
Say y here to enable the Amlogic secure monitor driver

View File

@@ -331,3 +331,4 @@ static struct platform_driver meson_sm_driver = {
},
};
module_platform_driver_probe(meson_sm_driver, meson_sm_probe);
MODULE_LICENSE("GPL v2");

View File

@@ -412,16 +412,12 @@ static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
goto out;
}
len = strlen(ppath) + strlen(name) + 1;
len = snprintf(pathbuf, pathlen, "%s%s/", ppath, name);
if (len >= pathlen) {
err = -EINVAL;
goto out;
}
strncpy(pathbuf, ppath, pathlen);
strncat(pathbuf, name, strlen(name));
strcat(pathbuf, "/");
err = bpmp_populate_debugfs_inband(bpmp, dentry,
pathbuf);
if (err < 0)

View File

@@ -1703,14 +1703,14 @@ fail:
* @subtype: Resource assignment subtype that is being requested
* from the given device.
* @s_host: Host processor ID to which the resources are allocated
* @range_start: Start index of the resource range
* @range_num: Number of resources in the range
* @desc: Pointer to ti_sci_resource_desc to be updated with the
* resource range start index and number of resources
*
* Return: 0 if all went fine, else return appropriate error.
*/
static int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
u32 dev_id, u8 subtype, u8 s_host,
u16 *range_start, u16 *range_num)
struct ti_sci_resource_desc *desc)
{
struct ti_sci_msg_resp_get_resource_range *resp;
struct ti_sci_msg_req_get_resource_range *req;
@@ -1721,7 +1721,7 @@ static int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
if (IS_ERR(handle))
return PTR_ERR(handle);
if (!handle)
if (!handle || !desc)
return -EINVAL;
info = handle_to_ti_sci_info(handle);
@@ -1751,11 +1751,14 @@ static int ti_sci_get_resource_range(const struct ti_sci_handle *handle,
if (!ti_sci_is_response_ack(resp)) {
ret = -ENODEV;
} else if (!resp->range_start && !resp->range_num) {
} else if (!resp->range_num && !resp->range_num_sec) {
/* Neither of the two resource range is valid */
ret = -ENODEV;
} else {
*range_start = resp->range_start;
*range_num = resp->range_num;
desc->start = resp->range_start;
desc->num = resp->range_num;
desc->start_sec = resp->range_start_sec;
desc->num_sec = resp->range_num_sec;
};
fail:
@@ -1771,18 +1774,18 @@ fail:
* @dev_id: TISCI device ID.
* @subtype: Resource assignment subtype that is being requested
* from the given device.
* @range_start: Start index of the resource range
* @range_num: Number of resources in the range
* @desc: Pointer to ti_sci_resource_desc to be updated with the
* resource range start index and number of resources
*
* Return: 0 if all went fine, else return appropriate error.
*/
static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle,
u32 dev_id, u8 subtype,
u16 *range_start, u16 *range_num)
struct ti_sci_resource_desc *desc)
{
return ti_sci_get_resource_range(handle, dev_id, subtype,
TI_SCI_IRQ_SECONDARY_HOST_INVALID,
range_start, range_num);
desc);
}
/**
@@ -1793,18 +1796,17 @@ static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle,
* @subtype: Resource assignment subtype that is being requested
* from the given device.
* @s_host: Host processor ID to which the resources are allocated
* @range_start: Start index of the resource range
* @range_num: Number of resources in the range
* @desc: Pointer to ti_sci_resource_desc to be updated with the
* resource range start index and number of resources
*
* Return: 0 if all went fine, else return appropriate error.
*/
static
int ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle,
u32 dev_id, u8 subtype, u8 s_host,
u16 *range_start, u16 *range_num)
struct ti_sci_resource_desc *desc)
{
return ti_sci_get_resource_range(handle, dev_id, subtype, s_host,
range_start, range_num);
return ti_sci_get_resource_range(handle, dev_id, subtype, s_host, desc);
}
/**
@@ -2047,28 +2049,17 @@ static int ti_sci_cmd_free_event_map(const struct ti_sci_handle *handle,
}
/**
* ti_sci_cmd_ring_config() - configure RA ring
* @handle: Pointer to TI SCI handle.
* @valid_params: Bitfield defining validity of ring configuration
* parameters
* @nav_id: Device ID of Navigator Subsystem from which the ring is
* allocated
* @index: Ring index
* @addr_lo: The ring base address lo 32 bits
* @addr_hi: The ring base address hi 32 bits
* @count: Number of ring elements
* @mode: The mode of the ring
* @size: The ring element size.
* @order_id: Specifies the ring's bus order ID
* ti_sci_cmd_rm_ring_cfg() - Configure a NAVSS ring
* @handle: Pointer to TI SCI handle.
* @params: Pointer to ti_sci_msg_rm_ring_cfg ring config structure
*
* Return: 0 if all went well, else returns appropriate error value.
*
* See @ti_sci_msg_rm_ring_cfg_req for more info.
* See @ti_sci_msg_rm_ring_cfg and @ti_sci_msg_rm_ring_cfg_req for
* more info.
*/
static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle,
u32 valid_params, u16 nav_id, u16 index,
u32 addr_lo, u32 addr_hi, u32 count,
u8 mode, u8 size, u8 order_id)
static int ti_sci_cmd_rm_ring_cfg(const struct ti_sci_handle *handle,
const struct ti_sci_msg_rm_ring_cfg *params)
{
struct ti_sci_msg_rm_ring_cfg_req *req;
struct ti_sci_msg_hdr *resp;
@@ -2092,15 +2083,17 @@ static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle,
return ret;
}
req = (struct ti_sci_msg_rm_ring_cfg_req *)xfer->xfer_buf;
req->valid_params = valid_params;
req->nav_id = nav_id;
req->index = index;
req->addr_lo = addr_lo;
req->addr_hi = addr_hi;
req->count = count;
req->mode = mode;
req->size = size;
req->order_id = order_id;
req->valid_params = params->valid_params;
req->nav_id = params->nav_id;
req->index = params->index;
req->addr_lo = params->addr_lo;
req->addr_hi = params->addr_hi;
req->count = params->count;
req->mode = params->mode;
req->size = params->size;
req->order_id = params->order_id;
req->virtid = params->virtid;
req->asel = params->asel;
ret = ti_sci_do_xfer(info, xfer);
if (ret) {
@@ -2109,90 +2102,11 @@ static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle,
}
resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL;
fail:
ti_sci_put_one_xfer(&info->minfo, xfer);
dev_dbg(dev, "RM_RA:config ring %u ret:%d\n", index, ret);
return ret;
}
/**
* ti_sci_cmd_ring_get_config() - get RA ring configuration
* @handle: Pointer to TI SCI handle.
* @nav_id: Device ID of Navigator Subsystem from which the ring is
* allocated
* @index: Ring index
* @addr_lo: Returns ring's base address lo 32 bits
* @addr_hi: Returns ring's base address hi 32 bits
* @count: Returns number of ring elements
* @mode: Returns mode of the ring
* @size: Returns ring element size
* @order_id: Returns ring's bus order ID
*
* Return: 0 if all went well, else returns appropriate error value.
*
* See @ti_sci_msg_rm_ring_get_cfg_req for more info.
*/
static int ti_sci_cmd_ring_get_config(const struct ti_sci_handle *handle,
u32 nav_id, u32 index, u8 *mode,
u32 *addr_lo, u32 *addr_hi,
u32 *count, u8 *size, u8 *order_id)
{
struct ti_sci_msg_rm_ring_get_cfg_resp *resp;
struct ti_sci_msg_rm_ring_get_cfg_req *req;
struct ti_sci_xfer *xfer;
struct ti_sci_info *info;
struct device *dev;
int ret = 0;
if (IS_ERR_OR_NULL(handle))
return -EINVAL;
info = handle_to_ti_sci_info(handle);
dev = info->dev;
xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_RING_GET_CFG,
TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
sizeof(*req), sizeof(*resp));
if (IS_ERR(xfer)) {
ret = PTR_ERR(xfer);
dev_err(dev,
"RM_RA:Message get config failed(%d)\n", ret);
return ret;
}
req = (struct ti_sci_msg_rm_ring_get_cfg_req *)xfer->xfer_buf;
req->nav_id = nav_id;
req->index = index;
ret = ti_sci_do_xfer(info, xfer);
if (ret) {
dev_err(dev, "RM_RA:Mbox get config send fail %d\n", ret);
goto fail;
}
resp = (struct ti_sci_msg_rm_ring_get_cfg_resp *)xfer->xfer_buf;
if (!ti_sci_is_response_ack(resp)) {
ret = -ENODEV;
} else {
if (mode)
*mode = resp->mode;
if (addr_lo)
*addr_lo = resp->addr_lo;
if (addr_hi)
*addr_hi = resp->addr_hi;
if (count)
*count = resp->count;
if (size)
*size = resp->size;
if (order_id)
*order_id = resp->order_id;
};
fail:
ti_sci_put_one_xfer(&info->minfo, xfer);
dev_dbg(dev, "RM_RA:get config ring %u ret:%d\n", index, ret);
dev_dbg(dev, "RM_RA:config ring %u ret:%d\n", params->index, ret);
return ret;
}
@@ -2362,6 +2276,8 @@ static int ti_sci_cmd_rm_udmap_tx_ch_cfg(const struct ti_sci_handle *handle,
req->fdepth = params->fdepth;
req->tx_sched_priority = params->tx_sched_priority;
req->tx_burst_size = params->tx_burst_size;
req->tx_tdtype = params->tx_tdtype;
req->extended_ch_type = params->extended_ch_type;
ret = ti_sci_do_xfer(info, xfer);
if (ret) {
@@ -2921,8 +2837,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
iops->free_irq = ti_sci_cmd_free_irq;
iops->free_event_map = ti_sci_cmd_free_event_map;
rops->config = ti_sci_cmd_ring_config;
rops->get_config = ti_sci_cmd_ring_get_config;
rops->set_cfg = ti_sci_cmd_rm_ring_cfg;
psilops->pair = ti_sci_cmd_rm_psil_pair;
psilops->unpair = ti_sci_cmd_rm_psil_unpair;
@@ -3157,12 +3072,18 @@ u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
raw_spin_lock_irqsave(&res->lock, flags);
for (set = 0; set < res->sets; set++) {
free_bit = find_first_zero_bit(res->desc[set].res_map,
res->desc[set].num);
if (free_bit != res->desc[set].num) {
set_bit(free_bit, res->desc[set].res_map);
struct ti_sci_resource_desc *desc = &res->desc[set];
int res_count = desc->num + desc->num_sec;
free_bit = find_first_zero_bit(desc->res_map, res_count);
if (free_bit != res_count) {
set_bit(free_bit, desc->res_map);
raw_spin_unlock_irqrestore(&res->lock, flags);
return res->desc[set].start + free_bit;
if (desc->num && free_bit < desc->num)
return desc->start + free_bit;
else
return desc->start_sec + free_bit;
}
}
raw_spin_unlock_irqrestore(&res->lock, flags);
@@ -3183,10 +3104,14 @@ void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
raw_spin_lock_irqsave(&res->lock, flags);
for (set = 0; set < res->sets; set++) {
if (res->desc[set].start <= id &&
(res->desc[set].num + res->desc[set].start) > id)
clear_bit(id - res->desc[set].start,
res->desc[set].res_map);
struct ti_sci_resource_desc *desc = &res->desc[set];
if (desc->num && desc->start <= id &&
(desc->start + desc->num) > id)
clear_bit(id - desc->start, desc->res_map);
else if (desc->num_sec && desc->start_sec <= id &&
(desc->start_sec + desc->num_sec) > id)
clear_bit(id - desc->start_sec, desc->res_map);
}
raw_spin_unlock_irqrestore(&res->lock, flags);
}
@@ -3203,7 +3128,7 @@ u32 ti_sci_get_num_resources(struct ti_sci_resource *res)
u32 set, count = 0;
for (set = 0; set < res->sets; set++)
count += res->desc[set].num;
count += res->desc[set].num + res->desc[set].num_sec;
return count;
}
@@ -3227,7 +3152,7 @@ devm_ti_sci_get_resource_sets(const struct ti_sci_handle *handle,
{
struct ti_sci_resource *res;
bool valid_set = false;
int i, ret;
int i, ret, res_count;
res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
if (!res)
@@ -3242,23 +3167,23 @@ devm_ti_sci_get_resource_sets(const struct ti_sci_handle *handle,
for (i = 0; i < res->sets; i++) {
ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
sub_types[i],
&res->desc[i].start,
&res->desc[i].num);
&res->desc[i]);
if (ret) {
dev_dbg(dev, "dev = %d subtype %d not allocated for this host\n",
dev_id, sub_types[i]);
res->desc[i].start = 0;
res->desc[i].num = 0;
memset(&res->desc[i], 0, sizeof(res->desc[i]));
continue;
}
dev_dbg(dev, "dev = %d, subtype = %d, start = %d, num = %d\n",
dev_dbg(dev, "dev/sub_type: %d/%d, start/num: %d/%d | %d/%d\n",
dev_id, sub_types[i], res->desc[i].start,
res->desc[i].num);
res->desc[i].num, res->desc[i].start_sec,
res->desc[i].num_sec);
valid_set = true;
res_count = res->desc[i].num + res->desc[i].num_sec;
res->desc[i].res_map =
devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) *
devm_kzalloc(dev, BITS_TO_LONGS(res_count) *
sizeof(*res->desc[i].res_map), GFP_KERNEL);
if (!res->desc[i].res_map)
return ERR_PTR(-ENOMEM);

View File

@@ -49,7 +49,6 @@
#define TI_SCI_MSG_RM_RING_RECONFIG 0x1102
#define TI_SCI_MSG_RM_RING_RESET 0x1103
#define TI_SCI_MSG_RM_RING_CFG 0x1110
#define TI_SCI_MSG_RM_RING_GET_CFG 0x1111
/* PSI-L requests */
#define TI_SCI_MSG_RM_PSIL_PAIR 0x1280
@@ -574,8 +573,10 @@ struct ti_sci_msg_req_get_resource_range {
/**
* struct ti_sci_msg_resp_get_resource_range - Response to resource get range.
* @hdr: Generic Header
* @range_start: Start index of the resource range.
* @range_num: Number of resources in the range.
* @range_start: Start index of the first resource range.
* @range_num: Number of resources in the first range.
* @range_start_sec: Start index of the second resource range.
* @range_num_sec: Number of resources in the second range.
*
* Response to request TI_SCI_MSG_GET_RESOURCE_RANGE.
*/
@@ -583,6 +584,8 @@ struct ti_sci_msg_resp_get_resource_range {
struct ti_sci_msg_hdr hdr;
u16 range_start;
u16 range_num;
u16 range_start_sec;
u16 range_num_sec;
} __packed;
/**
@@ -656,6 +659,8 @@ struct ti_sci_msg_req_manage_irq {
* 3 - Valid bit for @tisci_msg_rm_ring_cfg_req mode
* 4 - Valid bit for @tisci_msg_rm_ring_cfg_req size
* 5 - Valid bit for @tisci_msg_rm_ring_cfg_req order_id
* 6 - Valid bit for @tisci_msg_rm_ring_cfg_req virtid
* 7 - Valid bit for @tisci_msg_rm_ring_cfg_req ASEL
* @nav_id: Device ID of Navigator Subsystem from which the ring is allocated
* @index: ring index to be configured.
* @addr_lo: 32 LSBs of ring base address to be programmed into the ring's
@@ -669,6 +674,9 @@ struct ti_sci_msg_req_manage_irq {
* the formula (log2(size_bytes) - 2), where size_bytes cannot be
* greater than 256.
* @order_id: Specifies the ring's bus order ID.
* @virtid: Ring virt ID value
* @asel: Ring ASEL (address select) value to be set into the ASEL field of the
* ring's RING_BA_HI register.
*/
struct ti_sci_msg_rm_ring_cfg_req {
struct ti_sci_msg_hdr hdr;
@@ -681,49 +689,8 @@ struct ti_sci_msg_rm_ring_cfg_req {
u8 mode;
u8 size;
u8 order_id;
} __packed;
/**
* struct ti_sci_msg_rm_ring_get_cfg_req - Get RA ring's configuration
*
* Gets the configuration of the non-real-time register fields of a ring. The
* host, or a supervisor of the host, who owns the ring must be the requesting
* host. The values of the non-real-time registers are returned in
* @ti_sci_msg_rm_ring_get_cfg_resp.
*
* @hdr: Generic Header
* @nav_id: Device ID of Navigator Subsystem from which the ring is allocated
* @index: ring index.
*/
struct ti_sci_msg_rm_ring_get_cfg_req {
struct ti_sci_msg_hdr hdr;
u16 nav_id;
u16 index;
} __packed;
/**
* struct ti_sci_msg_rm_ring_get_cfg_resp - Ring get configuration response
*
* Response received by host processor after RM has handled
* @ti_sci_msg_rm_ring_get_cfg_req. The response contains the ring's
* non-real-time register values.
*
* @hdr: Generic Header
* @addr_lo: Ring 32 LSBs of base address
* @addr_hi: Ring 16 MSBs of base address.
* @count: Ring number of elements.
* @mode: Ring mode.
* @size: encoded Ring element size
* @order_id: ing order ID.
*/
struct ti_sci_msg_rm_ring_get_cfg_resp {
struct ti_sci_msg_hdr hdr;
u32 addr_lo;
u32 addr_hi;
u32 count;
u8 mode;
u8 size;
u8 order_id;
u16 virtid;
u8 asel;
} __packed;
/**
@@ -910,6 +877,8 @@ struct rm_ti_sci_msg_udmap_rx_flow_opt_cfg {
* 12 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_credit_count
* 13 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::fdepth
* 14 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_burst_size
* 15 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_tdtype
* 16 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::extended_ch_type
*
* @nav_id: SoC device ID of Navigator Subsystem where tx channel is located
*
@@ -973,6 +942,15 @@ struct rm_ti_sci_msg_udmap_rx_flow_opt_cfg {
*
* @tx_burst_size: UDMAP transmit channel burst size configuration to be
* programmed into the tx_burst_size field of the TCHAN_TCFG register.
*
* @tx_tdtype: UDMAP transmit channel teardown type configuration to be
* programmed into the tdtype field of the TCHAN_TCFG register:
* 0 - Return immediately
* 1 - Wait for completion message from remote peer
*
* @extended_ch_type: Valid for BCDMA.
* 0 - the channel is split tx channel (tchan)
* 1 - the channel is block copy channel (bchan)
*/
struct ti_sci_msg_rm_udmap_tx_ch_cfg_req {
struct ti_sci_msg_hdr hdr;
@@ -994,6 +972,8 @@ struct ti_sci_msg_rm_udmap_tx_ch_cfg_req {
u16 fdepth;
u8 tx_sched_priority;
u8 tx_burst_size;
u8 tx_tdtype;
u8 extended_ch_type;
} __packed;
/**

View File

@@ -615,13 +615,13 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
/**
* zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device
*
* @node_id Node ID of the device
* @type Type of tap delay to set (input/output)
* @value Value to set fot the tap delay
* @node_id: Node ID of the device
* @type: Type of tap delay to set (input/output)
* @value: Value to set fot the tap delay
*
* This function sets input/output tap delay for the SD device.
*
* @return Returns status, either success or error+reason
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
{
@@ -633,12 +633,12 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
/**
* zynqmp_pm_sd_dll_reset() - Reset DLL logic
*
* @node_id Node ID of the device
* @type Reset type
* @node_id: Node ID of the device
* @type: Reset type
*
* This function resets DLL logic for the SD device.
*
* @return Returns status, either success or error+reason
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
{
@@ -649,12 +649,12 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
/**
* zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
* @index GGS register index
* @value Register value to be written
* @index: GGS register index
* @value: Register value to be written
*
* This function writes value to GGS register.
*
* @return Returns status, either success or error+reason
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_write_ggs(u32 index, u32 value)
{
@@ -665,12 +665,12 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
/**
* zynqmp_pm_write_ggs() - PM API for reading global general storage (ggs)
* @index GGS register index
* @value Register value to be written
* @index: GGS register index
* @value: Register value to be written
*
* This function returns GGS register value.
*
* @return Returns status, either success or error+reason
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_read_ggs(u32 index, u32 *value)
{
@@ -682,12 +682,12 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
/**
* zynqmp_pm_write_pggs() - PM API for writing persistent global general
* storage (pggs)
* @index PGGS register index
* @value Register value to be written
* @index: PGGS register index
* @value: Register value to be written
*
* This function writes value to PGGS register.
*
* @return Returns status, either success or error+reason
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_write_pggs(u32 index, u32 value)
{
@@ -699,12 +699,12 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
/**
* zynqmp_pm_write_pggs() - PM API for reading persistent global general
* storage (pggs)
* @index PGGS register index
* @value Register value to be written
* @index: PGGS register index
* @value: Register value to be written
*
* This function returns PGGS register value.
*
* @return Returns status, either success or error+reason
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_read_pggs(u32 index, u32 *value)
{
@@ -715,12 +715,12 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
/**
* zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
* @value Status value to be written
* @value: Status value to be written
*
* This function sets healthy bit value to indicate boot health status
* to firmware.
*
* @return Returns status, either success or error+reason
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_set_boot_health_status(u32 value)
{
@@ -815,10 +815,10 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
* zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
* master has initialized its own power management
*
* Return: Returns status, either success or error+reason
*
* This API function is to be used for notify the power management controller
* about the completed power management initialization.
*
* Return: Returns status, either success or error+reason
*/
int zynqmp_pm_init_finalize(void)
{

View File

@@ -3102,6 +3102,8 @@ static int drm_cvt_modes(struct drm_connector *connector,
height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2;
switch (cvt->code[1] & 0x0c) {
/* default - because compiler doesn't see that we've enumerated all cases */
default:
case 0x00:
width = height * 4 / 3;
break;
@@ -3114,8 +3116,6 @@ static int drm_cvt_modes(struct drm_connector *connector,
case 0x0c:
width = height * 15 / 9;
break;
default:
unreachable();
}
for (j = 1; j < 5; j++) {

View File

@@ -829,8 +829,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
mtk_crtc->cmdq_client =
cmdq_mbox_create(mtk_crtc->mmsys_dev,
drm_crtc_index(&mtk_crtc->base),
2000);
drm_crtc_index(&mtk_crtc->base));
if (IS_ERR(mtk_crtc->cmdq_client)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base));

View File

@@ -7,6 +7,7 @@
#define MTK_DRM_DDP_COMP_H
#include <linux/io.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
struct device;
struct device_node;
@@ -35,39 +36,6 @@ enum mtk_ddp_comp_type {
MTK_DDP_COMP_TYPE_MAX,
};
enum mtk_ddp_comp_id {
DDP_COMPONENT_AAL0,
DDP_COMPONENT_AAL1,
DDP_COMPONENT_BLS,
DDP_COMPONENT_CCORR,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_COLOR1,
DDP_COMPONENT_DITHER,
DDP_COMPONENT_DPI0,
DDP_COMPONENT_DPI1,
DDP_COMPONENT_DSI0,
DDP_COMPONENT_DSI1,
DDP_COMPONENT_DSI2,
DDP_COMPONENT_DSI3,
DDP_COMPONENT_GAMMA,
DDP_COMPONENT_OD0,
DDP_COMPONENT_OD1,
DDP_COMPONENT_OVL0,
DDP_COMPONENT_OVL_2L0,
DDP_COMPONENT_OVL_2L1,
DDP_COMPONENT_OVL1,
DDP_COMPONENT_PWM0,
DDP_COMPONENT_PWM1,
DDP_COMPONENT_PWM2,
DDP_COMPONENT_RDMA0,
DDP_COMPONENT_RDMA1,
DDP_COMPONENT_RDMA2,
DDP_COMPONENT_UFOE,
DDP_COMPONENT_WDMA0,
DDP_COMPONENT_WDMA1,
DDP_COMPONENT_ID_MAX,
};
struct mtk_ddp_comp;
struct cmdq_pkt;
struct mtk_ddp_comp_funcs {

View File

@@ -805,25 +805,6 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
ret = of_dma_configure(drm->dev, dev->of_node, true);
if (ret)
return ret;
} else {
/*
* If we don't have the interconnect property, most likely
* because of an old DT, we need to set the DMA offset by hand
* on our device since the RAM mapping is at 0 for the DMA bus,
* unlike the CPU.
*
* XXX(hch): this has no business in a driver and needs to move
* to the device tree.
*
* If we have two subsequent calls to dma_direct_set_offset
* returns -EINVAL. Unfortunately, this happens when we have two
* backends in the system, and will result in the driver
* reporting an error while it has been setup properly before.
* Ignore EINVAL, but it should really be removed eventually.
*/
ret = dma_direct_set_offset(drm->dev, PHYS_OFFSET, 0, SZ_4G);
if (ret && ret != -EINVAL)
return ret;
}
backend->engine.node = dev->of_node;

View File

@@ -30,7 +30,7 @@ static inline u64 __pow10(u8 x)
static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value)
{
s8 scale = sensor->scale;
int scale = sensor->scale;
u64 f;
switch (sensor->type) {

View File

@@ -167,33 +167,6 @@ static int sun4i_csi_probe(struct platform_device *pdev)
if (!csi->traits)
return -EINVAL;
/*
* On Allwinner SoCs, some high memory bandwidth devices do DMA
* directly over the memory bus (called MBUS), instead of the
* system bus. The memory bus has a different addressing scheme
* without the DRAM starting offset.
*
* In some cases this can be described by an interconnect in
* the device tree. In other cases where the hardware is not
* fully understood and the interconnect is left out of the
* device tree, fall back to a default offset.
*/
if (of_find_property(csi->dev->of_node, "interconnects", NULL)) {
ret = of_dma_configure(csi->dev, csi->dev->of_node, true);
if (ret)
return ret;
} else {
/*
* XXX(hch): this has no business in a driver and needs to move
* to the device tree.
*/
#ifdef PHYS_PFN_OFFSET
ret = dma_direct_set_offset(csi->dev, PHYS_OFFSET, 0, SZ_4G);
if (ret)
return ret;
#endif
}
csi->mdev.dev = csi->dev;
strscpy(csi->mdev.model, "Allwinner Video Capture Device",
sizeof(csi->mdev.model));

View File

@@ -881,14 +881,6 @@ static int sun6i_csi_resource_request(struct sun6i_csi_dev *sdev,
return 0;
}
/*
* PHYS_OFFSET isn't available on all architectures. In order to
* accommodate for COMPILE_TEST, let's define it to something dumb.
*/
#if defined(CONFIG_COMPILE_TEST) && !defined(PHYS_OFFSET)
#define PHYS_OFFSET 0
#endif
static int sun6i_csi_probe(struct platform_device *pdev)
{
struct sun6i_csi_dev *sdev;
@@ -899,15 +891,6 @@ static int sun6i_csi_probe(struct platform_device *pdev)
return -ENOMEM;
sdev->dev = &pdev->dev;
/*
* The DMA bus has the memory mapped at 0.
*
* XXX(hch): this has no business in a driver and needs to move
* to the device tree.
*/
ret = dma_direct_set_offset(sdev->dev, PHYS_OFFSET, 0, SZ_4G);
if (ret)
return ret;
ret = sun6i_csi_resource_request(sdev, pdev);
if (ret)

View File

@@ -825,10 +825,6 @@ static int deinterlace_probe(struct platform_device *pdev)
return ret;
}
ret = of_dma_configure(dev->dev, dev->dev->of_node, true);
if (ret)
return ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dev->base))

View File

@@ -128,7 +128,7 @@ config OMAP_GPMC_DEBUG
config TI_EMIF_SRAM
tristate "Texas Instruments EMIF SRAM driver"
depends on SOC_AM33XX || SOC_AM43XX || (ARM && COMPILE_TEST)
depends on SOC_AM33XX || SOC_AM43XX || (ARM && CPU_V7 && COMPILE_TEST)
depends on SRAM
help
This driver is for the EMIF module available on Texas Instruments
@@ -191,8 +191,8 @@ config DA8XX_DDRCTL
config PL353_SMC
tristate "ARM PL35X Static Memory Controller(SMC) driver"
default y if ARM
depends on ARM
depends on ARM_AMBA || COMPILE_TEST
depends on ARM || COMPILE_TEST
depends on ARM_AMBA
help
This driver is for the ARM PL351/PL353 Static Memory
Controller(SMC) module.

View File

@@ -291,6 +291,8 @@ static int jz4780_nemc_probe(struct platform_device *pdev)
nemc->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -EINVAL;
/*
* The driver currently only uses the registers up to offset
@@ -304,9 +306,9 @@ static int jz4780_nemc_probe(struct platform_device *pdev)
}
nemc->base = devm_ioremap(dev, res->start, NEMC_REG_LEN);
if (IS_ERR(nemc->base)) {
if (!nemc->base) {
dev_err(dev, "failed to get I/O memory\n");
return PTR_ERR(nemc->base);
return -ENOMEM;
}
writel(0, nemc->base + NEMC_NFCSR);

View File

@@ -268,6 +268,10 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
/* IPU0 | IPU1 | CCU */
};
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
.config_port = mtk_smi_larb_config_port_gen2_general,
};
static const struct of_device_id mtk_smi_larb_of_ids[] = {
{
.compatible = "mediatek,mt8167-smi-larb",
@@ -293,6 +297,10 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
.compatible = "mediatek,mt8183-smi-larb",
.data = &mtk_smi_larb_mt8183
},
{
.compatible = "mediatek,mt8192-smi-larb",
.data = &mtk_smi_larb_mt8192
},
{}
};
@@ -432,6 +440,13 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
F_MMU1_LARB(7),
};
static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
.gen = MTK_SMI_GEN2,
.has_gals = true,
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(5) |
F_MMU1_LARB(6),
};
static const struct of_device_id mtk_smi_common_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-common",
@@ -457,6 +472,10 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
.compatible = "mediatek,mt8183-smi-common",
.data = &mtk_smi_common_mt8183,
},
{
.compatible = "mediatek,mt8192-smi-common",
.data = &mtk_smi_common_mt8192,
},
{}
};

View File

@@ -12,7 +12,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
@@ -204,18 +203,6 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
}
EXPORT_SYMBOL(rpcif_sw_init);
void rpcif_enable_rpm(struct rpcif *rpc)
{
pm_runtime_enable(rpc->dev);
}
EXPORT_SYMBOL(rpcif_enable_rpm);
void rpcif_disable_rpm(struct rpcif *rpc)
{
pm_runtime_put_sync(rpc->dev);
}
EXPORT_SYMBOL(rpcif_disable_rpm);
void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
{
u32 dummy;
@@ -508,7 +495,8 @@ exit:
return ret;
err_out:
ret = reset_control_reset(rpc->rstc);
if (reset_control_reset(rpc->rstc))
dev_err(rpc->dev, "Failed to reset HW\n");
rpcif_hw_init(rpc, rpc->bus_size == 2);
goto exit;
}
@@ -560,9 +548,11 @@ static int rpcif_probe(struct platform_device *pdev)
} else if (of_device_is_compatible(flash, "cfi-flash")) {
name = "rpc-if-hyperflash";
} else {
of_node_put(flash);
dev_warn(&pdev->dev, "unknown flash type\n");
return -ENODEV;
}
of_node_put(flash);
vdev = platform_device_alloc(name, pdev->id);
if (!vdev)

View File

@@ -3,14 +3,17 @@ config TEGRA_MC
bool "NVIDIA Tegra Memory Controller support"
default y
depends on ARCH_TEGRA
select INTERCONNECT
help
This driver supports the Memory Controller (MC) hardware found on
NVIDIA Tegra SoCs.
config TEGRA20_EMC
bool "NVIDIA Tegra20 External Memory Controller driver"
tristate "NVIDIA Tegra20 External Memory Controller driver"
default y
depends on ARCH_TEGRA_2x_SOC
depends on TEGRA_MC && ARCH_TEGRA_2x_SOC
select DEVFREQ_GOV_SIMPLE_ONDEMAND
select PM_DEVFREQ
help
This driver is for the External Memory Controller (EMC) found on
Tegra20 chips. The EMC controls the external DRAM on the board.
@@ -18,9 +21,10 @@ config TEGRA20_EMC
external memory.
config TEGRA30_EMC
bool "NVIDIA Tegra30 External Memory Controller driver"
tristate "NVIDIA Tegra30 External Memory Controller driver"
default y
depends on TEGRA_MC && ARCH_TEGRA_3x_SOC
select PM_OPP
help
This driver is for the External Memory Controller (EMC) found on
Tegra30 chips. The EMC controls the external DRAM on the board.

View File

@@ -6,6 +6,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -42,6 +43,54 @@ static const struct of_device_id tegra_mc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
static void tegra_mc_devm_action_put_device(void *data)
{
struct tegra_mc *mc = data;
put_device(mc->dev);
}
/**
* devm_tegra_memory_controller_get() - get Tegra Memory Controller handle
* @dev: device pointer for the consumer device
*
* This function will search for the Memory Controller node in a device-tree
* and retrieve the Memory Controller handle.
*
* Return: ERR_PTR() on error or a valid pointer to a struct tegra_mc.
*/
struct tegra_mc *devm_tegra_memory_controller_get(struct device *dev)
{
struct platform_device *pdev;
struct device_node *np;
struct tegra_mc *mc;
int err;
np = of_parse_phandle(dev->of_node, "nvidia,memory-controller", 0);
if (!np)
return ERR_PTR(-ENOENT);
pdev = of_find_device_by_node(np);
of_node_put(np);
if (!pdev)
return ERR_PTR(-ENODEV);
mc = platform_get_drvdata(pdev);
if (!mc) {
put_device(&pdev->dev);
return ERR_PTR(-EPROBE_DEFER);
}
err = devm_add_action(dev, tegra_mc_devm_action_put_device, mc);
if (err) {
put_device(mc->dev);
return ERR_PTR(err);
}
return mc;
}
EXPORT_SYMBOL_GPL(devm_tegra_memory_controller_get);
static int tegra_mc_block_dma_common(struct tegra_mc *mc,
const struct tegra_mc_reset *rst)
{
@@ -298,6 +347,7 @@ int tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate)
return 0;
}
EXPORT_SYMBOL_GPL(tegra_mc_write_emem_configuration);
unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc)
{
@@ -309,6 +359,7 @@ unsigned int tegra_mc_get_emem_device_count(struct tegra_mc *mc)
return dram_count;
}
EXPORT_SYMBOL_GPL(tegra_mc_get_emem_device_count);
static int load_one_timing(struct tegra_mc *mc,
struct tegra_mc_timing *timing,
@@ -591,6 +642,101 @@ static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data)
return IRQ_HANDLED;
}
/*
* Memory Controller (MC) has few Memory Clients that are issuing memory
* bandwidth allocation requests to the MC interconnect provider. The MC
* provider aggregates the requests and then sends the aggregated request
* up to the External Memory Controller (EMC) interconnect provider which
* re-configures hardware interface to External Memory (EMEM) in accordance
* to the required bandwidth. Each MC interconnect node represents an
* individual Memory Client.
*
* Memory interconnect topology:
*
* +----+
* +--------+ | |
* | TEXSRD +--->+ |
* +--------+ | |
* | | +-----+ +------+
* ... | MC +--->+ EMC +--->+ EMEM |
* | | +-----+ +------+
* +--------+ | |
* | DISP.. +--->+ |
* +--------+ | |
* +----+
*/
static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
{
struct icc_node *node;
unsigned int i;
int err;
/* older device-trees don't have interconnect properties */
if (!device_property_present(mc->dev, "#interconnect-cells") ||
!mc->soc->icc_ops)
return 0;
mc->provider.dev = mc->dev;
mc->provider.data = &mc->provider;
mc->provider.set = mc->soc->icc_ops->set;
mc->provider.aggregate = mc->soc->icc_ops->aggregate;
mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended;
err = icc_provider_add(&mc->provider);
if (err)
return err;
/* create Memory Controller node */
node = icc_node_create(TEGRA_ICC_MC);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto del_provider;
}
node->name = "Memory Controller";
icc_node_add(node, &mc->provider);
/* link Memory Controller to External Memory Controller */
err = icc_link_create(node, TEGRA_ICC_EMC);
if (err)
goto remove_nodes;
for (i = 0; i < mc->soc->num_clients; i++) {
/* create MC client node */
node = icc_node_create(mc->soc->clients[i].id);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto remove_nodes;
}
node->name = mc->soc->clients[i].name;
icc_node_add(node, &mc->provider);
/* link Memory Client to Memory Controller */
err = icc_link_create(node, TEGRA_ICC_MC);
if (err)
goto remove_nodes;
}
/*
* MC driver is registered too early, so early that generic driver
* syncing doesn't work for the MC. But it doesn't really matter
* since syncing works for the EMC drivers, hence we can sync the
* MC driver by ourselves and then EMC will complete syncing of
* the whole ICC state.
*/
icc_sync_state(mc->dev);
return 0;
remove_nodes:
icc_nodes_remove(&mc->provider);
del_provider:
icc_provider_del(&mc->provider);
return err;
}
static int tegra_mc_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -659,10 +805,8 @@ static int tegra_mc_probe(struct platform_device *pdev)
}
mc->irq = platform_get_irq(pdev, 0);
if (mc->irq < 0) {
dev_err(&pdev->dev, "interrupt not specified\n");
if (mc->irq < 0)
return mc->irq;
}
WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n");
@@ -681,6 +825,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to register reset controller: %d\n",
err);
err = tegra_mc_interconnect_setup(mc);
if (err < 0)
dev_err(&pdev->dev, "failed to initialize interconnect: %d\n",
err);
if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU) && mc->soc->smmu) {
mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
if (IS_ERR(mc->smmu)) {

View File

@@ -78,6 +78,20 @@
#define MC_TIMING_UPDATE BIT(0)
static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents)
{
val = val * percents;
do_div(val, 100);
return min_t(u64, val, U32_MAX);
}
static inline struct tegra_mc *
icc_provider_to_tegra_mc(struct icc_provider *provider)
{
return container_of(provider, struct tegra_mc, provider);
}
static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset)
{
return readl_relaxed(mc->regs + offset);
@@ -115,4 +129,12 @@ extern const struct tegra_mc_soc tegra132_mc_soc;
extern const struct tegra_mc_soc tegra210_mc_soc;
#endif
/*
* These IDs are for internal use of Tegra ICC drivers. The ID numbers are
* chosen such that they don't conflict with the device-tree ICC node IDs.
*/
#define TEGRA_ICC_MC 1000
#define TEGRA_ICC_EMC 1001
#define TEGRA_ICC_EMEM 1002
#endif /* MEMORY_TEGRA_MC_H */

View File

@@ -15,6 +15,12 @@ static const struct tegra_mc_client tegra114_mc_clients[] = {
.id = 0x00,
.name = "ptcr",
.swgroup = TEGRA_SWGROUP_PTC,
.la = {
.reg = 0x34c,
.shift = 0,
.mask = 0xff,
.def = 0x0,
},
}, {
.id = 0x01,
.name = "display0a",

View File

@@ -1177,10 +1177,8 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
static int tegra_emc_probe(struct platform_device *pdev)
{
struct platform_device *mc;
struct device_node *np;
struct tegra_emc *emc;
struct resource *res;
u32 ram_code;
int err;
@@ -1190,25 +1188,13 @@ static int tegra_emc_probe(struct platform_device *pdev)
emc->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
emc->regs = devm_ioremap_resource(&pdev->dev, res);
emc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(emc->regs))
return PTR_ERR(emc->regs);
np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
if (!np) {
dev_err(&pdev->dev, "could not get memory controller\n");
return -ENOENT;
}
mc = of_find_device_by_node(np);
of_node_put(np);
if (!mc)
return -ENOENT;
emc->mc = platform_get_drvdata(mc);
if (!emc->mc)
return -EPROBE_DEFER;
emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
if (IS_ERR(emc->mc))
return PTR_ERR(emc->mc);
ram_code = tegra_read_ram_code();

View File

@@ -15,6 +15,12 @@ static const struct tegra_mc_client tegra124_mc_clients[] = {
.id = 0x00,
.name = "ptcr",
.swgroup = TEGRA_SWGROUP_PTC,
.la = {
.reg = 0x34c,
.shift = 0,
.mask = 0xff,
.def = 0x0,
},
}, {
.id = 0x01,
.name = "display0a",

View File

@@ -8,19 +8,27 @@
#include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/debugfs.h>
#include <linux/devfreq.h>
#include <linux/err.h>
#include <linux/interconnect-provider.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/sort.h>
#include <linux/types.h>
#include <soc/tegra/common.h>
#include <soc/tegra/fuse.h>
#include "mc.h"
#define EMC_INTSTATUS 0x000
#define EMC_INTMASK 0x004
#define EMC_DBG 0x008
@@ -62,6 +70,11 @@
#define EMC_ODT_READ 0x0b4
#define EMC_FBIO_CFG5 0x104
#define EMC_FBIO_CFG6 0x114
#define EMC_STAT_CONTROL 0x160
#define EMC_STAT_LLMC_CONTROL 0x178
#define EMC_STAT_PWR_CLOCK_LIMIT 0x198
#define EMC_STAT_PWR_CLOCKS 0x19c
#define EMC_STAT_PWR_COUNT 0x1a0
#define EMC_AUTO_CAL_INTERVAL 0x2a8
#define EMC_CFG_2 0x2b8
#define EMC_CFG_DIG_DLL 0x2bc
@@ -88,6 +101,12 @@
#define EMC_DBG_READ_DQM_CTRL BIT(9)
#define EMC_DBG_CFG_PRIORITY BIT(24)
#define EMC_FBIO_CFG5_DRAM_WIDTH_X16 BIT(4)
#define EMC_PWR_GATHER_CLEAR (1 << 8)
#define EMC_PWR_GATHER_DISABLE (2 << 8)
#define EMC_PWR_GATHER_ENABLE (3 << 8)
static const u16 emc_timing_registers[] = {
EMC_RC,
EMC_RFC,
@@ -142,11 +161,26 @@ struct emc_timing {
u32 data[ARRAY_SIZE(emc_timing_registers)];
};
enum emc_rate_request_type {
EMC_RATE_DEVFREQ,
EMC_RATE_DEBUG,
EMC_RATE_ICC,
EMC_RATE_TYPE_MAX,
};
struct emc_rate_request {
unsigned long min_rate;
unsigned long max_rate;
};
struct tegra_emc {
struct device *dev;
struct tegra_mc *mc;
struct icc_provider provider;
struct notifier_block clk_nb;
struct clk *clk;
void __iomem *regs;
unsigned int dram_bus_width;
struct emc_timing *timings;
unsigned int num_timings;
@@ -156,6 +190,17 @@ struct tegra_emc {
unsigned long min_rate;
unsigned long max_rate;
} debugfs;
/*
* There are multiple sources in the EMC driver which could request
* a min/max clock rate, these rates are contained in this array.
*/
struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
/* protect shared rate-change code path */
struct mutex rate_lock;
struct devfreq_simple_ondemand_data ondemand_data;
};
static irqreturn_t tegra_emc_isr(int irq, void *data)
@@ -383,6 +428,11 @@ tegra_emc_find_node_by_ram_code(struct device *dev)
u32 value, ram_code;
int err;
if (of_get_child_count(dev->of_node) == 0) {
dev_info(dev, "device-tree doesn't have memory timings\n");
return NULL;
}
if (!of_property_read_bool(dev->of_node, "nvidia,use-ram-code"))
return of_node_get(dev->of_node);
@@ -408,7 +458,7 @@ tegra_emc_find_node_by_ram_code(struct device *dev)
static int emc_setup_hw(struct tegra_emc *emc)
{
u32 intmask = EMC_REFRESH_OVERFLOW_INT;
u32 emc_cfg, emc_dbg;
u32 emc_cfg, emc_dbg, emc_fbio;
emc_cfg = readl_relaxed(emc->regs + EMC_CFG_2);
@@ -439,6 +489,15 @@ static int emc_setup_hw(struct tegra_emc *emc)
emc_dbg &= ~EMC_DBG_FORCE_UPDATE;
writel_relaxed(emc_dbg, emc->regs + EMC_DBG);
emc_fbio = readl_relaxed(emc->regs + EMC_FBIO_CFG5);
if (emc_fbio & EMC_FBIO_CFG5_DRAM_WIDTH_X16)
emc->dram_bus_width = 16;
else
emc->dram_bus_width = 32;
dev_info(emc->dev, "%ubit DRAM bus\n", emc->dram_bus_width);
return 0;
}
@@ -451,6 +510,9 @@ static long emc_round_rate(unsigned long rate,
struct tegra_emc *emc = arg;
unsigned int i;
if (!emc->num_timings)
return clk_get_rate(emc->clk);
min_rate = min(min_rate, emc->timings[emc->num_timings - 1].rate);
for (i = 0; i < emc->num_timings; i++) {
@@ -480,6 +542,83 @@ static long emc_round_rate(unsigned long rate,
return timing->rate;
}
static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
{
unsigned int i;
for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
emc->requested_rate[i].min_rate = 0;
emc->requested_rate[i].max_rate = ULONG_MAX;
}
}
static int emc_request_rate(struct tegra_emc *emc,
unsigned long new_min_rate,
unsigned long new_max_rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = emc->requested_rate;
unsigned long min_rate = 0, max_rate = ULONG_MAX;
unsigned int i;
int err;
/* select minimum and maximum rates among the requested rates */
for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
if (i == type) {
min_rate = max(new_min_rate, min_rate);
max_rate = min(new_max_rate, max_rate);
} else {
min_rate = max(req->min_rate, min_rate);
max_rate = min(req->max_rate, max_rate);
}
}
if (min_rate > max_rate) {
dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
__func__, type, min_rate, max_rate);
return -ERANGE;
}
/*
* EMC rate-changes should go via OPP API because it manages voltage
* changes.
*/
err = dev_pm_opp_set_rate(emc->dev, min_rate);
if (err)
return err;
emc->requested_rate[type].min_rate = new_min_rate;
emc->requested_rate[type].max_rate = new_max_rate;
return 0;
}
static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, rate, req->max_rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, req->min_rate, rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
/*
* debugfs interface
*
@@ -563,7 +702,7 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
if (!tegra_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_min_rate(emc->clk, rate);
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -593,7 +732,7 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
if (!tegra_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_max_rate(emc->clk, rate);
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -650,47 +789,330 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc)
emc, &tegra_emc_debug_max_rate_fops);
}
static inline struct tegra_emc *
to_tegra_emc_provider(struct icc_provider *provider)
{
return container_of(provider, struct tegra_emc, provider);
}
static struct icc_node_data *
emc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data)
{
struct icc_provider *provider = data;
struct icc_node_data *ndata;
struct icc_node *node;
/* External Memory is the only possible ICC route */
list_for_each_entry(node, &provider->nodes, node_list) {
if (node->id != TEGRA_ICC_EMEM)
continue;
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
if (!ndata)
return ERR_PTR(-ENOMEM);
/*
* SRC and DST nodes should have matching TAG in order to have
* it set by default for a requested path.
*/
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
ndata->node = node;
return ndata;
}
return ERR_PTR(-EPROBE_DEFER);
}
static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct tegra_emc *emc = to_tegra_emc_provider(dst->provider);
unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
unsigned long long rate = max(avg_bw, peak_bw);
unsigned int dram_data_bus_width_bytes;
int err;
/*
* Tegra20 EMC runs on x2 clock rate of SDRAM bus because DDR data
* is sampled on both clock edges. This means that EMC clock rate
* equals to the peak data-rate.
*/
dram_data_bus_width_bytes = emc->dram_bus_width / 8;
do_div(rate, dram_data_bus_width_bytes);
rate = min_t(u64, rate, U32_MAX);
err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
if (err)
return err;
return 0;
}
static int tegra_emc_interconnect_init(struct tegra_emc *emc)
{
const struct tegra_mc_soc *soc;
struct icc_node *node;
int err;
emc->mc = devm_tegra_memory_controller_get(emc->dev);
if (IS_ERR(emc->mc))
return PTR_ERR(emc->mc);
soc = emc->mc->soc;
emc->provider.dev = emc->dev;
emc->provider.set = emc_icc_set;
emc->provider.data = &emc->provider;
emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider);
if (err)
goto err_msg;
/* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto del_provider;
}
node->name = "External Memory Controller";
icc_node_add(node, &emc->provider);
/* link External Memory Controller to External Memory (DRAM) */
err = icc_link_create(node, TEGRA_ICC_EMEM);
if (err)
goto remove_nodes;
/* create External Memory node */
node = icc_node_create(TEGRA_ICC_EMEM);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto remove_nodes;
}
node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider);
return 0;
remove_nodes:
icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
return err;
}
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
{
u32 hw_version = BIT(tegra_sku_info.soc_process_id);
struct opp_table *clk_opp_table, *hw_opp_table;
int err;
clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL);
err = PTR_ERR_OR_ZERO(clk_opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP clk: %d\n", err);
return err;
}
hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
err = PTR_ERR_OR_ZERO(hw_opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
goto put_clk_table;
}
err = dev_pm_opp_of_add_table(emc->dev);
if (err) {
if (err == -ENODEV)
dev_err(emc->dev, "OPP table not found, please update your device tree\n");
else
dev_err(emc->dev, "failed to add OPP table: %d\n", err);
goto put_hw_table;
}
dev_info(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
hw_version, clk_get_rate(emc->clk) / 1000000);
/* first dummy rate-set initializes voltage state */
err = dev_pm_opp_set_rate(emc->dev, clk_get_rate(emc->clk));
if (err) {
dev_err(emc->dev, "failed to initialize OPP clock: %d\n", err);
goto remove_table;
}
return 0;
remove_table:
dev_pm_opp_of_remove_table(emc->dev);
put_hw_table:
dev_pm_opp_put_supported_hw(hw_opp_table);
put_clk_table:
dev_pm_opp_put_clkname(clk_opp_table);
return err;
}
static void devm_tegra_emc_unset_callback(void *data)
{
tegra20_clk_set_emc_round_callback(NULL, NULL);
}
static void devm_tegra_emc_unreg_clk_notifier(void *data)
{
struct tegra_emc *emc = data;
clk_notifier_unregister(emc->clk, &emc->clk_nb);
}
static int tegra_emc_init_clk(struct tegra_emc *emc)
{
int err;
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
err = devm_add_action_or_reset(emc->dev, devm_tegra_emc_unset_callback,
NULL);
if (err)
return err;
emc->clk = devm_clk_get(emc->dev, NULL);
if (IS_ERR(emc->clk)) {
dev_err(emc->dev, "failed to get EMC clock: %pe\n", emc->clk);
return PTR_ERR(emc->clk);
}
err = clk_notifier_register(emc->clk, &emc->clk_nb);
if (err) {
dev_err(emc->dev, "failed to register clk notifier: %d\n", err);
return err;
}
err = devm_add_action_or_reset(emc->dev,
devm_tegra_emc_unreg_clk_notifier, emc);
if (err)
return err;
return 0;
}
static int tegra_emc_devfreq_target(struct device *dev, unsigned long *freq,
u32 flags)
{
struct tegra_emc *emc = dev_get_drvdata(dev);
struct dev_pm_opp *opp;
unsigned long rate;
opp = devfreq_recommended_opp(dev, freq, flags);
if (IS_ERR(opp)) {
dev_err(dev, "failed to find opp for %lu Hz\n", *freq);
return PTR_ERR(opp);
}
rate = dev_pm_opp_get_freq(opp);
dev_pm_opp_put(opp);
return emc_set_min_rate(emc, rate, EMC_RATE_DEVFREQ);
}
static int tegra_emc_devfreq_get_dev_status(struct device *dev,
struct devfreq_dev_status *stat)
{
struct tegra_emc *emc = dev_get_drvdata(dev);
/* freeze counters */
writel_relaxed(EMC_PWR_GATHER_DISABLE, emc->regs + EMC_STAT_CONTROL);
/*
* busy_time: number of clocks EMC request was accepted
* total_time: number of clocks PWR_GATHER control was set to ENABLE
*/
stat->busy_time = readl_relaxed(emc->regs + EMC_STAT_PWR_COUNT);
stat->total_time = readl_relaxed(emc->regs + EMC_STAT_PWR_CLOCKS);
stat->current_frequency = clk_get_rate(emc->clk);
/* clear counters and restart */
writel_relaxed(EMC_PWR_GATHER_CLEAR, emc->regs + EMC_STAT_CONTROL);
writel_relaxed(EMC_PWR_GATHER_ENABLE, emc->regs + EMC_STAT_CONTROL);
return 0;
}
static struct devfreq_dev_profile tegra_emc_devfreq_profile = {
.polling_ms = 30,
.target = tegra_emc_devfreq_target,
.get_dev_status = tegra_emc_devfreq_get_dev_status,
};
static int tegra_emc_devfreq_init(struct tegra_emc *emc)
{
struct devfreq *devfreq;
/*
* PWR_COUNT is 1/2 of PWR_CLOCKS at max, and thus, the up-threshold
* should be less than 50. Secondly, multiple active memory clients
* may cause over 20% of lost clock cycles due to stalls caused by
* competing memory accesses. This means that threshold should be
* set to a less than 30 in order to have a properly working governor.
*/
emc->ondemand_data.upthreshold = 20;
/*
* Reset statistic gathers state, select global bandwidth for the
* statistics collection mode and set clocks counter saturation
* limit to maximum.
*/
writel_relaxed(0x00000000, emc->regs + EMC_STAT_CONTROL);
writel_relaxed(0x00000000, emc->regs + EMC_STAT_LLMC_CONTROL);
writel_relaxed(0xffffffff, emc->regs + EMC_STAT_PWR_CLOCK_LIMIT);
devfreq = devm_devfreq_add_device(emc->dev, &tegra_emc_devfreq_profile,
DEVFREQ_GOV_SIMPLE_ONDEMAND,
&emc->ondemand_data);
if (IS_ERR(devfreq)) {
dev_err(emc->dev, "failed to initialize devfreq: %pe", devfreq);
return PTR_ERR(devfreq);
}
return 0;
}
static int tegra_emc_probe(struct platform_device *pdev)
{
struct device_node *np;
struct tegra_emc *emc;
struct resource *res;
int irq, err;
/* driver has nothing to do in a case of memory timing absence */
if (of_get_child_count(pdev->dev.of_node) == 0) {
dev_info(&pdev->dev,
"EMC device tree node doesn't have memory timings\n");
return 0;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "interrupt not specified\n");
dev_err(&pdev->dev, "please update your device tree\n");
return irq;
}
np = tegra_emc_find_node_by_ram_code(&pdev->dev);
if (!np)
return -EINVAL;
emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
if (!emc) {
of_node_put(np);
if (!emc)
return -ENOMEM;
}
mutex_init(&emc->rate_lock);
emc->clk_nb.notifier_call = tegra_emc_clk_change_notify;
emc->dev = &pdev->dev;
err = tegra_emc_load_timings_from_dt(emc, np);
of_node_put(np);
if (err)
return err;
np = tegra_emc_find_node_by_ram_code(&pdev->dev);
if (np) {
err = tegra_emc_load_timings_from_dt(emc, np);
of_node_put(np);
if (err)
return err;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
emc->regs = devm_ioremap_resource(&pdev->dev, res);
emc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(emc->regs))
return PTR_ERR(emc->regs);
@@ -701,41 +1123,39 @@ static int tegra_emc_probe(struct platform_device *pdev)
err = devm_request_irq(&pdev->dev, irq, tegra_emc_isr, 0,
dev_name(&pdev->dev), emc);
if (err) {
dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err);
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
return err;
}
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
err = tegra_emc_init_clk(emc);
if (err)
return err;
emc->clk = devm_clk_get(&pdev->dev, "emc");
if (IS_ERR(emc->clk)) {
err = PTR_ERR(emc->clk);
dev_err(&pdev->dev, "failed to get emc clock: %d\n", err);
goto unset_cb;
}
err = clk_notifier_register(emc->clk, &emc->clk_nb);
if (err) {
dev_err(&pdev->dev, "failed to register clk notifier: %d\n",
err);
goto unset_cb;
}
err = tegra_emc_opp_table_init(emc);
if (err)
return err;
platform_set_drvdata(pdev, emc);
tegra_emc_rate_requests_init(emc);
tegra_emc_debugfs_init(emc);
tegra_emc_interconnect_init(emc);
tegra_emc_devfreq_init(emc);
/*
* Don't allow the kernel module to be unloaded. Unloading adds some
* extra complexity which doesn't really worth the effort in a case of
* this driver.
*/
try_module_get(THIS_MODULE);
return 0;
unset_cb:
tegra20_clk_set_emc_round_callback(NULL, NULL);
return err;
}
static const struct of_device_id tegra_emc_of_match[] = {
{ .compatible = "nvidia,tegra20-emc", },
{},
};
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);
static struct platform_driver tegra_emc_driver = {
.probe = tegra_emc_probe,
@@ -743,11 +1163,11 @@ static struct platform_driver tegra_emc_driver = {
.name = "tegra20-emc",
.of_match_table = tegra_emc_of_match,
.suppress_bind_attrs = true,
.sync_state = icc_sync_state,
},
};
module_platform_driver(tegra_emc_driver);
static int __init tegra_emc_init(void)
{
return platform_driver_register(&tegra_emc_driver);
}
subsys_initcall(tegra_emc_init);
MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
MODULE_DESCRIPTION("NVIDIA Tegra20 EMC driver");
MODULE_LICENSE("GPL v2");

View File

@@ -3,6 +3,10 @@
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <dt-bindings/memory/tegra20-mc.h>
#include "mc.h"
@@ -280,6 +284,78 @@ static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
.reset_status = tegra20_mc_reset_status,
};
static int tegra20_mc_icc_set(struct icc_node *src, struct icc_node *dst)
{
/*
* It should be possible to tune arbitration knobs here, but the
* default values are known to work well on all devices. Hence
* nothing to do here so far.
*/
return 0;
}
static int tegra20_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
/*
* ISO clients need to reserve extra bandwidth up-front because
* there could be high bandwidth pressure during initial filling
* of the client's FIFO buffers. Secondly, we need to take into
* account impurities of the memory subsystem.
*/
if (tag & TEGRA_MC_ICC_TAG_ISO)
peak_bw = tegra_mc_scale_percents(peak_bw, 300);
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
static struct icc_node_data *
tegra20_mc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data)
{
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
unsigned int i, idx = spec->args[0];
struct icc_node_data *ndata;
struct icc_node *node;
list_for_each_entry(node, &mc->provider.nodes, node_list) {
if (node->id != idx)
continue;
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
if (!ndata)
return ERR_PTR(-ENOMEM);
ndata->node = node;
/* these clients are isochronous by default */
if (strstarts(node->name, "display") ||
strstarts(node->name, "vi"))
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
else
ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
return ndata;
}
for (i = 0; i < mc->soc->num_clients; i++) {
if (mc->soc->clients[i].id == idx)
return ERR_PTR(-EPROBE_DEFER);
}
dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
return ERR_PTR(-EINVAL);
}
static const struct tegra_mc_icc_ops tegra20_mc_icc_ops = {
.xlate_extended = tegra20_mc_of_icc_xlate_extended,
.aggregate = tegra20_mc_icc_aggreate,
.set = tegra20_mc_icc_set,
};
const struct tegra_mc_soc tegra20_mc_soc = {
.clients = tegra20_mc_clients,
.num_clients = ARRAY_SIZE(tegra20_mc_clients),
@@ -290,4 +366,5 @@ const struct tegra_mc_soc tegra20_mc_soc = {
.reset_ops = &tegra20_mc_reset_ops,
.resets = tegra20_mc_resets,
.num_resets = ARRAY_SIZE(tegra20_mc_resets),
.icc_ops = &tegra20_mc_icc_ops,
};

View File

@@ -1828,7 +1828,6 @@ static int tegra210_emc_probe(struct platform_device *pdev)
{
struct thermal_cooling_device *cd;
unsigned long current_rate;
struct platform_device *mc;
struct tegra210_emc *emc;
struct device_node *np;
unsigned int i;
@@ -1846,35 +1845,19 @@ static int tegra210_emc_probe(struct platform_device *pdev)
spin_lock_init(&emc->lock);
emc->dev = &pdev->dev;
np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
if (!np) {
dev_err(&pdev->dev, "could not get memory controller\n");
return -ENOENT;
}
mc = of_find_device_by_node(np);
of_node_put(np);
if (!mc)
return -ENOENT;
emc->mc = platform_get_drvdata(mc);
if (!emc->mc) {
put_device(&mc->dev);
return -EPROBE_DEFER;
}
emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
if (IS_ERR(emc->mc))
return PTR_ERR(emc->mc);
emc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(emc->regs)) {
err = PTR_ERR(emc->regs);
goto put_mc;
}
if (IS_ERR(emc->regs))
return PTR_ERR(emc->regs);
for (i = 0; i < 2; i++) {
emc->channel[i] = devm_platform_ioremap_resource(pdev, 1 + i);
if (IS_ERR(emc->channel[i])) {
err = PTR_ERR(emc->channel[i]);
goto put_mc;
}
if (IS_ERR(emc->channel[i]))
return PTR_ERR(emc->channel[i]);
}
tegra210_emc_detect(emc);
@@ -1884,7 +1867,7 @@ static int tegra210_emc_probe(struct platform_device *pdev)
err = of_reserved_mem_device_init_by_name(emc->dev, np, "nominal");
if (err < 0) {
dev_err(emc->dev, "failed to get nominal EMC table: %d\n", err);
goto put_mc;
return err;
}
err = of_reserved_mem_device_init_by_name(emc->dev, np, "derated");
@@ -2015,8 +1998,7 @@ detach:
tegra210_clk_emc_detach(emc->clk);
release:
of_reserved_mem_device_release(emc->dev);
put_mc:
put_device(emc->mc->dev);
return err;
}
@@ -2027,7 +2009,6 @@ static int tegra210_emc_remove(struct platform_device *pdev)
debugfs_remove_recursive(emc->debugfs.root);
tegra210_clk_emc_detach(emc->clk);
of_reserved_mem_device_release(emc->dev);
put_device(emc->mc->dev);
return 0;
}

View File

@@ -24,7 +24,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2e8,
.shift = 0,
.mask = 0xff,
.def = 0xc2,
.def = 0x1e,
},
}, {
.id = 0x02,
@@ -38,7 +38,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2f4,
.shift = 0,
.mask = 0xff,
.def = 0xc6,
.def = 0x1e,
},
}, {
.id = 0x03,
@@ -52,7 +52,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2e8,
.shift = 16,
.mask = 0xff,
.def = 0x50,
.def = 0x1e,
},
}, {
.id = 0x04,
@@ -66,7 +66,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2f4,
.shift = 16,
.mask = 0xff,
.def = 0x50,
.def = 0x1e,
},
}, {
.id = 0x05,
@@ -80,7 +80,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2ec,
.shift = 0,
.mask = 0xff,
.def = 0x50,
.def = 0x1e,
},
}, {
.id = 0x06,
@@ -94,7 +94,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2f8,
.shift = 0,
.mask = 0xff,
.def = 0x50,
.def = 0x1e,
},
}, {
.id = 0x0e,
@@ -108,7 +108,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2e0,
.shift = 0,
.mask = 0xff,
.def = 0x13,
.def = 0x2e,
},
}, {
.id = 0x0f,
@@ -136,7 +136,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2f0,
.shift = 0,
.mask = 0xff,
.def = 0x50,
.def = 0x1e,
},
}, {
.id = 0x11,
@@ -150,7 +150,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2fc,
.shift = 0,
.mask = 0xff,
.def = 0x50,
.def = 0x1e,
},
}, {
.id = 0x15,
@@ -380,7 +380,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x350,
.shift = 16,
.mask = 0xff,
.def = 0x65,
.def = 0x80,
},
}, {
.id = 0x44,
@@ -620,7 +620,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x2f0,
.shift = 16,
.mask = 0xff,
.def = 0x50,
.def = 0x1e,
},
}, {
.id = 0x60,
@@ -648,7 +648,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x3bc,
.shift = 0,
.mask = 0xff,
.def = 0x49,
.def = 0x5a,
},
}, {
.id = 0x62,
@@ -676,7 +676,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x3c4,
.shift = 0,
.mask = 0xff,
.def = 0x49,
.def = 0x5a,
},
}, {
.id = 0x64,
@@ -897,7 +897,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.bit = 1,
},
.la = {
.reg = 0xb98,
.reg = 0x3e0,
.shift = 16,
.mask = 0xff,
.def = 0x80,
@@ -956,7 +956,7 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
.reg = 0x3ec,
.shift = 16,
.mask = 0xff,
.def = 0xff,
.def = 0x80,
},
}, {
.id = 0x86,
@@ -1020,35 +1020,45 @@ static const struct tegra_mc_client tegra210_mc_clients[] = {
};
static const struct tegra_smmu_swgroup tegra210_swgroups[] = {
{ .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 },
{ .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 },
{ .name = "afi", .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 },
{ .name = "avpc", .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c },
{ .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 },
{ .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 },
{ .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 },
{ .name = "hc", .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 },
{ .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 },
{ .name = "isp2", .swgroup = TEGRA_SWGROUP_ISP2, .reg = 0x258 },
{ .name = "nvenc", .swgroup = TEGRA_SWGROUP_NVENC, .reg = 0x264 },
{ .name = "nv", .swgroup = TEGRA_SWGROUP_NV, .reg = 0x268 },
{ .name = "nv2", .swgroup = TEGRA_SWGROUP_NV2, .reg = 0x26c },
{ .name = "ppcs", .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 },
{ .name = "sata", .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x274 },
{ .name = "isp2", .swgroup = TEGRA_SWGROUP_ISP2, .reg = 0x258 },
{ .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 },
{ .name = "vic", .swgroup = TEGRA_SWGROUP_VIC, .reg = 0x284 },
{ .name = "xusb_host", .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 },
{ .name = "xusb_dev", .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c },
{ .name = "isp2b", .swgroup = TEGRA_SWGROUP_ISP2B, .reg = 0xaa4 },
{ .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 },
{ .name = "a9avp", .swgroup = TEGRA_SWGROUP_A9AVP, .reg = 0x290 },
{ .name = "gpu", .swgroup = TEGRA_SWGROUP_GPU, .reg = 0xaac },
{ .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 },
{ .name = "ppcs1", .swgroup = TEGRA_SWGROUP_PPCS1, .reg = 0x298 },
{ .name = "dc1", .swgroup = TEGRA_SWGROUP_DC1, .reg = 0xa88 },
{ .name = "sdmmc1a", .swgroup = TEGRA_SWGROUP_SDMMC1A, .reg = 0xa94 },
{ .name = "sdmmc2a", .swgroup = TEGRA_SWGROUP_SDMMC2A, .reg = 0xa98 },
{ .name = "sdmmc3a", .swgroup = TEGRA_SWGROUP_SDMMC3A, .reg = 0xa9c },
{ .name = "sdmmc4a", .swgroup = TEGRA_SWGROUP_SDMMC4A, .reg = 0xaa0 },
{ .name = "vic", .swgroup = TEGRA_SWGROUP_VIC, .reg = 0x284 },
{ .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 },
{ .name = "isp2b", .swgroup = TEGRA_SWGROUP_ISP2B, .reg = 0xaa4 },
{ .name = "gpu", .swgroup = TEGRA_SWGROUP_GPU, .reg = 0xaac },
{ .name = "ppcs2", .swgroup = TEGRA_SWGROUP_PPCS2, .reg = 0xab0 },
{ .name = "nvdec", .swgroup = TEGRA_SWGROUP_NVDEC, .reg = 0xab4 },
{ .name = "ape", .swgroup = TEGRA_SWGROUP_APE, .reg = 0xab8 },
{ .name = "nvjpg", .swgroup = TEGRA_SWGROUP_NVJPG, .reg = 0xac0 },
{ .name = "se", .swgroup = TEGRA_SWGROUP_SE, .reg = 0xabc },
{ .name = "nvjpg", .swgroup = TEGRA_SWGROUP_NVJPG, .reg = 0xac0 },
{ .name = "hc1", .swgroup = TEGRA_SWGROUP_HC1, .reg = 0xac4 },
{ .name = "se1", .swgroup = TEGRA_SWGROUP_SE1, .reg = 0xac8 },
{ .name = "axiap", .swgroup = TEGRA_SWGROUP_AXIAP, .reg = 0xacc },
{ .name = "etr", .swgroup = TEGRA_SWGROUP_ETR, .reg = 0xad0 },
{ .name = "tsecb", .swgroup = TEGRA_SWGROUP_TSECB, .reg = 0xad4 },
{ .name = "tsec1", .swgroup = TEGRA_SWGROUP_TSEC1, .reg = 0xad8 },
{ .name = "tsecb1", .swgroup = TEGRA_SWGROUP_TSECB1, .reg = 0xadc },
{ .name = "nvdec1", .swgroup = TEGRA_SWGROUP_NVDEC1, .reg = 0xae0 },
};
static const unsigned int tegra210_group_display[] = {

View File

@@ -14,16 +14,21 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interconnect-provider.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/sort.h>
#include <linux/types.h>
#include <soc/tegra/common.h>
#include <soc/tegra/fuse.h>
#include "mc.h"
@@ -323,9 +328,21 @@ struct emc_timing {
bool emc_cfg_dyn_self_ref;
};
enum emc_rate_request_type {
EMC_RATE_DEBUG,
EMC_RATE_ICC,
EMC_RATE_TYPE_MAX,
};
struct emc_rate_request {
unsigned long min_rate;
unsigned long max_rate;
};
struct tegra_emc {
struct device *dev;
struct tegra_mc *mc;
struct icc_provider provider;
struct notifier_block clk_nb;
struct clk *clk;
void __iomem *regs;
@@ -352,6 +369,15 @@ struct tegra_emc {
unsigned long min_rate;
unsigned long max_rate;
} debugfs;
/*
* There are multiple sources in the EMC driver which could request
* a min/max clock rate, these rates are contained in this array.
*/
struct emc_rate_request requested_rate[EMC_RATE_TYPE_MAX];
/* protect shared rate-change code path */
struct mutex rate_lock;
};
static int emc_seq_update_timing(struct tegra_emc *emc)
@@ -988,6 +1014,11 @@ static struct device_node *emc_find_node_by_ram_code(struct device *dev)
u32 value, ram_code;
int err;
if (of_get_child_count(dev->of_node) == 0) {
dev_info(dev, "device-tree doesn't have memory timings\n");
return NULL;
}
ram_code = tegra_read_ram_code();
for_each_child_of_node(dev->of_node, np) {
@@ -1057,6 +1088,9 @@ static long emc_round_rate(unsigned long rate,
struct tegra_emc *emc = arg;
unsigned int i;
if (!emc->num_timings)
return clk_get_rate(emc->clk);
min_rate = min(min_rate, emc->timings[emc->num_timings - 1].rate);
for (i = 0; i < emc->num_timings; i++) {
@@ -1086,6 +1120,83 @@ static long emc_round_rate(unsigned long rate,
return timing->rate;
}
static void tegra_emc_rate_requests_init(struct tegra_emc *emc)
{
unsigned int i;
for (i = 0; i < EMC_RATE_TYPE_MAX; i++) {
emc->requested_rate[i].min_rate = 0;
emc->requested_rate[i].max_rate = ULONG_MAX;
}
}
static int emc_request_rate(struct tegra_emc *emc,
unsigned long new_min_rate,
unsigned long new_max_rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = emc->requested_rate;
unsigned long min_rate = 0, max_rate = ULONG_MAX;
unsigned int i;
int err;
/* select minimum and maximum rates among the requested rates */
for (i = 0; i < EMC_RATE_TYPE_MAX; i++, req++) {
if (i == type) {
min_rate = max(new_min_rate, min_rate);
max_rate = min(new_max_rate, max_rate);
} else {
min_rate = max(req->min_rate, min_rate);
max_rate = min(req->max_rate, max_rate);
}
}
if (min_rate > max_rate) {
dev_err_ratelimited(emc->dev, "%s: type %u: out of range: %lu %lu\n",
__func__, type, min_rate, max_rate);
return -ERANGE;
}
/*
* EMC rate-changes should go via OPP API because it manages voltage
* changes.
*/
err = dev_pm_opp_set_rate(emc->dev, min_rate);
if (err)
return err;
emc->requested_rate[type].min_rate = new_min_rate;
emc->requested_rate[type].max_rate = new_max_rate;
return 0;
}
static int emc_set_min_rate(struct tegra_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, rate, req->max_rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
static int emc_set_max_rate(struct tegra_emc *emc, unsigned long rate,
enum emc_rate_request_type type)
{
struct emc_rate_request *req = &emc->requested_rate[type];
int ret;
mutex_lock(&emc->rate_lock);
ret = emc_request_rate(emc, req->min_rate, rate, type);
mutex_unlock(&emc->rate_lock);
return ret;
}
/*
* debugfs interface
*
@@ -1169,7 +1280,7 @@ static int tegra_emc_debug_min_rate_set(void *data, u64 rate)
if (!tegra_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_min_rate(emc->clk, rate);
err = emc_set_min_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -1199,7 +1310,7 @@ static int tegra_emc_debug_max_rate_set(void *data, u64 rate)
if (!tegra_emc_validate_rate(emc, rate))
return -EINVAL;
err = clk_set_max_rate(emc->clk, rate);
err = emc_set_max_rate(emc, rate, EMC_RATE_DEBUG);
if (err < 0)
return err;
@@ -1256,51 +1367,239 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc)
emc, &tegra_emc_debug_max_rate_fops);
}
static inline struct tegra_emc *
to_tegra_emc_provider(struct icc_provider *provider)
{
return container_of(provider, struct tegra_emc, provider);
}
static struct icc_node_data *
emc_of_icc_xlate_extended(struct of_phandle_args *spec, void *data)
{
struct icc_provider *provider = data;
struct icc_node_data *ndata;
struct icc_node *node;
/* External Memory is the only possible ICC route */
list_for_each_entry(node, &provider->nodes, node_list) {
if (node->id != TEGRA_ICC_EMEM)
continue;
ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
if (!ndata)
return ERR_PTR(-ENOMEM);
/*
* SRC and DST nodes should have matching TAG in order to have
* it set by default for a requested path.
*/
ndata->tag = TEGRA_MC_ICC_TAG_ISO;
ndata->node = node;
return ndata;
}
return ERR_PTR(-EPROBE_DEFER);
}
static int emc_icc_set(struct icc_node *src, struct icc_node *dst)
{
struct tegra_emc *emc = to_tegra_emc_provider(dst->provider);
unsigned long long peak_bw = icc_units_to_bps(dst->peak_bw);
unsigned long long avg_bw = icc_units_to_bps(dst->avg_bw);
unsigned long long rate = max(avg_bw, peak_bw);
const unsigned int dram_data_bus_width_bytes = 4;
const unsigned int ddr = 2;
int err;
/*
* Tegra30 EMC runs on a clock rate of SDRAM bus. This means that
* EMC clock rate is twice smaller than the peak data rate because
* data is sampled on both EMC clock edges.
*/
do_div(rate, ddr * dram_data_bus_width_bytes);
rate = min_t(u64, rate, U32_MAX);
err = emc_set_min_rate(emc, rate, EMC_RATE_ICC);
if (err)
return err;
return 0;
}
static int tegra_emc_interconnect_init(struct tegra_emc *emc)
{
const struct tegra_mc_soc *soc = emc->mc->soc;
struct icc_node *node;
int err;
emc->provider.dev = emc->dev;
emc->provider.set = emc_icc_set;
emc->provider.data = &emc->provider;
emc->provider.aggregate = soc->icc_ops->aggregate;
emc->provider.xlate_extended = emc_of_icc_xlate_extended;
err = icc_provider_add(&emc->provider);
if (err)
goto err_msg;
/* create External Memory Controller node */
node = icc_node_create(TEGRA_ICC_EMC);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto del_provider;
}
node->name = "External Memory Controller";
icc_node_add(node, &emc->provider);
/* link External Memory Controller to External Memory (DRAM) */
err = icc_link_create(node, TEGRA_ICC_EMEM);
if (err)
goto remove_nodes;
/* create External Memory node */
node = icc_node_create(TEGRA_ICC_EMEM);
if (IS_ERR(node)) {
err = PTR_ERR(node);
goto remove_nodes;
}
node->name = "External Memory (DRAM)";
icc_node_add(node, &emc->provider);
return 0;
remove_nodes:
icc_nodes_remove(&emc->provider);
del_provider:
icc_provider_del(&emc->provider);
err_msg:
dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
return err;
}
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
{
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
struct opp_table *clk_opp_table, *hw_opp_table;
int err;
clk_opp_table = dev_pm_opp_set_clkname(emc->dev, NULL);
err = PTR_ERR_OR_ZERO(clk_opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP clk: %d\n", err);
return err;
}
hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
err = PTR_ERR_OR_ZERO(hw_opp_table);
if (err) {
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
goto put_clk_table;
}
err = dev_pm_opp_of_add_table(emc->dev);
if (err) {
if (err == -ENODEV)
dev_err(emc->dev, "OPP table not found, please update your device tree\n");
else
dev_err(emc->dev, "failed to add OPP table: %d\n", err);
goto put_hw_table;
}
dev_info(emc->dev, "OPP HW ver. 0x%x, current clock rate %lu MHz\n",
hw_version, clk_get_rate(emc->clk) / 1000000);
/* first dummy rate-set initializes voltage state */
err = dev_pm_opp_set_rate(emc->dev, clk_get_rate(emc->clk));
if (err) {
dev_err(emc->dev, "failed to initialize OPP clock: %d\n", err);
goto remove_table;
}
return 0;
remove_table:
dev_pm_opp_of_remove_table(emc->dev);
put_hw_table:
dev_pm_opp_put_supported_hw(hw_opp_table);
put_clk_table:
dev_pm_opp_put_clkname(clk_opp_table);
return err;
}
static void devm_tegra_emc_unset_callback(void *data)
{
tegra20_clk_set_emc_round_callback(NULL, NULL);
}
static void devm_tegra_emc_unreg_clk_notifier(void *data)
{
struct tegra_emc *emc = data;
clk_notifier_unregister(emc->clk, &emc->clk_nb);
}
static int tegra_emc_init_clk(struct tegra_emc *emc)
{
int err;
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
err = devm_add_action_or_reset(emc->dev, devm_tegra_emc_unset_callback,
NULL);
if (err)
return err;
emc->clk = devm_clk_get(emc->dev, NULL);
if (IS_ERR(emc->clk)) {
dev_err(emc->dev, "failed to get EMC clock: %pe\n", emc->clk);
return PTR_ERR(emc->clk);
}
err = clk_notifier_register(emc->clk, &emc->clk_nb);
if (err) {
dev_err(emc->dev, "failed to register clk notifier: %d\n", err);
return err;
}
err = devm_add_action_or_reset(emc->dev,
devm_tegra_emc_unreg_clk_notifier, emc);
if (err)
return err;
return 0;
}
static int tegra_emc_probe(struct platform_device *pdev)
{
struct platform_device *mc;
struct device_node *np;
struct tegra_emc *emc;
int err;
if (of_get_child_count(pdev->dev.of_node) == 0) {
dev_info(&pdev->dev,
"device-tree node doesn't have memory timings\n");
return -ENODEV;
}
np = of_parse_phandle(pdev->dev.of_node, "nvidia,memory-controller", 0);
if (!np) {
dev_err(&pdev->dev, "could not get memory controller node\n");
return -ENOENT;
}
mc = of_find_device_by_node(np);
of_node_put(np);
if (!mc)
return -ENOENT;
np = emc_find_node_by_ram_code(&pdev->dev);
if (!np)
return -EINVAL;
emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
if (!emc) {
of_node_put(np);
if (!emc)
return -ENOMEM;
}
emc->mc = platform_get_drvdata(mc);
if (!emc->mc)
return -EPROBE_DEFER;
emc->mc = devm_tegra_memory_controller_get(&pdev->dev);
if (IS_ERR(emc->mc))
return PTR_ERR(emc->mc);
mutex_init(&emc->rate_lock);
emc->clk_nb.notifier_call = emc_clk_change_notify;
emc->dev = &pdev->dev;
err = emc_load_timings_from_dt(emc, np);
of_node_put(np);
if (err)
return err;
np = emc_find_node_by_ram_code(&pdev->dev);
if (np) {
err = emc_load_timings_from_dt(emc, np);
of_node_put(np);
if (err)
return err;
}
emc->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(emc->regs))
@@ -1311,10 +1610,9 @@ static int tegra_emc_probe(struct platform_device *pdev)
return err;
err = platform_get_irq(pdev, 0);
if (err < 0) {
dev_err(&pdev->dev, "interrupt not specified: %d\n", err);
if (err < 0)
return err;
}
emc->irq = err;
err = devm_request_irq(&pdev->dev, emc->irq, tegra_emc_isr, 0,
@@ -1324,31 +1622,27 @@ static int tegra_emc_probe(struct platform_device *pdev)
return err;
}
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
err = tegra_emc_init_clk(emc);
if (err)
return err;
emc->clk = devm_clk_get(&pdev->dev, "emc");
if (IS_ERR(emc->clk)) {
err = PTR_ERR(emc->clk);
dev_err(&pdev->dev, "failed to get emc clock: %d\n", err);
goto unset_cb;
}
err = clk_notifier_register(emc->clk, &emc->clk_nb);
if (err) {
dev_err(&pdev->dev, "failed to register clk notifier: %d\n",
err);
goto unset_cb;
}
err = tegra_emc_opp_table_init(emc);
if (err)
return err;
platform_set_drvdata(pdev, emc);
tegra_emc_rate_requests_init(emc);
tegra_emc_debugfs_init(emc);
tegra_emc_interconnect_init(emc);
/*
* Don't allow the kernel module to be unloaded. Unloading adds some
* extra complexity which doesn't really worth the effort in a case of
* this driver.
*/
try_module_get(THIS_MODULE);
return 0;
unset_cb:
tegra20_clk_set_emc_round_callback(NULL, NULL);
return err;
}
static int tegra_emc_suspend(struct device *dev)
@@ -1393,6 +1687,7 @@ static const struct of_device_id tegra_emc_of_match[] = {
{ .compatible = "nvidia,tegra30-emc", },
{},
};
MODULE_DEVICE_TABLE(of, tegra_emc_of_match);
static struct platform_driver tegra_emc_driver = {
.probe = tegra_emc_probe,
@@ -1401,11 +1696,11 @@ static struct platform_driver tegra_emc_driver = {
.of_match_table = tegra_emc_of_match,
.pm = &tegra_emc_pm_ops,
.suppress_bind_attrs = true,
.sync_state = icc_sync_state,
},
};
module_platform_driver(tegra_emc_driver);
static int __init tegra_emc_init(void)
{
return platform_driver_register(&tegra_emc_driver);
}
subsys_initcall(tegra_emc_init);
MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
MODULE_DESCRIPTION("NVIDIA Tegra30 EMC driver");
MODULE_LICENSE("GPL v2");

Some files were not shown because too many files have changed in this diff Show More