ARM: soc: TI driver updates for v5.10
Consist of: - Add Ring accelerator support for AM65x - Add TI PRUSS platform driver and enable it on available platforms - Extend PRUSS driver for CORECLK_MUX/IEPCLK_MUX support - UDMA rx ring pair fix - Add socinfo entry for J7200 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIbBAABAgAGBQJfaBQeAAoJEHJsHOdBp5c/K1oP+Or/n3/TMOGoAKQL+2m2hhH+ c6fVzGOWEI4AkToGiE9n/EyDvh7BAvPG+j0f7SxTPUEmgbweJ2Lc6NNx+c+dssRA g6zQVzHphtGLla3u5NDOI8vQ66vw6hMY48zSRwbUuE+ee4VbUjmwTYgDN42rawQs N1Iq+KN2FzzYmT3lnJp0jDqZjKicCJ6GjYWZVlEJ6i6Yn7Rq2F1m4ilLoGejN15x bEr5IItF3kmLAuCbjgDzanSYv5ni20iGfVniNynQcTqsjzRQnJqpY2+XgWhV/nZo tT45m6AU/D7l/fbDNXecQ9X4AxLuL+JUb1nM0DcIWWPUDJauAMLzC5+IX5gg/f79 FUoUWpyxNVUuis3ZLAhzhe8uVZEcpD5Pwp7LCKr7QbBu84eCol3cUGCIvdvaAaQM 9eDBORUhkd8XdMtHDhPqpvYxUeKmlqSLHabWmEtdGVRvzJElrxF6AyUDD7ToDHiv x9wuC+bZi63gL1xukinGtTUic9vaytGrUeElslhTUGo8upZKc2XahTE0ce8e8ij5 9Vtnr7a8vQR0AanRa0yDx40IBC9w8wlnfFSNnVbQ2SOhE8YiuT0H8p2unWA6Oz4K tB+vUk+rGAZ5fnhbpSQRKWoTUbiKqU7S+lQ8gUFVzOsDy9DzoD9L+jmw1xEFUIjd 4cqaaQ9WbnBytGFmxgw= =s8sI -----END PGP SIGNATURE----- Merge tag 'drivers_soc_for_5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone into arm/drivers ARM: soc: TI driver updates for v5.10 Consist of: - Add Ring accelerator support for AM65x - Add TI PRUSS platform driver and enable it on available platforms - Extend PRUSS driver for CORECLK_MUX/IEPCLK_MUX support - UDMA rx ring pair fix - Add socinfo entry for J7200 * tag 'drivers_soc_for_5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone: Add missing '#' to fix schema errors: soc: ti: Convert to DEFINE_SHOW_ATTRIBUTE dmaengine: ti: k3-udma-glue: Fix parameters for rx ring pair request soc: ti: k3-socinfo: Add entry for J7200 soc: ti: pruss: support CORECLK_MUX and IEPCLK_MUX dt-bindings: soc: ti: Update TI PRUSS bindings regarding clock-muxes firmware: ti_sci: allow frequency change for disabled clocks by default soc: ti: ti_sci_pm_domains: switch to use multiple genpds instead of one soc: ti: pruss: Enable support for ICSSG subsystems on K3 J721E SoCs soc: ti: pruss: Enable support for ICSSG subsystems on K3 AM65x SoCs soc: ti: pruss: Add support for PRU-ICSS subsystems on 66AK2G SoC soc: ti: pruss: Add support for PRU-ICSS subsystems on AM57xx SoCs soc: ti: pruss: Add support for PRU-ICSSs on AM437x SoCs soc: ti: pruss: Add a platform driver for PRUSS in TI SoCs dt-bindings: soc: ti: Add TI PRUSS bindings bindings: soc: ti: soc: ringacc: remove ti,dma-ring-reset-quirk soc: ti: k3: ringacc: add am65x sr2.0 support Link: https://lore.kernel.org/r/1600656828-29267-1-git-send-email-santosh.shilimkar@oracle.com Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
aa78dd167e
@ -62,11 +62,6 @@ properties:
|
|||||||
$ref: /schemas/types.yaml#/definitions/uint32
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
description: TI-SCI device id of the ring accelerator
|
description: TI-SCI device id of the ring accelerator
|
||||||
|
|
||||||
ti,dma-ring-reset-quirk:
|
|
||||||
$ref: /schemas/types.yaml#definitions/flag
|
|
||||||
description: |
|
|
||||||
enable ringacc/udma ring state interoperability issue software w/a
|
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
@ -94,7 +89,6 @@ examples:
|
|||||||
reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
|
reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
|
||||||
ti,num-rings = <818>;
|
ti,num-rings = <818>;
|
||||||
ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */
|
ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */
|
||||||
ti,dma-ring-reset-quirk;
|
|
||||||
ti,sci = <&dmsc>;
|
ti,sci = <&dmsc>;
|
||||||
ti,sci-dev-id = <187>;
|
ti,sci-dev-id = <187>;
|
||||||
msi-parent = <&inta_main_udmass>;
|
msi-parent = <&inta_main_udmass>;
|
||||||
|
439
Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
Normal file
439
Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
Normal file
@ -0,0 +1,439 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/soc/ti/ti,pruss.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: |+
|
||||||
|
TI Programmable Real-Time Unit and Industrial Communication Subsystem
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Suman Anna <s-anna@ti.com>
|
||||||
|
|
||||||
|
description: |+
|
||||||
|
|
||||||
|
The Programmable Real-Time Unit and Industrial Communication Subsystem
|
||||||
|
(PRU-ICSS a.k.a. PRUSS) is present on various TI SoCs such as AM335x, AM437x,
|
||||||
|
Keystone 66AK2G, OMAP-L138/DA850 etc. A PRUSS consists of dual 32-bit RISC
|
||||||
|
cores (Programmable Real-Time Units, or PRUs), shared RAM, data and
|
||||||
|
instruction RAMs, some internal peripheral modules to facilitate industrial
|
||||||
|
communication, and an interrupt controller.
|
||||||
|
|
||||||
|
The programmable nature of the PRUs provide flexibility to implement custom
|
||||||
|
peripheral interfaces, fast real-time responses, or specialized data handling.
|
||||||
|
The common peripheral modules include the following,
|
||||||
|
- an Ethernet MII_RT module with two MII ports
|
||||||
|
- an MDIO port to control external Ethernet PHYs
|
||||||
|
- an Industrial Ethernet Peripheral (IEP) to manage/generate Industrial
|
||||||
|
Ethernet functions
|
||||||
|
- an Enhanced Capture Module (eCAP)
|
||||||
|
- an Industrial Ethernet Timer with 7/9 capture and 16 compare events
|
||||||
|
- a 16550-compatible UART to support PROFIBUS
|
||||||
|
- Enhanced GPIO with async capture and serial support
|
||||||
|
|
||||||
|
A PRU-ICSS subsystem can have up to three shared data memories. A PRU core
|
||||||
|
acts on a primary Data RAM (there are usually 2 Data RAMs) at its address
|
||||||
|
0x0, but also has access to a secondary Data RAM (primary to the other PRU
|
||||||
|
core) at its address 0x2000. A shared Data RAM, if present, can be accessed
|
||||||
|
by both the PRU cores. The Interrupt Controller (INTC) and a CFG module are
|
||||||
|
common to both the PRU cores. Each PRU core also has a private instruction
|
||||||
|
RAM, and specific register spaces for Control and Debug functionalities.
|
||||||
|
|
||||||
|
Various sub-modules within a PRU-ICSS subsystem are represented as individual
|
||||||
|
nodes and are defined using a parent-child hierarchy depending on their
|
||||||
|
integration within the IP and the SoC. These nodes are described in the
|
||||||
|
following sections.
|
||||||
|
|
||||||
|
|
||||||
|
PRU-ICSS Node
|
||||||
|
==============
|
||||||
|
Each PRU-ICSS instance is represented as its own node with the individual PRU
|
||||||
|
processor cores, the memories node, an INTC node and an MDIO node represented
|
||||||
|
as child nodes within this PRUSS node. This node shall be a child of the
|
||||||
|
corresponding interconnect bus nodes or target-module nodes.
|
||||||
|
|
||||||
|
See ../../mfd/syscon.yaml for generic SysCon binding details.
|
||||||
|
|
||||||
|
|
||||||
|
properties:
|
||||||
|
$nodename:
|
||||||
|
pattern: "^(pruss|icssg)@[0-9a-f]+$"
|
||||||
|
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- ti,am3356-pruss # for AM335x SoC family
|
||||||
|
- ti,am4376-pruss0 # for AM437x SoC family and PRUSS unit 0
|
||||||
|
- ti,am4376-pruss1 # for AM437x SoC family and PRUSS unit 1
|
||||||
|
- ti,am5728-pruss # for AM57xx SoC family
|
||||||
|
- ti,k2g-pruss # for 66AK2G SoC family
|
||||||
|
- ti,am654-icssg # for K3 AM65x SoC family
|
||||||
|
- ti,j721e-icssg # for K3 J721E SoC family
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
"#address-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
"#size-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
ranges:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
description: |
|
||||||
|
This property is as per sci-pm-domain.txt.
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
|
||||||
|
memories@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
The various Data RAMs within a single PRU-ICSS unit are represented as a
|
||||||
|
single node with the name 'memories'.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
minItems: 2 # On AM437x one of two PRUSS units don't contain Shared RAM.
|
||||||
|
maxItems: 3
|
||||||
|
items:
|
||||||
|
- description: Address and size of the Data RAM0.
|
||||||
|
- description: Address and size of the Data RAM1.
|
||||||
|
- description: |
|
||||||
|
Address and size of the Shared Data RAM. Note that on AM437x one
|
||||||
|
of two PRUSS units don't contain Shared RAM, while the second one
|
||||||
|
has it.
|
||||||
|
|
||||||
|
reg-names:
|
||||||
|
minItems: 2
|
||||||
|
maxItems: 3
|
||||||
|
items:
|
||||||
|
- const: dram0
|
||||||
|
- const: dram1
|
||||||
|
- const: shrdram2
|
||||||
|
|
||||||
|
required:
|
||||||
|
- reg
|
||||||
|
- reg-names
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
cfg@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
PRU-ICSS configuration space. CFG sub-module represented as a SysCon.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: ti,pruss-cfg
|
||||||
|
- const: syscon
|
||||||
|
|
||||||
|
"#address-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
"#size-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ranges:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
"#address-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
"#size-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
coreclk-mux@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
This is applicable only for ICSSG (K3 SoCs). The ICSSG modules
|
||||||
|
core clock can be set to one of the 2 sources: ICSSG_CORE_CLK or
|
||||||
|
ICSSG_ICLK. This node models this clock mux and should have the
|
||||||
|
name "coreclk-mux".
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
'#clock-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: ICSSG_CORE Clock
|
||||||
|
- description: ICSSG_ICLK Clock
|
||||||
|
|
||||||
|
assigned-clocks:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
assigned-clock-parents:
|
||||||
|
maxItems: 1
|
||||||
|
description: |
|
||||||
|
Standard assigned-clocks-parents definition used for selecting
|
||||||
|
mux parent (one of the mux input).
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- clocks
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
iepclk-mux@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
The IEP module can get its clock from 2 sources: ICSSG_IEP_CLK or
|
||||||
|
CORE_CLK (OCP_CLK in older SoCs). This node models this clock
|
||||||
|
mux and should have the name "iepclk-mux".
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
'#clock-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: ICSSG_IEP Clock
|
||||||
|
- description: Core Clock (OCP Clock in older SoCs)
|
||||||
|
|
||||||
|
assigned-clocks:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
assigned-clock-parents:
|
||||||
|
maxItems: 1
|
||||||
|
description: |
|
||||||
|
Standard assigned-clocks-parents definition used for selecting
|
||||||
|
mux parent (one of the mux input).
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- clocks
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
iep@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
Industrial Ethernet Peripheral to manage/generate Industrial Ethernet
|
||||||
|
functions such as time stamping. Each PRUSS has either 1 IEP (on AM335x,
|
||||||
|
AM437x, AM57xx & 66AK2G SoCs) or 2 IEPs (on K3 AM65x & J721E SoCs ). IEP
|
||||||
|
is used for creating PTP clocks and generating PPS signals.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
mii-rt@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
Real-Time Ethernet to support multiple industrial communication protocols.
|
||||||
|
MII-RT sub-module represented as a SysCon.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: ti,pruss-mii
|
||||||
|
- const: syscon
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
mii-g-rt@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
The Real-time Media Independent Interface to support multiple industrial
|
||||||
|
communication protocols (G stands for Gigabit). MII-G-RT sub-module
|
||||||
|
represented as a SysCon.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: ti,pruss-mii-g
|
||||||
|
- const: syscon
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
interrupt-controller@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
PRUSS INTC Node. Each PRUSS has a single interrupt controller instance
|
||||||
|
that is common to all the PRU cores. This should be represented as an
|
||||||
|
interrupt-controller node.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
mdio@[a-f0-9]+$:
|
||||||
|
description: |
|
||||||
|
MDIO Node. Each PRUSS has an MDIO module that can be used to control
|
||||||
|
external PHYs. The MDIO module used within the PRU-ICSS is an instance of
|
||||||
|
the MDIO Controller used in TI Davinci SoCs.
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/net/ti,davinci-mdio.yaml#
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
"^(pru|rtu|txpru)@[0-9a-f]+$":
|
||||||
|
description: |
|
||||||
|
PRU Node. Each PRUSS has dual PRU cores, each represented as a RemoteProc
|
||||||
|
device through a PRU child node each. Each node can optionally be rendered
|
||||||
|
inactive by using the standard DT string property, "status". The ICSSG IP
|
||||||
|
present on K3 SoCs have additional auxiliary PRU cores with slightly
|
||||||
|
different IP integration.
|
||||||
|
|
||||||
|
type: object
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- ranges
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
# Due to inability of correctly verifying sub-nodes with an @address through
|
||||||
|
# the "required" list, the required sub-nodes below are commented out for now.
|
||||||
|
|
||||||
|
#required:
|
||||||
|
# - memories
|
||||||
|
# - interrupt-controller
|
||||||
|
# - pru
|
||||||
|
|
||||||
|
if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- ti,k2g-pruss
|
||||||
|
- ti,am654-icssg
|
||||||
|
- ti,j721e-icssg
|
||||||
|
then:
|
||||||
|
required:
|
||||||
|
- power-domains
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
|
||||||
|
/* Example 1 AM33xx PRU-ICSS */
|
||||||
|
pruss: pruss@0 {
|
||||||
|
compatible = "ti,am3356-pruss";
|
||||||
|
reg = <0x0 0x80000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
pruss_mem: memories@0 {
|
||||||
|
reg = <0x0 0x2000>,
|
||||||
|
<0x2000 0x2000>,
|
||||||
|
<0x10000 0x3000>;
|
||||||
|
reg-names = "dram0", "dram1", "shrdram2";
|
||||||
|
};
|
||||||
|
|
||||||
|
pruss_cfg: cfg@26000 {
|
||||||
|
compatible = "ti,pruss-cfg", "syscon";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
reg = <0x26000 0x2000>;
|
||||||
|
ranges = <0x00 0x26000 0x2000>;
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
pruss_iepclk_mux: iepclk-mux@30 {
|
||||||
|
reg = <0x30>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clocks = <&l3_gclk>, /* icss_iep */
|
||||||
|
<&pruss_ocp_gclk>; /* icss_ocp */
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pruss_mii_rt: mii-rt@32000 {
|
||||||
|
compatible = "ti,pruss-mii", "syscon";
|
||||||
|
reg = <0x32000 0x58>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pruss_mdio: mdio@32400 {
|
||||||
|
compatible = "ti,davinci_mdio";
|
||||||
|
reg = <0x32400 0x90>;
|
||||||
|
clocks = <&dpll_core_m4_ck>;
|
||||||
|
clock-names = "fck";
|
||||||
|
bus_freq = <1000000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
- |
|
||||||
|
|
||||||
|
/* Example 2 AM43xx PRU-ICSS with PRUSS1 node */
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
pruss1: pruss@0 {
|
||||||
|
compatible = "ti,am4376-pruss1";
|
||||||
|
reg = <0x0 0x40000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
pruss1_mem: memories@0 {
|
||||||
|
reg = <0x0 0x2000>,
|
||||||
|
<0x2000 0x2000>,
|
||||||
|
<0x10000 0x8000>;
|
||||||
|
reg-names = "dram0", "dram1", "shrdram2";
|
||||||
|
};
|
||||||
|
|
||||||
|
pruss1_cfg: cfg@26000 {
|
||||||
|
compatible = "ti,pruss-cfg", "syscon";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
reg = <0x26000 0x2000>;
|
||||||
|
ranges = <0x00 0x26000 0x2000>;
|
||||||
|
|
||||||
|
clocks {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
pruss1_iepclk_mux: iepclk-mux@30 {
|
||||||
|
reg = <0x30>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clocks = <&sysclk_div>, /* icss_iep */
|
||||||
|
<&pruss_ocp_gclk>; /* icss_ocp */
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pruss1_mii_rt: mii-rt@32000 {
|
||||||
|
compatible = "ti,pruss-mii", "syscon";
|
||||||
|
reg = <0x32000 0x58>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pruss1_mdio: mdio@32400 {
|
||||||
|
compatible = "ti,davinci_mdio";
|
||||||
|
reg = <0x32400 0x90>;
|
||||||
|
clocks = <&dpll_core_m4_ck>;
|
||||||
|
clock-names = "fck";
|
||||||
|
bus_freq = <1000000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
@ -579,8 +579,8 @@ static int k3_udma_glue_cfg_rx_flow(struct k3_udma_glue_rx_channel *rx_chn,
|
|||||||
|
|
||||||
/* request and cfg rings */
|
/* request and cfg rings */
|
||||||
ret = k3_ringacc_request_rings_pair(rx_chn->common.ringacc,
|
ret = k3_ringacc_request_rings_pair(rx_chn->common.ringacc,
|
||||||
flow_cfg->ring_rxq_id,
|
|
||||||
flow_cfg->ring_rxfdq0_id,
|
flow_cfg->ring_rxfdq0_id,
|
||||||
|
flow_cfg->ring_rxq_id,
|
||||||
&flow->ringrxfdq,
|
&flow->ringrxfdq,
|
||||||
&flow->ringrx);
|
&flow->ringrx);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -1124,7 +1124,8 @@ static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
|
|||||||
static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
|
static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
|
||||||
u32 dev_id, u32 clk_id)
|
u32 dev_id, u32 clk_id)
|
||||||
{
|
{
|
||||||
return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
|
return ti_sci_set_clock_state(handle, dev_id, clk_id,
|
||||||
|
MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE,
|
||||||
MSG_CLOCK_SW_STATE_UNREQ);
|
MSG_CLOCK_SW_STATE_UNREQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1143,7 +1144,8 @@ static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
|
|||||||
static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
|
static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
|
||||||
u32 dev_id, u32 clk_id)
|
u32 dev_id, u32 clk_id)
|
||||||
{
|
{
|
||||||
return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
|
return ti_sci_set_clock_state(handle, dev_id, clk_id,
|
||||||
|
MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE,
|
||||||
MSG_CLOCK_SW_STATE_AUTO);
|
MSG_CLOCK_SW_STATE_AUTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,17 @@ config TI_K3_SOCINFO
|
|||||||
platforms to provide information about the SoC family and
|
platforms to provide information about the SoC family and
|
||||||
variant to user space.
|
variant to user space.
|
||||||
|
|
||||||
|
config TI_PRUSS
|
||||||
|
tristate "TI PRU-ICSS Subsystem Platform drivers"
|
||||||
|
depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3
|
||||||
|
select MFD_SYSCON
|
||||||
|
help
|
||||||
|
TI PRU-ICSS Subsystem platform specific support.
|
||||||
|
|
||||||
|
Say Y or M here to support the Programmable Realtime Unit (PRU)
|
||||||
|
processors on various TI SoCs. It's safe to say N here if you're
|
||||||
|
not interested in the PRU or if you are unsure.
|
||||||
|
|
||||||
endif # SOC_TI
|
endif # SOC_TI
|
||||||
|
|
||||||
config TI_SCI_INTA_MSI_DOMAIN
|
config TI_SCI_INTA_MSI_DOMAIN
|
||||||
|
@ -12,3 +12,4 @@ obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o
|
|||||||
obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
|
obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN) += ti_sci_inta_msi.o
|
||||||
obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o
|
obj-$(CONFIG_TI_K3_RINGACC) += k3-ringacc.o
|
||||||
obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o
|
obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o
|
||||||
|
obj-$(CONFIG_TI_PRUSS) += pruss.o
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/sys_soc.h>
|
||||||
#include <linux/soc/ti/k3-ringacc.h>
|
#include <linux/soc/ti/k3-ringacc.h>
|
||||||
#include <linux/soc/ti/ti_sci_protocol.h>
|
#include <linux/soc/ti/ti_sci_protocol.h>
|
||||||
#include <linux/soc/ti/ti_sci_inta_msi.h>
|
#include <linux/soc/ti/ti_sci_inta_msi.h>
|
||||||
@ -208,6 +209,15 @@ struct k3_ringacc {
|
|||||||
const struct k3_ringacc_ops *ops;
|
const struct k3_ringacc_ops *ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct k3_ringacc - Rings accelerator SoC data
|
||||||
|
*
|
||||||
|
* @dma_ring_reset_quirk: DMA reset w/a enable
|
||||||
|
*/
|
||||||
|
struct k3_ringacc_soc_data {
|
||||||
|
unsigned dma_ring_reset_quirk:1;
|
||||||
|
};
|
||||||
|
|
||||||
static long k3_ringacc_ring_get_fifo_pos(struct k3_ring *ring)
|
static long k3_ringacc_ring_get_fifo_pos(struct k3_ring *ring)
|
||||||
{
|
{
|
||||||
return K3_RINGACC_FIFO_WINDOW_SIZE_BYTES -
|
return K3_RINGACC_FIFO_WINDOW_SIZE_BYTES -
|
||||||
@ -1051,9 +1061,6 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ringacc->dma_ring_reset_quirk =
|
|
||||||
of_property_read_bool(node, "ti,dma-ring-reset-quirk");
|
|
||||||
|
|
||||||
ringacc->tisci = ti_sci_get_by_phandle(node, "ti,sci");
|
ringacc->tisci = ti_sci_get_by_phandle(node, "ti,sci");
|
||||||
if (IS_ERR(ringacc->tisci)) {
|
if (IS_ERR(ringacc->tisci)) {
|
||||||
ret = PTR_ERR(ringacc->tisci);
|
ret = PTR_ERR(ringacc->tisci);
|
||||||
@ -1084,9 +1091,22 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc)
|
|||||||
ringacc->rm_gp_range);
|
ringacc->rm_gp_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct k3_ringacc_soc_data k3_ringacc_soc_data_sr1 = {
|
||||||
|
.dma_ring_reset_quirk = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct soc_device_attribute k3_ringacc_socinfo[] = {
|
||||||
|
{ .family = "AM65X",
|
||||||
|
.revision = "SR1.0",
|
||||||
|
.data = &k3_ringacc_soc_data_sr1
|
||||||
|
},
|
||||||
|
{/* sentinel */}
|
||||||
|
};
|
||||||
|
|
||||||
static int k3_ringacc_init(struct platform_device *pdev,
|
static int k3_ringacc_init(struct platform_device *pdev,
|
||||||
struct k3_ringacc *ringacc)
|
struct k3_ringacc *ringacc)
|
||||||
{
|
{
|
||||||
|
const struct soc_device_attribute *soc;
|
||||||
void __iomem *base_fifo, *base_rt;
|
void __iomem *base_fifo, *base_rt;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
@ -1103,6 +1123,13 @@ static int k3_ringacc_init(struct platform_device *pdev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
soc = soc_device_match(k3_ringacc_socinfo);
|
||||||
|
if (soc && soc->data) {
|
||||||
|
const struct k3_ringacc_soc_data *soc_data = soc->data;
|
||||||
|
|
||||||
|
ringacc->dma_ring_reset_quirk = soc_data->dma_ring_reset_quirk;
|
||||||
|
}
|
||||||
|
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rt");
|
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rt");
|
||||||
base_rt = devm_ioremap_resource(dev, res);
|
base_rt = devm_ioremap_resource(dev, res);
|
||||||
if (IS_ERR(base_rt))
|
if (IS_ERR(base_rt))
|
||||||
|
@ -39,6 +39,7 @@ static const struct k3_soc_id {
|
|||||||
} k3_soc_ids[] = {
|
} k3_soc_ids[] = {
|
||||||
{ 0xBB5A, "AM65X" },
|
{ 0xBB5A, "AM65X" },
|
||||||
{ 0xBB64, "J721E" },
|
{ 0xBB64, "J721E" },
|
||||||
|
{ 0xBB6D, "J7200" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -355,7 +355,7 @@ static void dma_debug_show_devices(struct seq_file *s,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dma_debug_show(struct seq_file *s, void *v)
|
static int knav_dma_debug_show(struct seq_file *s, void *v)
|
||||||
{
|
{
|
||||||
struct knav_dma_device *dma;
|
struct knav_dma_device *dma;
|
||||||
|
|
||||||
@ -370,17 +370,7 @@ static int dma_debug_show(struct seq_file *s, void *v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int knav_dma_debug_open(struct inode *inode, struct file *file)
|
DEFINE_SHOW_ATTRIBUTE(knav_dma_debug);
|
||||||
{
|
|
||||||
return single_open(file, dma_debug_show, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations knav_dma_debug_ops = {
|
|
||||||
.open = knav_dma_debug_open,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int of_channel_match_helper(struct device_node *np, const char *name,
|
static int of_channel_match_helper(struct device_node *np, const char *name,
|
||||||
const char **dma_instance)
|
const char **dma_instance)
|
||||||
@ -778,7 +768,7 @@ static int knav_dma_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
debugfs_create_file("knav_dma", S_IFREG | S_IRUGO, NULL, NULL,
|
debugfs_create_file("knav_dma", S_IFREG | S_IRUGO, NULL, NULL,
|
||||||
&knav_dma_debug_ops);
|
&knav_dma_debug_fops);
|
||||||
|
|
||||||
device_ready = true;
|
device_ready = true;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -478,17 +478,7 @@ static int knav_queue_debug_show(struct seq_file *s, void *v)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int knav_queue_debug_open(struct inode *inode, struct file *file)
|
DEFINE_SHOW_ATTRIBUTE(knav_queue_debug);
|
||||||
{
|
|
||||||
return single_open(file, knav_queue_debug_show, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations knav_queue_debug_ops = {
|
|
||||||
.open = knav_queue_debug_open,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int knav_queue_pdsp_wait(u32 * __iomem addr, unsigned timeout,
|
static inline int knav_queue_pdsp_wait(u32 * __iomem addr, unsigned timeout,
|
||||||
u32 flags)
|
u32 flags)
|
||||||
@ -1878,7 +1868,7 @@ static int knav_queue_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
debugfs_create_file("qmss", S_IFREG | S_IRUGO, NULL, NULL,
|
debugfs_create_file("qmss", S_IFREG | S_IRUGO, NULL, NULL,
|
||||||
&knav_queue_debug_ops);
|
&knav_queue_debug_fops);
|
||||||
device_ready = true;
|
device_ready = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
354
drivers/soc/ti/pruss.c
Normal file
354
drivers/soc/ti/pruss.c
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* PRU-ICSS platform driver for various TI SoCs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014-2020 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
* Author(s):
|
||||||
|
* Suman Anna <s-anna@ti.com>
|
||||||
|
* Andrew F. Davis <afd@ti.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/pruss_driver.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct pruss_private_data - PRUSS driver private data
|
||||||
|
* @has_no_sharedram: flag to indicate the absence of PRUSS Shared Data RAM
|
||||||
|
* @has_core_mux_clock: flag to indicate the presence of PRUSS core clock
|
||||||
|
*/
|
||||||
|
struct pruss_private_data {
|
||||||
|
bool has_no_sharedram;
|
||||||
|
bool has_core_mux_clock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void pruss_of_free_clk_provider(void *data)
|
||||||
|
{
|
||||||
|
struct device_node *clk_mux_np = data;
|
||||||
|
|
||||||
|
of_clk_del_provider(clk_mux_np);
|
||||||
|
of_node_put(clk_mux_np);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
|
||||||
|
char *mux_name, struct device_node *clks_np)
|
||||||
|
{
|
||||||
|
struct device_node *clk_mux_np;
|
||||||
|
struct device *dev = pruss->dev;
|
||||||
|
char *clk_mux_name;
|
||||||
|
unsigned int num_parents;
|
||||||
|
const char **parent_names;
|
||||||
|
void __iomem *reg;
|
||||||
|
u32 reg_offset;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clk_mux_np = of_get_child_by_name(clks_np, mux_name);
|
||||||
|
if (!clk_mux_np) {
|
||||||
|
dev_err(dev, "%pOF is missing its '%s' node\n", clks_np,
|
||||||
|
mux_name);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_parents = of_clk_get_parent_count(clk_mux_np);
|
||||||
|
if (num_parents < 1) {
|
||||||
|
dev_err(dev, "mux-clock %pOF must have parents\n", clk_mux_np);
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_names = devm_kcalloc(dev, sizeof(*parent_names), num_parents,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!parent_names) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
}
|
||||||
|
|
||||||
|
of_clk_parent_fill(clk_mux_np, parent_names, num_parents);
|
||||||
|
|
||||||
|
clk_mux_name = devm_kasprintf(dev, GFP_KERNEL, "%s.%pOFn",
|
||||||
|
dev_name(dev), clk_mux_np);
|
||||||
|
if (!clk_mux_name) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = of_property_read_u32(clk_mux_np, "reg", ®_offset);
|
||||||
|
if (ret)
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
|
||||||
|
reg = pruss->cfg_base + reg_offset;
|
||||||
|
|
||||||
|
clk_mux = clk_register_mux(NULL, clk_mux_name, parent_names,
|
||||||
|
num_parents, 0, reg, 0, 1, 0, NULL);
|
||||||
|
if (IS_ERR(clk_mux)) {
|
||||||
|
ret = PTR_ERR(clk_mux);
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux,
|
||||||
|
clk_mux);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to add clkmux unregister action %d", ret);
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = of_clk_add_provider(clk_mux_np, of_clk_src_simple_get, clk_mux);
|
||||||
|
if (ret)
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
|
||||||
|
ret = devm_add_action_or_reset(dev, pruss_of_free_clk_provider,
|
||||||
|
clk_mux_np);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to add clkmux free action %d", ret);
|
||||||
|
goto put_clk_mux_np;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
put_clk_mux_np:
|
||||||
|
of_node_put(clk_mux_np);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pruss_clk_init(struct pruss *pruss, struct device_node *cfg_node)
|
||||||
|
{
|
||||||
|
const struct pruss_private_data *data;
|
||||||
|
struct device_node *clks_np;
|
||||||
|
struct device *dev = pruss->dev;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
data = of_device_get_match_data(dev);
|
||||||
|
if (IS_ERR(data))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
clks_np = of_get_child_by_name(cfg_node, "clocks");
|
||||||
|
if (!clks_np) {
|
||||||
|
dev_err(dev, "%pOF is missing its 'clocks' node\n", clks_np);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data && data->has_core_mux_clock) {
|
||||||
|
ret = pruss_clk_mux_setup(pruss, pruss->core_clk_mux,
|
||||||
|
"coreclk-mux", clks_np);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to setup coreclk-mux\n");
|
||||||
|
goto put_clks_node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pruss_clk_mux_setup(pruss, pruss->iep_clk_mux, "iepclk-mux",
|
||||||
|
clks_np);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to setup iepclk-mux\n");
|
||||||
|
goto put_clks_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
put_clks_node:
|
||||||
|
of_node_put(clks_np);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct regmap_config regmap_conf = {
|
||||||
|
.reg_bits = 32,
|
||||||
|
.val_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pruss_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *np = dev_of_node(dev);
|
||||||
|
struct device_node *child;
|
||||||
|
struct pruss *pruss;
|
||||||
|
struct resource res;
|
||||||
|
int ret, i, index;
|
||||||
|
const struct pruss_private_data *data;
|
||||||
|
const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" };
|
||||||
|
|
||||||
|
data = of_device_get_match_data(&pdev->dev);
|
||||||
|
if (IS_ERR(data)) {
|
||||||
|
dev_err(dev, "missing private data\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to set the DMA coherent mask");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pruss = devm_kzalloc(dev, sizeof(*pruss), GFP_KERNEL);
|
||||||
|
if (!pruss)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pruss->dev = dev;
|
||||||
|
|
||||||
|
child = of_get_child_by_name(np, "memories");
|
||||||
|
if (!child) {
|
||||||
|
dev_err(dev, "%pOF is missing its 'memories' node\n", child);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < PRUSS_MEM_MAX; i++) {
|
||||||
|
/*
|
||||||
|
* On AM437x one of two PRUSS units don't contain Shared RAM,
|
||||||
|
* skip it
|
||||||
|
*/
|
||||||
|
if (data && data->has_no_sharedram && i == PRUSS_MEM_SHRD_RAM2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
index = of_property_match_string(child, "reg-names",
|
||||||
|
mem_names[i]);
|
||||||
|
if (index < 0) {
|
||||||
|
of_node_put(child);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (of_address_to_resource(child, index, &res)) {
|
||||||
|
of_node_put(child);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pruss->mem_regions[i].va = devm_ioremap(dev, res.start,
|
||||||
|
resource_size(&res));
|
||||||
|
if (!pruss->mem_regions[i].va) {
|
||||||
|
dev_err(dev, "failed to parse and map memory resource %d %s\n",
|
||||||
|
i, mem_names[i]);
|
||||||
|
of_node_put(child);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
pruss->mem_regions[i].pa = res.start;
|
||||||
|
pruss->mem_regions[i].size = resource_size(&res);
|
||||||
|
|
||||||
|
dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
|
||||||
|
mem_names[i], &pruss->mem_regions[i].pa,
|
||||||
|
pruss->mem_regions[i].size, pruss->mem_regions[i].va);
|
||||||
|
}
|
||||||
|
of_node_put(child);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, pruss);
|
||||||
|
|
||||||
|
pm_runtime_enable(dev);
|
||||||
|
ret = pm_runtime_get_sync(dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "couldn't enable module\n");
|
||||||
|
pm_runtime_put_noidle(dev);
|
||||||
|
goto rpm_disable;
|
||||||
|
}
|
||||||
|
|
||||||
|
child = of_get_child_by_name(np, "cfg");
|
||||||
|
if (!child) {
|
||||||
|
dev_err(dev, "%pOF is missing its 'cfg' node\n", child);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto rpm_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (of_address_to_resource(child, 0, &res)) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto node_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res));
|
||||||
|
if (!pruss->cfg_base) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto node_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child,
|
||||||
|
(u64)res.start);
|
||||||
|
regmap_conf.max_register = resource_size(&res) - 4;
|
||||||
|
|
||||||
|
pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base,
|
||||||
|
®map_conf);
|
||||||
|
kfree(regmap_conf.name);
|
||||||
|
if (IS_ERR(pruss->cfg_regmap)) {
|
||||||
|
dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n",
|
||||||
|
PTR_ERR(pruss->cfg_regmap));
|
||||||
|
ret = PTR_ERR(pruss->cfg_regmap);
|
||||||
|
goto node_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pruss_clk_init(pruss, child);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to setup coreclk-mux\n");
|
||||||
|
goto node_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_of_platform_populate(dev);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "failed to register child devices\n");
|
||||||
|
goto node_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
of_node_put(child);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
node_put:
|
||||||
|
of_node_put(child);
|
||||||
|
rpm_put:
|
||||||
|
pm_runtime_put_sync(dev);
|
||||||
|
rpm_disable:
|
||||||
|
pm_runtime_disable(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pruss_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
|
||||||
|
devm_of_platform_depopulate(dev);
|
||||||
|
|
||||||
|
pm_runtime_put_sync(dev);
|
||||||
|
pm_runtime_disable(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* instance-specific driver private data */
|
||||||
|
static const struct pruss_private_data am437x_pruss1_data = {
|
||||||
|
.has_no_sharedram = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pruss_private_data am437x_pruss0_data = {
|
||||||
|
.has_no_sharedram = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pruss_private_data am65x_j721e_pruss_data = {
|
||||||
|
.has_core_mux_clock = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id pruss_of_match[] = {
|
||||||
|
{ .compatible = "ti,am3356-pruss" },
|
||||||
|
{ .compatible = "ti,am4376-pruss0", .data = &am437x_pruss0_data, },
|
||||||
|
{ .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, },
|
||||||
|
{ .compatible = "ti,am5728-pruss" },
|
||||||
|
{ .compatible = "ti,k2g-pruss" },
|
||||||
|
{ .compatible = "ti,am654-icssg", .data = &am65x_j721e_pruss_data, },
|
||||||
|
{ .compatible = "ti,j721e-icssg", .data = &am65x_j721e_pruss_data, },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, pruss_of_match);
|
||||||
|
|
||||||
|
static struct platform_driver pruss_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "pruss",
|
||||||
|
.of_match_table = pruss_of_match,
|
||||||
|
},
|
||||||
|
.probe = pruss_probe,
|
||||||
|
.remove = pruss_remove,
|
||||||
|
};
|
||||||
|
module_platform_driver(pruss_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
|
||||||
|
MODULE_DESCRIPTION("PRU-ICSS Subsystem Driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_domain.h>
|
#include <linux/pm_domain.h>
|
||||||
@ -18,150 +17,95 @@
|
|||||||
#include <dt-bindings/soc/ti,sci_pm_domain.h>
|
#include <dt-bindings/soc/ti,sci_pm_domain.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ti_sci_genpd_dev_data: holds data needed for every device attached
|
* struct ti_sci_genpd_provider: holds common TI SCI genpd provider data
|
||||||
* to this genpd
|
* @ti_sci: handle to TI SCI protocol driver that provides ops to
|
||||||
* @idx: index of the device that identifies it with the system
|
* communicate with system control processor.
|
||||||
* control processor.
|
* @dev: pointer to dev for the driver for devm allocs
|
||||||
* @exclusive: Permissions for exclusive request or shared request of the
|
* @pd_list: list of all the power domains on the device
|
||||||
* device.
|
* @data: onecell data for genpd core
|
||||||
*/
|
*/
|
||||||
struct ti_sci_genpd_dev_data {
|
struct ti_sci_genpd_provider {
|
||||||
int idx;
|
const struct ti_sci_handle *ti_sci;
|
||||||
u8 exclusive;
|
struct device *dev;
|
||||||
|
struct list_head pd_list;
|
||||||
|
struct genpd_onecell_data data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct ti_sci_pm_domain: TI specific data needed for power domain
|
* struct ti_sci_pm_domain: TI specific data needed for power domain
|
||||||
* @ti_sci: handle to TI SCI protocol driver that provides ops to
|
* @idx: index of the device that identifies it with the system
|
||||||
* communicate with system control processor.
|
* control processor.
|
||||||
* @dev: pointer to dev for the driver for devm allocs
|
* @exclusive: Permissions for exclusive request or shared request of the
|
||||||
|
* device.
|
||||||
* @pd: generic_pm_domain for use with the genpd framework
|
* @pd: generic_pm_domain for use with the genpd framework
|
||||||
|
* @node: link for the genpd list
|
||||||
|
* @parent: link to the parent TI SCI genpd provider
|
||||||
*/
|
*/
|
||||||
struct ti_sci_pm_domain {
|
struct ti_sci_pm_domain {
|
||||||
const struct ti_sci_handle *ti_sci;
|
int idx;
|
||||||
struct device *dev;
|
u8 exclusive;
|
||||||
struct generic_pm_domain pd;
|
struct generic_pm_domain pd;
|
||||||
|
struct list_head node;
|
||||||
|
struct ti_sci_genpd_provider *parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
|
#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* ti_sci_dev_id(): get prepopulated ti_sci id from struct dev
|
* ti_sci_pd_power_off(): genpd power down hook
|
||||||
* @dev: pointer to device associated with this genpd
|
* @domain: pointer to the powerdomain to power off
|
||||||
*
|
|
||||||
* Returns device_id stored from ti,sci_id property
|
|
||||||
*/
|
*/
|
||||||
static int ti_sci_dev_id(struct device *dev)
|
static int ti_sci_pd_power_off(struct generic_pm_domain *domain)
|
||||||
{
|
{
|
||||||
struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
|
struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
|
||||||
struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
|
const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
|
||||||
|
|
||||||
return sci_dev_data->idx;
|
return ti_sci->ops.dev_ops.put_device(ti_sci, pd->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 is_ti_sci_dev_exclusive(struct device *dev)
|
/*
|
||||||
{
|
* ti_sci_pd_power_on(): genpd power up hook
|
||||||
struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
|
* @domain: pointer to the powerdomain to power on
|
||||||
struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
|
|
||||||
|
|
||||||
return sci_dev_data->exclusive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle
|
|
||||||
* @dev: pointer to device associated with this genpd
|
|
||||||
*
|
|
||||||
* Returns ti_sci_handle to be used to communicate with system
|
|
||||||
* control processor.
|
|
||||||
*/
|
*/
|
||||||
static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev)
|
static int ti_sci_pd_power_on(struct generic_pm_domain *domain)
|
||||||
{
|
{
|
||||||
struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain);
|
struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain);
|
||||||
struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd);
|
const struct ti_sci_handle *ti_sci = pd->parent->ti_sci;
|
||||||
|
|
||||||
return ti_sci_genpd->ti_sci;
|
if (pd->exclusive)
|
||||||
}
|
return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci,
|
||||||
|
pd->idx);
|
||||||
/**
|
|
||||||
* ti_sci_dev_start(): genpd device start hook called to turn device on
|
|
||||||
* @dev: pointer to device associated with this genpd to be powered on
|
|
||||||
*/
|
|
||||||
static int ti_sci_dev_start(struct device *dev)
|
|
||||||
{
|
|
||||||
const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
|
|
||||||
int idx = ti_sci_dev_id(dev);
|
|
||||||
|
|
||||||
if (is_ti_sci_dev_exclusive(dev))
|
|
||||||
return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci, idx);
|
|
||||||
else
|
else
|
||||||
return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
|
return ti_sci->ops.dev_ops.get_device(ti_sci, pd->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* ti_sci_dev_stop(): genpd device stop hook called to turn device off
|
* ti_sci_pd_xlate(): translation service for TI SCI genpds
|
||||||
* @dev: pointer to device associated with this genpd to be powered off
|
* @genpdspec: DT identification data for the genpd
|
||||||
|
* @data: genpd core data for all the powerdomains on the device
|
||||||
*/
|
*/
|
||||||
static int ti_sci_dev_stop(struct device *dev)
|
static struct generic_pm_domain *ti_sci_pd_xlate(
|
||||||
|
struct of_phandle_args *genpdspec,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
|
struct genpd_onecell_data *genpd_data = data;
|
||||||
int idx = ti_sci_dev_id(dev);
|
unsigned int idx = genpdspec->args[0];
|
||||||
|
|
||||||
return ti_sci->ops.dev_ops.put_device(ti_sci, idx);
|
if (genpdspec->args_count < 2)
|
||||||
}
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
|
if (idx >= genpd_data->num_domains) {
|
||||||
struct device *dev)
|
pr_err("%s: invalid domain index %u\n", __func__, idx);
|
||||||
{
|
return ERR_PTR(-EINVAL);
|
||||||
struct device_node *np = dev->of_node;
|
}
|
||||||
struct of_phandle_args pd_args;
|
|
||||||
struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain);
|
|
||||||
const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci;
|
|
||||||
struct ti_sci_genpd_dev_data *sci_dev_data;
|
|
||||||
struct generic_pm_domain_data *genpd_data;
|
|
||||||
int idx, ret = 0;
|
|
||||||
|
|
||||||
ret = of_parse_phandle_with_args(np, "power-domains",
|
if (!genpd_data->domains[idx])
|
||||||
"#power-domain-cells", 0, &pd_args);
|
return ERR_PTR(-ENOENT);
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (pd_args.args_count != 1 && pd_args.args_count != 2)
|
genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive =
|
||||||
return -EINVAL;
|
genpdspec->args[1];
|
||||||
|
|
||||||
idx = pd_args.args[0];
|
return genpd_data->domains[idx];
|
||||||
|
|
||||||
/*
|
|
||||||
* Check the validity of the requested idx, if the index is not valid
|
|
||||||
* the PMMC will return a NAK here and we will not allocate it.
|
|
||||||
*/
|
|
||||||
ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx);
|
|
||||||
if (ret)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL);
|
|
||||||
if (!sci_dev_data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
sci_dev_data->idx = idx;
|
|
||||||
/* Enable the exclusive permissions by default */
|
|
||||||
sci_dev_data->exclusive = TI_SCI_PD_EXCLUSIVE;
|
|
||||||
if (pd_args.args_count == 2)
|
|
||||||
sci_dev_data->exclusive = pd_args.args[1] & 0x1;
|
|
||||||
|
|
||||||
genpd_data = dev_gpd_data(dev);
|
|
||||||
genpd_data->data = sci_dev_data;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain,
|
|
||||||
struct device *dev)
|
|
||||||
{
|
|
||||||
struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
|
|
||||||
struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
|
|
||||||
|
|
||||||
kfree(sci_dev_data);
|
|
||||||
genpd_data->data = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id ti_sci_pm_domain_matches[] = {
|
static const struct of_device_id ti_sci_pm_domain_matches[] = {
|
||||||
@ -173,33 +117,80 @@ MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
|
|||||||
static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
static int ti_sci_pm_domain_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct device_node *np = dev->of_node;
|
struct ti_sci_genpd_provider *pd_provider;
|
||||||
struct ti_sci_pm_domain *ti_sci_pd;
|
struct ti_sci_pm_domain *pd;
|
||||||
|
struct device_node *np = NULL;
|
||||||
|
struct of_phandle_args args;
|
||||||
int ret;
|
int ret;
|
||||||
|
u32 max_id = 0;
|
||||||
|
int index;
|
||||||
|
|
||||||
ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL);
|
pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL);
|
||||||
if (!ti_sci_pd)
|
if (!pd_provider)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev);
|
pd_provider->ti_sci = devm_ti_sci_get_handle(dev);
|
||||||
if (IS_ERR(ti_sci_pd->ti_sci))
|
if (IS_ERR(pd_provider->ti_sci))
|
||||||
return PTR_ERR(ti_sci_pd->ti_sci);
|
return PTR_ERR(pd_provider->ti_sci);
|
||||||
|
|
||||||
ti_sci_pd->dev = dev;
|
pd_provider->dev = dev;
|
||||||
|
|
||||||
ti_sci_pd->pd.name = "ti_sci_pd";
|
INIT_LIST_HEAD(&pd_provider->pd_list);
|
||||||
|
|
||||||
ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev;
|
/* Find highest device ID used for power domains */
|
||||||
ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev;
|
while (1) {
|
||||||
|
np = of_find_node_with_property(np, "power-domains");
|
||||||
|
if (!np)
|
||||||
|
break;
|
||||||
|
|
||||||
ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start;
|
index = 0;
|
||||||
ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop;
|
|
||||||
|
|
||||||
pm_genpd_init(&ti_sci_pd->pd, NULL, true);
|
while (1) {
|
||||||
|
ret = of_parse_phandle_with_args(np, "power-domains",
|
||||||
|
"#power-domain-cells",
|
||||||
|
index, &args);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
|
||||||
ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd);
|
if (args.args_count >= 1 && args.np == dev->of_node) {
|
||||||
|
if (args.args[0] > max_id)
|
||||||
|
max_id = args.args[0];
|
||||||
|
|
||||||
return ret;
|
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||||
|
if (!pd)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pd->pd.name = devm_kasprintf(dev, GFP_KERNEL,
|
||||||
|
"pd:%d",
|
||||||
|
args.args[0]);
|
||||||
|
if (!pd->pd.name)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pd->pd.power_off = ti_sci_pd_power_off;
|
||||||
|
pd->pd.power_on = ti_sci_pd_power_on;
|
||||||
|
pd->idx = args.args[0];
|
||||||
|
pd->parent = pd_provider;
|
||||||
|
|
||||||
|
pm_genpd_init(&pd->pd, NULL, true);
|
||||||
|
|
||||||
|
list_add(&pd->node, &pd_provider->pd_list);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pd_provider->data.domains =
|
||||||
|
devm_kcalloc(dev, max_id + 1,
|
||||||
|
sizeof(*pd_provider->data.domains),
|
||||||
|
GFP_KERNEL);
|
||||||
|
|
||||||
|
pd_provider->data.num_domains = max_id + 1;
|
||||||
|
pd_provider->data.xlate = ti_sci_pd_xlate;
|
||||||
|
|
||||||
|
list_for_each_entry(pd, &pd_provider->pd_list, node)
|
||||||
|
pd_provider->data.domains[pd->idx] = &pd->pd;
|
||||||
|
|
||||||
|
return of_genpd_add_provider_onecell(dev->of_node, &pd_provider->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver ti_sci_pm_domains_driver = {
|
static struct platform_driver ti_sci_pm_domains_driver = {
|
||||||
|
54
include/linux/pruss_driver.h
Normal file
54
include/linux/pruss_driver.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* PRU-ICSS sub-system specific definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014-2020 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
* Suman Anna <s-anna@ti.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PRUSS_DRIVER_H_
|
||||||
|
#define _PRUSS_DRIVER_H_
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* enum pruss_mem - PRUSS memory range identifiers
|
||||||
|
*/
|
||||||
|
enum pruss_mem {
|
||||||
|
PRUSS_MEM_DRAM0 = 0,
|
||||||
|
PRUSS_MEM_DRAM1,
|
||||||
|
PRUSS_MEM_SHRD_RAM2,
|
||||||
|
PRUSS_MEM_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct pruss_mem_region - PRUSS memory region structure
|
||||||
|
* @va: kernel virtual address of the PRUSS memory region
|
||||||
|
* @pa: physical (bus) address of the PRUSS memory region
|
||||||
|
* @size: size of the PRUSS memory region
|
||||||
|
*/
|
||||||
|
struct pruss_mem_region {
|
||||||
|
void __iomem *va;
|
||||||
|
phys_addr_t pa;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct pruss - PRUSS parent structure
|
||||||
|
* @dev: pruss device pointer
|
||||||
|
* @cfg_base: base iomap for CFG region
|
||||||
|
* @cfg_regmap: regmap for config region
|
||||||
|
* @mem_regions: data for each of the PRUSS memory regions
|
||||||
|
* @core_clk_mux: clk handle for PRUSS CORE_CLK_MUX
|
||||||
|
* @iep_clk_mux: clk handle for PRUSS IEP_CLK_MUX
|
||||||
|
*/
|
||||||
|
struct pruss {
|
||||||
|
struct device *dev;
|
||||||
|
void __iomem *cfg_base;
|
||||||
|
struct regmap *cfg_regmap;
|
||||||
|
struct pruss_mem_region mem_regions[PRUSS_MEM_MAX];
|
||||||
|
struct clk *core_clk_mux;
|
||||||
|
struct clk *iep_clk_mux;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _PRUSS_DRIVER_H_ */
|
Loading…
x
Reference in New Issue
Block a user