From 95e7be062aea6d2e09116cd4d28957d310c04781 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 11 Sep 2020 21:29:56 -0700 Subject: [PATCH 01/17] soc: ti: k3: ringacc: add am65x sr2.0 support The AM65x SR2.0 Ringacc has fixed errata i2023 "RINGACC, UDMA: RINGACC and UDMA Ring State Interoperability Issue after Channel Teardown". This errata also fixed for J271E SoC. Use SOC bus data for K3 SoC identification and enable i2023 errate w/a only for the AM65x SR1.0. This also makes obsolete "ti,dma-ring-reset-quirk" DT property. Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/k3-ringacc.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c index 6dcc21dde0cb..1147dc4c1d59 100644 --- a/drivers/soc/ti/k3-ringacc.c +++ b/drivers/soc/ti/k3-ringacc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,15 @@ struct k3_ringacc { 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) { return K3_RINGACC_FIFO_WINDOW_SIZE_BYTES - @@ -1051,9 +1061,6 @@ static int k3_ringacc_probe_dt(struct k3_ringacc *ringacc) 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"); if (IS_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); } +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, struct k3_ringacc *ringacc) { + const struct soc_device_attribute *soc; void __iomem *base_fifo, *base_rt; struct device *dev = &pdev->dev; struct resource *res; @@ -1103,6 +1123,13 @@ static int k3_ringacc_init(struct platform_device *pdev, if (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"); base_rt = devm_ioremap_resource(dev, res); if (IS_ERR(base_rt)) From aee123f48f387ea62002cddb46c7cb04c96628df Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 11 Sep 2020 21:30:23 -0700 Subject: [PATCH 02/17] bindings: soc: ti: soc: ringacc: remove ti,dma-ring-reset-quirk Remove "ti,dma-ring-reset-quirk" DT property as proper w/a handling is implemented now in Ringacc driver using SoC info. Signed-off-by: Grygorii Strashko Signed-off-by: Santosh Shilimkar --- Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml b/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml index ae33fc957141..c3c595e235a8 100644 --- a/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml +++ b/Documentation/devicetree/bindings/soc/ti/k3-ringacc.yaml @@ -62,11 +62,6 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 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: - compatible - reg @@ -94,7 +89,6 @@ examples: reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target"; ti,num-rings = <818>; ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */ - ti,dma-ring-reset-quirk; ti,sci = <&dmsc>; ti,sci-dev-id = <187>; msi-parent = <&inta_main_udmass>; From bd691ce0ba9d610018072723307f5983f94f5322 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Fri, 11 Sep 2020 21:41:17 -0700 Subject: [PATCH 03/17] dt-bindings: soc: ti: Add TI PRUSS bindings This patch adds the bindings for the Programmable Real-Time Unit and Industrial Communication Subsystem (PRU-ICSS) present on various TI SoCs. The IP is present on multiple TI SoC architecture families including the OMAP architecture SoCs such as AM33xx, AM437x and AM57xx; and on a Keystone 2 architecture based 66AK2G SoC. It is also present on the Davinci based OMAPL138 SoCs and K3 architecture based AM65x and J721E SoCs as well. The IP has a number of sub-modules some of which are represented as their own devices. This binding covers only the top-level sub-system devices, and some sub-modules like MDIO, MII_RT (Ethernet MII_RT module with MII ports) and IEP (Industrial Ethernet Peripheral). The remaining sub-modules bindings shall be defined in the respective driver subsystem bindings folders. Couple of full examples have also been added demonstrating the devices on AM335x and AM437x SoCs. Reviewed-by: Rob Herring Signed-off-by: Suman Anna Signed-off-by: Roger Quadros Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- .../devicetree/bindings/soc/ti/ti,pruss.yaml | 320 ++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml new file mode 100644 index 000000000000..482beefaac1f --- /dev/null +++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml @@ -0,0 +1,320 @@ +# 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 + +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 + + reg: + maxItems: 1 + + 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"; + reg = <0x26000 0x2000>; + }; + + 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 + 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"; + reg = <0x26000 0x2000>; + }; + + 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>; + }; + }; + +... From dc1129564a0147feb459159fd220ae22357e2eb6 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:34 -0700 Subject: [PATCH 04/17] soc: ti: pruss: Add a platform driver for PRUSS in TI SoCs The Programmable Real-Time Unit - Industrial Communication Subsystem (PRU-ICSS) is present on various TI SoCs such as AM335x or AM437x or the Keystone 66AK2G. Each SoC can have one or more PRUSS instances that may or may not be identical. For example, AM335x SoCs have a single PRUSS, while AM437x has two PRUSS instances PRUSS1 and PRUSS0, with the PRUSS0 being a cut-down version of the PRUSS1. The PRUSS consists of dual 32-bit RISC cores called the Programmable Real-Time Units (PRUs), some shared, data and instruction memories, some internal peripheral modules, 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 PRU-ICSS functionality is achieved through three different platform drivers addressing a specific portion of the PRUSS. Some sub-modules of the PRU-ICSS IP reuse some of the existing drivers (like davinci mdio driver or the generic syscon driver). This design provides flexibility in representing the different modules of PRUSS accordingly, and at the same time allowing the PRUSS driver to add some instance specific configuration within an SoC. The PRUSS platform driver deals with the overall PRUSS and is used for managing the subsystem level resources like various memories and the CFG module. It is responsible for the creation and deletion of the platform devices for the child PRU devices and other child devices (like Interrupt Controller, MDIO node and some syscon nodes) so that they can be managed by specific platform drivers. The PRUSS interrupt controller is managed by an irqchip driver, while the individual PRU RISC cores are managed by a PRU remoteproc driver. The driver currently supports the AM335x SoC, and support for other TI SoCs will be added in subsequent patches. Signed-off-by: Suman Anna Signed-off-by: Andrew F. Davis Signed-off-by: Tero Kristo Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 11 +++ drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 147 +++++++++++++++++++++++++++++++++++ include/linux/pruss_driver.h | 48 ++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/linux/pruss_driver.h diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index e192fb788836..b934bc341d26 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -101,6 +101,17 @@ config TI_K3_SOCINFO platforms to provide information about the SoC family and variant to user space. +config TI_PRUSS + tristate "TI PRU-ICSS Subsystem Platform drivers" + depends on SOC_AM33XX + 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 config TI_SCI_INTA_MSI_DOMAIN diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index 1110e5c98685..18129aa557df 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -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_K3_RINGACC) += k3-ringacc.o obj-$(CONFIG_TI_K3_SOCINFO) += k3-socinfo.o +obj-$(CONFIG_TI_PRUSS) += pruss.o diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c new file mode 100644 index 000000000000..c071bb2e1c33 --- /dev/null +++ b/drivers/soc/ti/pruss.c @@ -0,0 +1,147 @@ +// 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 + * Andrew F. Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" }; + + 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 < ARRAY_SIZE(mem_names); i++) { + 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; + } + + pruss->cfg_regmap = syscon_node_to_regmap(child); + of_node_put(child); + if (IS_ERR(pruss->cfg_regmap)) { + ret = -ENODEV; + goto rpm_put; + } + + ret = devm_of_platform_populate(dev); + if (ret) { + dev_err(dev, "failed to register child devices\n"); + goto rpm_put; + } + + return 0; + +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; +} + +static const struct of_device_id pruss_of_match[] = { + { .compatible = "ti,am3356-pruss" }, + {}, +}; +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 "); +MODULE_DESCRIPTION("PRU-ICSS Subsystem Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h new file mode 100644 index 000000000000..0701fe1953dd --- /dev/null +++ b/include/linux/pruss_driver.h @@ -0,0 +1,48 @@ +/* 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 + */ + +#ifndef _PRUSS_DRIVER_H_ +#define _PRUSS_DRIVER_H_ + +#include + +/* + * 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_regmap: regmap for config region + * @mem_regions: data for each of the PRUSS memory regions + */ +struct pruss { + struct device *dev; + struct regmap *cfg_regmap; + struct pruss_mem_region mem_regions[PRUSS_MEM_MAX]; +}; + +#endif /* _PRUSS_DRIVER_H_ */ From 78251639d376a4ea1a795a4f3dcd985fcdf9aed3 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:35 -0700 Subject: [PATCH 05/17] soc: ti: pruss: Add support for PRU-ICSSs on AM437x SoCs The AM437x SoCs have two different PRU-ICSS subsystems: PRU-ICSS1 and a smaller PRU-ICSS0. Enhance the PRUSS platform driver to support both the PRU-ICSS sub-systems on these SoCs. The PRU-ICSS1 on AM437x is very similar to the PRU-ICSS on AM33xx except for few minor differences - increased Instruction RAM, increased Shared Data RAM2, and 1 less interrupt (PRUSS host interrupt 7 which is redirected to the other PRUSS) towards the MPU INTC. The PRU-ICSS0 is a cut-down version of the IP, with less DRAM per PRU, no Shared DRAM etc. It also does not have direct access to L3 bus regions, there is a single interface to L3 for both PRUSS0 and PRUSS1, and it would have to go through the PRUSS1's interface. The PRUSS_SYSCFG register is reserved on PRUSS0, so any external access requires the programming the corresponding PRUSS_SYSCFG register in PRUSS1. It does have its own dedicated I/O lines though. Note that this instance does not support any PRU Ethernet related use cases. The adaptation uses SoC-specific compatibles in the driver and uses a newly introduced pruss_match_private_data structure and the pruss_get_private_data() function to retrieve a PRUSS instance specific data using a device-name based lookup logic. The reset and the L3 external access are managed by the parent interconnect ti-sysc bus driver so that PRUSS1 and PRUSS0 can be independently supported. Signed-off-by: Suman Anna Signed-off-by: Andrew F. Davis Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index b934bc341d26..40d6a222275f 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX + depends on SOC_AM33XX || SOC_AM43XX select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index c071bb2e1c33..04938ba6b150 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -17,6 +17,14 @@ #include #include +/** + * struct pruss_private_data - PRUSS driver private data + * @has_no_sharedram: flag to indicate the absence of PRUSS Shared Data RAM + */ +struct pruss_private_data { + bool has_no_sharedram; +}; + static int pruss_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -25,8 +33,15 @@ static int pruss_probe(struct platform_device *pdev) 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"); @@ -45,7 +60,14 @@ static int pruss_probe(struct platform_device *pdev) return -ENODEV; } - for (i = 0; i < ARRAY_SIZE(mem_names); i++) { + 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) { @@ -126,8 +148,19 @@ static int pruss_remove(struct platform_device *pdev) 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 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, }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From ae19b8a145252d35d4d31d53799f823fe3e2ccbf Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:35 -0700 Subject: [PATCH 06/17] soc: ti: pruss: Add support for PRU-ICSS subsystems on AM57xx SoCs The AM57xx family of SoCs supports two PRU-ICSS instances, each of which has two PRU processor cores. The two PRU-ICSS instances are identical to each other, and are very similar to the PRU-ICSS1 of AM33xx/AM43xx except for a few minor differences like the RAM sizes and the number of interrupts coming into the MPU INTC. They do not have a programmable module reset line unlike those present on AM33xx/AM43xx SoCs. The modules are reset just like any other IP with the SoC's global cold/warm resets. Each PRU-ICSS's INTC is also preceded by a Crossbar that enables multiple external events to be routed to a specific number of input interrupt events. Any interrupt event directed towards PRUSS needs this crossbar to be setup properly on the firmware side. The existing PRUSS platform driver has been enhanced to support these AM57xx PRU-ICSS instances through new AM57xx specific compatible for properly probing and booting all the different PRU cores in each PRU-ICSS processor subsystem. A build dependency with SOC_DRA7XX is also added to enable the driver to be built in AM57xx-only configuration (there is no separate Kconfig option for AM57xx vs DRA7xx). Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 40d6a222275f..99dbc14e0d3e 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 04938ba6b150..5df4caa4bcf4 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -161,6 +161,7 @@ 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" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From 3227c8daac3c34bcb7cef374c57c83844851c31e Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:36 -0700 Subject: [PATCH 07/17] soc: ti: pruss: Add support for PRU-ICSS subsystems on 66AK2G SoC The 66AK2G SoC supports two PRU-ICSS instances, named PRUSS0 and PRUSS1, each of which has two PRU processor cores. The two PRU-ICSS instances are identical to each other with few minor SoC integration differences, and are very similar to the PRU-ICSS1 of AM57xx/AM43xx. The Shared Data RAM size is larger and the number of interrupts coming into MPU INTC is like the instances on AM437x. There are also few other differences attributing to integration in Keystone architecture (like no SYSCFG register or PRCM handshake protocols). Other IP level differences include different constant table, differences in system event interrupt input sources etc. They also do not have a programmable module reset line like those present on AM33xx/AM43xx SoCs. The modules are reset just like any other IP with the SoC's global cold/warm resets. The existing PRUSS platform driver has been enhanced to support these 66AK2G PRU-ICSS instances through new 66AK2G specific compatible for properly probing and booting all the different PRU cores in each PRU-ICSS processor subsystem. A build dependency with ARCH_KEYSTONE is added to enable the driver to be built in K2G-only configuration. Signed-off-by: Andrew F. Davis Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 99dbc14e0d3e..c29034321b50 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 5df4caa4bcf4..d5f128ec1e31 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -162,6 +162,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am4376-pruss0", .data = &am437x_pruss0_data, }, { .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, }, { .compatible = "ti,am5728-pruss" }, + { .compatible = "ti,k2g-pruss" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From 6530cd9b201db9a2f78c53a76b2dff4a5bf072fa Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:36 -0700 Subject: [PATCH 08/17] soc: ti: pruss: Enable support for ICSSG subsystems on K3 AM65x SoCs The K3 AM65x family of SoCs have the next generation of the PRU-ICSS processor subsystem capable of supporting Gigabit Ethernet, and is commonly referred to as ICSSG. These SoCs contain typically three ICSSG instances named ICSSG0, ICSSG1 and ICSSG2. The three ICSSGs are identical to each other for the most part with minor SoC integration differences and capabilities. The ICSSG2 supports slightly enhanced features like SGMII mode Ethernet, while the ICSS0 and ICSSG1 instances are limited to MII mode only. The ICSSGs on K3 AM65x SoCs are in general super-sets of the PRUSS on the AM57xx/66AK2G SoCs. They include two additional auxiliary PRU cores called RTUs and few other additional sub-modules. The interrupt integration is also different on the K3 AM65x SoCs and are propagated through various SoC-level Interrupt Router and Interrupt Aggregator blocks. Other IP level differences include different constant tables, differences in system event interrupt input sources etc. They also do not have a programmable module reset line like those present on AM33xx/AM43xx SoCs. The modules are reset just like any other IP with the SoC's global cold/warm resets. The existing pruss platform driver has been updated to support these new ICSSG instances through new AM65x specific compatibles. A build dependency with ARCH_K3 is added to enable building all the existing PRUSS platform drivers for this ARMv8 platform. Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/Kconfig | 2 +- drivers/soc/ti/pruss.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index c29034321b50..f5b82ffa637b 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -103,7 +103,7 @@ config TI_K3_SOCINFO config TI_PRUSS tristate "TI PRU-ICSS Subsystem Platform drivers" - depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE + depends on SOC_AM33XX || SOC_AM43XX || SOC_DRA7XX || ARCH_KEYSTONE || ARCH_K3 select MFD_SYSCON help TI PRU-ICSS Subsystem platform specific support. diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index d5f128ec1e31..ccc9783c123a 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -163,6 +163,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, }, { .compatible = "ti,am5728-pruss" }, { .compatible = "ti,k2g-pruss" }, + { .compatible = "ti,am654-icssg" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From 557003a98fb89e4841a8d9522c023ada145056d2 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Fri, 11 Sep 2020 21:43:37 -0700 Subject: [PATCH 09/17] soc: ti: pruss: Enable support for ICSSG subsystems on K3 J721E SoCs The K3 J721E family of SoCs have a revised version of the PRU-ICSS (ICSSG) processor subsystem present on K3 AM65x SoCs. These SoCs contain typically two ICSSG instances named ICSSG0 and ICSSG1. The two ICSSGs are identical to each other for the most part with minor SoC integration differences and capabilities. The ICSSG1 supports slightly enhanced features like SGMII mode Ethernet, while the ICSSG0 instance is limited to MII mode only. There is no change in the Interrupt Controller w.r.t AM65x. All other integration aspects are very similar to the ICSSGs on AM65x SoCs. The existing pruss platform driver has been updated to support these new ICSSG instances through new J721E specific compatibles. Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/pruss.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index ccc9783c123a..37df543998ef 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -164,6 +164,7 @@ static const struct of_device_id pruss_of_match[] = { { .compatible = "ti,am5728-pruss" }, { .compatible = "ti,k2g-pruss" }, { .compatible = "ti,am654-icssg" }, + { .compatible = "ti,j721e-icssg" }, {}, }; MODULE_DEVICE_TABLE(of, pruss_of_match); From efa5c01cd7ee20421a92ffe9b4aae7dfed385eeb Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 11 Sep 2020 21:47:08 -0700 Subject: [PATCH 10/17] soc: ti: ti_sci_pm_domains: switch to use multiple genpds instead of one Current implementation of the genpd support over TI SCI uses a single genpd across the whole SoC, and attaches multiple devices to this. This solution has its drawbacks, like it is currently impossible to attach more than one power domain to a device; the core genpd implementation requires one genpd per power-domain entry in DT for a single device. Also, some devices like USB apparently require their own genpd during probe time, the current shared approach in use does not work at all. Switch the implementation over to use a single genpd per power domain entry in DT. The domains are registered with the onecell approach, but we also add our own xlate service due to recent introduction of the extended flag for TI SCI PM domains; genpd core xlate service requires a single cell per powerdomain, but we are using two cells. Signed-off-by: Tero Kristo Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/ti_sci_pm_domains.c | 251 ++++++++++++++--------------- 1 file changed, 121 insertions(+), 130 deletions(-) diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c index 8c2a2f23982c..af2126d2b2ff 100644 --- a/drivers/soc/ti/ti_sci_pm_domains.c +++ b/drivers/soc/ti/ti_sci_pm_domains.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -18,150 +17,95 @@ #include /** - * struct ti_sci_genpd_dev_data: holds data needed for every device attached - * to this genpd - * @idx: index of the device that identifies it with the system - * control processor. - * @exclusive: Permissions for exclusive request or shared request of the - * device. + * struct ti_sci_genpd_provider: holds common TI SCI genpd provider data + * @ti_sci: handle to TI SCI protocol driver that provides ops to + * communicate with system control processor. + * @dev: pointer to dev for the driver for devm allocs + * @pd_list: list of all the power domains on the device + * @data: onecell data for genpd core */ -struct ti_sci_genpd_dev_data { - int idx; - u8 exclusive; +struct ti_sci_genpd_provider { + const struct ti_sci_handle *ti_sci; + 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 - * @ti_sci: handle to TI SCI protocol driver that provides ops to - * communicate with system control processor. - * @dev: pointer to dev for the driver for devm allocs + * @idx: index of the device that identifies it with the system + * control processor. + * @exclusive: Permissions for exclusive request or shared request of the + * device. * @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 { - const struct ti_sci_handle *ti_sci; - struct device *dev; + int idx; + u8 exclusive; 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) -/** - * ti_sci_dev_id(): get prepopulated ti_sci id from struct dev - * @dev: pointer to device associated with this genpd - * - * Returns device_id stored from ti,sci_id property +/* + * ti_sci_pd_power_off(): genpd power down hook + * @domain: pointer to the powerdomain to power off */ -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_genpd_dev_data *sci_dev_data = genpd_data->data; + struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain); + 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) -{ - struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev); - 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. +/* + * ti_sci_pd_power_on(): genpd power up hook + * @domain: pointer to the powerdomain to power on */ -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 *ti_sci_genpd = genpd_to_ti_sci_pd(pd); + struct ti_sci_pm_domain *pd = genpd_to_ti_sci_pd(domain); + const struct ti_sci_handle *ti_sci = pd->parent->ti_sci; - return ti_sci_genpd->ti_sci; -} - -/** - * 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); + if (pd->exclusive) + return ti_sci->ops.dev_ops.get_device_exclusive(ti_sci, + pd->idx); 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 - * @dev: pointer to device associated with this genpd to be powered off +/* + * ti_sci_pd_xlate(): translation service for TI SCI genpds + * @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); - int idx = ti_sci_dev_id(dev); + struct genpd_onecell_data *genpd_data = data; + 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, - struct device *dev) -{ - 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; + if (idx >= genpd_data->num_domains) { + pr_err("%s: invalid domain index %u\n", __func__, idx); + return ERR_PTR(-EINVAL); + } - ret = of_parse_phandle_with_args(np, "power-domains", - "#power-domain-cells", 0, &pd_args); - if (ret < 0) - return ret; + if (!genpd_data->domains[idx]) + return ERR_PTR(-ENOENT); - if (pd_args.args_count != 1 && pd_args.args_count != 2) - return -EINVAL; + genpd_to_ti_sci_pd(genpd_data->domains[idx])->exclusive = + genpdspec->args[1]; - idx = pd_args.args[0]; - - /* - * 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; + return genpd_data->domains[idx]; } 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) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct ti_sci_pm_domain *ti_sci_pd; + struct ti_sci_genpd_provider *pd_provider; + struct ti_sci_pm_domain *pd; + struct device_node *np = NULL; + struct of_phandle_args args; int ret; + u32 max_id = 0; + int index; - ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL); - if (!ti_sci_pd) + pd_provider = devm_kzalloc(dev, sizeof(*pd_provider), GFP_KERNEL); + if (!pd_provider) return -ENOMEM; - ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev); - if (IS_ERR(ti_sci_pd->ti_sci)) - return PTR_ERR(ti_sci_pd->ti_sci); + pd_provider->ti_sci = devm_ti_sci_get_handle(dev); + if (IS_ERR(pd_provider->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; - ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev; + /* Find highest device ID used for power domains */ + 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; - ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop; + index = 0; - 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 = { From 71b610825f4b2130901c7b6fbf4063f03350bcb9 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Fri, 11 Sep 2020 21:47:08 -0700 Subject: [PATCH 11/17] firmware: ti_sci: allow frequency change for disabled clocks by default If a clock is disabled, its frequency should be allowed to change as it is no longer in use. Add a flag towards this to the firmware clock API handler routines. Acked-by: Nishanth Menon Tested-by: Tomi Valkeinen Signed-off-by: Tero Kristo Signed-off-by: Santosh Shilimkar --- drivers/firmware/ti_sci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 53cee17d0115..39890665a975 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -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, 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); } @@ -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, 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); } From 25bafac9408f67873f03909401deecfb16974d84 Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Fri, 11 Sep 2020 21:47:09 -0700 Subject: [PATCH 12/17] dt-bindings: soc: ti: Update TI PRUSS bindings regarding clock-muxes ICSS/ICSSG modules have an IEP clock mux that allow selection of internal IEP clock from 2 clock sources. ICSSG module has a CORE clock mux that allows selection of internal CORE clock from 2 clock sources. Add binding information for these 2 clock muxes. Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- .../devicetree/bindings/soc/ti/ti,pruss.yaml | 121 +++++++++++++++++- 1 file changed, 120 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml index 482beefaac1f..cf7dc83f724f 100644 --- a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml +++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml @@ -132,10 +132,99 @@ patternProperties: - const: ti,pruss-cfg - const: syscon + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + reg: maxItems: 1 - additionalProperties: false + 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: | @@ -259,7 +348,22 @@ examples: 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 { @@ -298,7 +402,22 @@ examples: 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 { From ba59c9b43c86b2c2396acac94e41d946cbaec9fe Mon Sep 17 00:00:00 2001 From: Grzegorz Jaszczyk Date: Fri, 11 Sep 2020 21:47:10 -0700 Subject: [PATCH 13/17] soc: ti: pruss: support CORECLK_MUX and IEPCLK_MUX The IEPCLK_MUX is present on all SoCs whereas the CORECLK_MUX is present only on AM65x SoCs and J721E. Add support for both these CLK muxes. This allows the clock rates and clock parents for these to be controlled through DT leveraging the clk infrastructure for configuring the default parents and rates. Signed-off-by: Roger Quadros Signed-off-by: Suman Anna Signed-off-by: Grzegorz Jaszczyk Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/pruss.c | 184 +++++++++++++++++++++++++++++++++-- include/linux/pruss_driver.h | 6 ++ 2 files changed, 183 insertions(+), 7 deletions(-) diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c index 37df543998ef..cc0b4ad7a3d3 100644 --- a/drivers/soc/ti/pruss.c +++ b/drivers/soc/ti/pruss.c @@ -8,6 +8,7 @@ * Andrew F. Davis */ +#include #include #include #include @@ -16,13 +17,150 @@ #include #include #include +#include +#include /** * 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) @@ -114,21 +252,49 @@ static int pruss_probe(struct platform_device *pdev) goto rpm_put; } - pruss->cfg_regmap = syscon_node_to_regmap(child); - of_node_put(child); + 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)) { - ret = -ENODEV; - goto rpm_put; + 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 rpm_put; + goto node_put; } + of_node_put(child); + return 0; +node_put: + of_node_put(child); rpm_put: pm_runtime_put_sync(dev); rpm_disable: @@ -157,14 +323,18 @@ 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" }, - { .compatible = "ti,j721e-icssg" }, + { .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); diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h index 0701fe1953dd..ecfded30ed05 100644 --- a/include/linux/pruss_driver.h +++ b/include/linux/pruss_driver.h @@ -36,13 +36,19 @@ struct pruss_mem_region { /** * 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_ */ From 4f02044123b23660cee9d9dbea74383a58eb46b5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Sep 2020 21:47:39 -0700 Subject: [PATCH 14/17] soc: ti: k3-socinfo: Add entry for J7200 Update K3 chipinfo driver to support new TI J7200 SoC. It's JTAG PARTNO is 0xBB6D. Reviewed-by: Lokesh Vutla Reviewed-by: Grygorii Strashko Signed-off-by: Peter Ujfalusi Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/k3-socinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c index af0ba5288e58..bbbc2d2b7091 100644 --- a/drivers/soc/ti/k3-socinfo.c +++ b/drivers/soc/ti/k3-socinfo.c @@ -39,6 +39,7 @@ static const struct k3_soc_id { } k3_soc_ids[] = { { 0xBB5A, "AM65X" }, { 0xBB64, "J721E" }, + { 0xBB6D, "J7200" }, }; static int From 6259c8441c4de3f1727a0db61465a8dc8f340c05 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 11 Sep 2020 21:47:39 -0700 Subject: [PATCH 15/17] dmaengine: ti: k3-udma-glue: Fix parameters for rx ring pair request The original commit mixed up the forward and completion ring IDs for the rx flow configuration. Acked-by: Vinod Koul Reviewed-by: Grygorii Strashko Fixes: 4927b1ab2047 ("dmaengine: ti: k3-udma: Switch to k3_ringacc_request_rings_pair") Signed-off-by: Peter Ujfalusi Signed-off-by: Santosh Shilimkar --- drivers/dma/ti/k3-udma-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c index 3a5d33ea5ebe..12da38a92218 100644 --- a/drivers/dma/ti/k3-udma-glue.c +++ b/drivers/dma/ti/k3-udma-glue.c @@ -579,8 +579,8 @@ static int k3_udma_glue_cfg_rx_flow(struct k3_udma_glue_rx_channel *rx_chn, /* request and cfg rings */ ret = k3_ringacc_request_rings_pair(rx_chn->common.ringacc, - flow_cfg->ring_rxq_id, flow_cfg->ring_rxfdq0_id, + flow_cfg->ring_rxq_id, &flow->ringrxfdq, &flow->ringrx); if (ret) { From 74e0e43a09cea3189c12ad6a5444d313f45664ac Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Sun, 20 Sep 2020 19:30:30 -0700 Subject: [PATCH 16/17] soc: ti: Convert to DEFINE_SHOW_ATTRIBUTE Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Qinglang Miao Signed-off-by: Santosh Shilimkar --- drivers/soc/ti/knav_dma.c | 16 +++------------- drivers/soc/ti/knav_qmss_queue.c | 14 ++------------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index 6285cd8efb21..8c863ecb1c60 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -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; @@ -370,17 +370,7 @@ static int dma_debug_show(struct seq_file *s, void *v) return 0; } -static int knav_dma_debug_open(struct inode *inode, struct file *file) -{ - 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, -}; +DEFINE_SHOW_ATTRIBUTE(knav_dma_debug); static int of_channel_match_helper(struct device_node *np, const char *name, 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, - &knav_dma_debug_ops); + &knav_dma_debug_fops); device_ready = true; return ret; diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index aa071d96ef36..a460f201bf8e 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -478,17 +478,7 @@ static int knav_queue_debug_show(struct seq_file *s, void *v) return 0; } -static int knav_queue_debug_open(struct inode *inode, struct file *file) -{ - 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, -}; +DEFINE_SHOW_ATTRIBUTE(knav_queue_debug); static inline int knav_queue_pdsp_wait(u32 * __iomem addr, unsigned timeout, 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, - &knav_queue_debug_ops); + &knav_queue_debug_fops); device_ready = true; return 0; From dcca7a97c6bfff2a7a18b928a0b9bf215cc8f4f5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 20 Sep 2020 19:32:38 -0700 Subject: [PATCH 17/17] Add missing '#' to fix schema errors: $id: 'http://devicetree.org/schemas/soc/ti/ti,pruss.yaml' does not match 'http://devicetree.org/schemas/.*\\.yaml#' $schema: 'http://devicetree.org/meta-schemas/core.yaml' is not one of ['http://devicetree.org/meta-schemas/core.yaml#', 'http://devicetree.org/meta-schemas/base.yaml#'] Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml: ignoring, error in schema: $id Fixes: bd691ce0ba9d ("dt-bindings: soc: ti: Add TI PRUSS bindings") Acked-by: Suman Anna Signed-off-by: Krzysztof Kozlowski Signed-off-by: Santosh Shilimkar --- Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml index cf7dc83f724f..037c51b2f972 100644 --- a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml +++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml @@ -1,8 +1,8 @@ # 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 +$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