mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -23,6 +23,7 @@ properties:
|
||||
enum:
|
||||
- qcom,sc7180-llcc
|
||||
- qcom,sdm845-llcc
|
||||
- qcom,sm8150-llcc
|
||||
|
||||
reg:
|
||||
items:
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
58
Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
Normal file
58
Documentation/devicetree/bindings/soc/mediatek/devapc.yaml
Normal 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";
|
||||
};
|
||||
@@ -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>;
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
|
||||
==============================
|
||||
The Second Extended Filesystem
|
||||
==============================
|
||||
|
||||
|
||||
@@ -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
|
||||
----------------------------
|
||||
|
||||
|
||||
@@ -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] = {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -238,7 +238,6 @@
|
||||
|
||||
&gpmc {
|
||||
compatible = "ti,am3352-gpmc";
|
||||
ti,hwmods = "gpmc";
|
||||
status = "okay";
|
||||
gpmc,num-waitpins = <2>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 },
|
||||
};
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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" },
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user