Commit 701a9c80 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver updates from Greg KH:
 "Here is the big char/misc/whatever driver changes for 5.6-rc1

  Included in here are loads of things from a variety of different
  driver subsystems:
   - soundwire updates
   - binder updates
   - nvmem updates
   - firmware drivers updates
   - extcon driver updates
   - various misc driver updates
   - fpga driver updates
   - interconnect subsystem and driver updates
   - bus driver updates
   - uio driver updates
   - mei driver updates
   - w1 driver cleanups
   - various other small driver updates

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (86 commits)
  mei: me: add jasper point DID
  char: hpet: Use flexible-array member
  binder: fix log spam for existing debugfs file creation.
  mei: me: add comet point (lake) H device ids
  nvmem: add QTI SDAM driver
  dt-bindings: nvmem: add binding for QTI SPMI SDAM
  dt-bindings: imx-ocotp: Add i.MX8MP compatible
  dt-bindings: soundwire: fix example
  soundwire: cadence: fix kernel-doc parameter descriptions
  soundwire: intel: report slave_ids for each link to SOF driver
  siox: Use the correct style for SPDX License Identifier
  w1: omap-hdq: Simplify driver with PM runtime autosuspend
  firmware: stratix10-svc: Remove unneeded semicolon
  firmware: google: Probe for a GSMI handler in firmware
  firmware: google: Unregister driver_info on failure and exit in gsmi
  firmware: google: Release devices before unregistering the bus
  slimbus: qcom: add missed clk_disable_unprepare in remove
  slimbus: Use the correct style for SPDX License Identifier
  slimbus: qcom-ngd-ctrl: Use dma_request_chan() instead dma_request_slave_channel()
  dt-bindings: SLIMBus: add slim devices optional properties
  ...
parents 975f9ce9 0db4a15d
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/interconnect/qcom,msm8916.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm MSM8916 Network-On-Chip interconnect
maintainers:
- Georgi Djakov <georgi.djakov@linaro.org>
description: |
The Qualcomm MSM8916 interconnect providers support adjusting the
bandwidth requirements between the various NoC fabrics.
properties:
compatible:
enum:
- qcom,msm8916-bimc
- qcom,msm8916-pcnoc
- qcom,msm8916-snoc
reg:
maxItems: 1
'#interconnect-cells':
const: 1
clock-names:
items:
- const: bus
- const: bus_a
clocks:
items:
- description: Bus Clock
- description: Bus A Clock
required:
- compatible
- reg
- '#interconnect-cells'
- clock-names
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmcc.h>
bimc: interconnect@400000 {
compatible = "qcom,msm8916-bimc";
reg = <0x00400000 0x62000>;
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
<&rpmcc RPM_SMD_BIMC_A_CLK>;
};
pcnoc: interconnect@500000 {
compatible = "qcom,msm8916-pcnoc";
reg = <0x00500000 0x11000>;
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_PCNOC_CLK>,
<&rpmcc RPM_SMD_PCNOC_A_CLK>;
};
snoc: interconnect@580000 {
compatible = "qcom,msm8916-snoc";
reg = <0x00580000 0x14000>;
#interconnect-cells = <1>;
clock-names = "bus", "bus_a";
clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
<&rpmcc RPM_SMD_SNOC_A_CLK>;
};
...@@ -2,7 +2,7 @@ Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings ...@@ -2,7 +2,7 @@ Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings
This binding represents the on-chip eFuse OTP controller found on This binding represents the on-chip eFuse OTP controller found on
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL, i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL,
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM and i.MX8MN SoCs. i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN and i.MX8MP SoCs.
Required properties: Required properties:
- compatible: should be one of - compatible: should be one of
...@@ -17,6 +17,7 @@ Required properties: ...@@ -17,6 +17,7 @@ Required properties:
"fsl,imx8mq-ocotp" (i.MX8MQ), "fsl,imx8mq-ocotp" (i.MX8MQ),
"fsl,imx8mm-ocotp" (i.MX8MM), "fsl,imx8mm-ocotp" (i.MX8MM),
"fsl,imx8mn-ocotp" (i.MX8MN), "fsl,imx8mn-ocotp" (i.MX8MN),
"fsl,imx8mp-ocotp" (i.MX8MP),
followed by "syscon". followed by "syscon".
- #address-cells : Should be 1 - #address-cells : Should be 1
- #size-cells : Should be 1 - #size-cells : Should be 1
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/nvmem/qcom,spmi-sdam.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SPMI SDAM DT bindings
maintainers:
- Shyam Kumar Thella <sthella@codeaurora.org>
description: |
The SDAM provides scratch register space for the PMIC clients. This
memory can be used by software to store information or communicate
to/from the PBUS.
allOf:
- $ref: "nvmem.yaml#"
properties:
compatible:
enum:
- qcom,spmi-sdam
reg:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 1
ranges: true
required:
- compatible
- reg
- ranges
patternProperties:
"^.*@[0-9a-f]+$":
type: object
properties:
reg:
maxItems: 1
description:
Offset and size in bytes within the storage device.
bits:
$ref: /schemas/types.yaml#/definitions/uint32-array
maxItems: 1
items:
items:
- minimum: 0
maximum: 7
description:
Offset in bit within the address range specified by reg.
- minimum: 1
description:
Size in bit within the address range specified by reg.
required:
- reg
additionalProperties: false
examples:
- |
sdam_1: nvram@b000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "qcom,spmi-sdam";
reg = <0xb000 0x100>;
ranges = <0 0xb000 0x100>;
/* Data cells */
restart_reason: restart@50 {
reg = <0x50 0x1>;
bits = <6 2>;
};
};
...
...@@ -32,6 +32,10 @@ Required property for SLIMbus child node if it is present: ...@@ -32,6 +32,10 @@ Required property for SLIMbus child node if it is present:
Product Code, shall be in lower case hexadecimal with leading Product Code, shall be in lower case hexadecimal with leading
zeroes suppressed zeroes suppressed
Optional property for SLIMbus child node if it is present:
- slim-ifc-dev - Should be phandle to SLIMBus Interface device.
Required for devices which deal with streams.
SLIMbus example for Qualcomm's slimbus manager component: SLIMbus example for Qualcomm's slimbus manager component:
slim@28080000 { slim@28080000 {
...@@ -43,8 +47,14 @@ SLIMbus example for Qualcomm's slimbus manager component: ...@@ -43,8 +47,14 @@ SLIMbus example for Qualcomm's slimbus manager component:
#address-cells = <2>; #address-cells = <2>;
#size-cell = <0>; #size-cell = <0>;
codec_ifd: ifd@0,0{
compatible = "slim217,60";
reg = <0 0>;
};
codec: wcd9310@1,0{ codec: wcd9310@1,0{
compatible = "slim217,60"; compatible = "slim217,60";
reg = <1 0>; reg = <1 0>;
slim-ifc-dev = <&codec_ifd>;
}; };
}; };
Qualcomm SoundWire Controller Bindings
This binding describes the Qualcomm SoundWire Controller along with its
board specific bus parameters.
- compatible:
Usage: required
Value type: <stringlist>
Definition: must be "qcom,soundwire-v<MAJOR>.<MINOR>.<STEP>",
Example:
"qcom,soundwire-v1.3.0"
"qcom,soundwire-v1.5.0"
"qcom,soundwire-v1.6.0"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: the base address and size of SoundWire controller
address space.
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the SoundWire Controller IRQ
- clock-names:
Usage: required
Value type: <stringlist>
Definition: should be "iface" for SoundWire Controller interface clock
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the SoundWire Controller interface clock
- #sound-dai-cells:
Usage: required
Value type: <u32>
Definition: must be 1 for digital audio interfaces on the controller.
- qcom,dout-ports:
Usage: required
Value type: <u32>
Definition: must be count of data out ports
- qcom,din-ports:
Usage: required
Value type: <u32>
Definition: must be count of data in ports
- qcom,ports-offset1:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify payload transport window offset1 of each
data port. Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-offset2:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify payload transport window offset2 of each
data port. Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-sinterval-low:
Usage: required
Value type: <prop-encoded-array>
Definition: should be sample interval low of each data port.
Out ports followed by In ports. Used for Sample Interval
calculation.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-word-length:
Usage: optional
Value type: <prop-encoded-array>
Definition: should be size of payload channel sample.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-block-pack-mode:
Usage: optional
Value type: <prop-encoded-array>
Definition: should be 0 or 1 to indicate the block packing mode.
0 to indicate Blocks are per Channel
1 to indicate Blocks are per Port.
Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-block-group-count:
Usage: optional
Value type: <prop-encoded-array>
Definition: should be in range 1 to 4 to indicate how many sample
intervals are combined into a payload.
Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-lane-control:
Usage: optional
Value type: <prop-encoded-array>
Definition: should be in range 0 to 7 to identify which data lane
the data port uses.
Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-hstart:
Usage: optional
Value type: <prop-encoded-array>
Definition: should be number identifying lowerst numbered coloum in
SoundWire Frame, i.e. left edge of the Transport sub-frame
for each port. Values between 0 and 15 are valid.
Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,ports-hstop:
Usage: optional
Value type: <prop-encoded-array>
Definition: should be number identifying highest numbered coloum in
SoundWire Frame, i.e. the right edge of the Transport
sub-frame for each port. Values between 0 and 15 are valid.
Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
- qcom,dports-type:
Usage: optional
Value type: <prop-encoded-array>
Definition: should be one of the following types
0 for reduced port
1 for simple ports
2 for full port
Out ports followed by In ports.
More info in MIPI Alliance SoundWire 1.0 Specifications.
Note:
More Information on detail of encoding of these fields can be
found in MIPI Alliance SoundWire 1.0 Specifications.
= SoundWire devices
Each subnode of the bus represents SoundWire device attached to it.
The properties of these nodes are defined by the individual bindings.
= EXAMPLE
The following example represents a SoundWire controller on DB845c board
which has controller integrated inside WCD934x codec on SDM845 SoC.
soundwire: soundwire@c85 {
compatible = "qcom,soundwire-v1.3.0";
reg = <0xc85 0x20>;
interrupts = <20 IRQ_TYPE_EDGE_RISING>;
clocks = <&wcc>;
clock-names = "iface";
#sound-dai-cells = <1>;
qcom,dports-type = <0>;
qcom,dout-ports = <6>;
qcom,din-ports = <2>;
qcom,ports-sinterval-low = /bits/ 8 <0x07 0x1F 0x3F 0x7 0x1F 0x3F 0x0F 0x0F>;
qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0C 0x6 0x12 0x0D 0x07 0x0A >;
qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x1F 0x00 0x00 0x1F 0x00 0x00>;
/* Left Speaker */
left{
....
};
/* Right Speaker */
right{
....
};
};
...@@ -69,6 +69,7 @@ examples: ...@@ -69,6 +69,7 @@ examples:
reg = <0 1>; reg = <0 1>;
powerdown-gpios = <&wcdpinctrl 2 0>; powerdown-gpios = <&wcdpinctrl 2 0>;
#thermal-sensor-cells = <0>; #thermal-sensor-cells = <0>;
#sound-dai-cells = <0>;
}; };
speaker@0,2 { speaker@0,2 {
...@@ -76,6 +77,7 @@ examples: ...@@ -76,6 +77,7 @@ examples:
reg = <0 2>; reg = <0 2>;
powerdown-gpios = <&wcdpinctrl 2 0>; powerdown-gpios = <&wcdpinctrl 2 0>;
#thermal-sensor-cells = <0>; #thermal-sensor-cells = <0>;
#sound-dai-cells = <0>;
}; };
}; };
......
...@@ -91,3 +91,25 @@ Interconnect consumers are the clients which use the interconnect APIs to ...@@ -91,3 +91,25 @@ Interconnect consumers are the clients which use the interconnect APIs to
get paths between endpoints and set their bandwidth/latency/QoS requirements get paths between endpoints and set their bandwidth/latency/QoS requirements
for these interconnect paths. These interfaces are not currently for these interconnect paths. These interfaces are not currently
documented. documented.
Interconnect debugfs interfaces
-------------------------------
Like several other subsystems interconnect will create some files for debugging
and introspection. Files in debugfs are not considered ABI so application
software shouldn't rely on format details change between kernel versions.
``/sys/kernel/debug/interconnect/interconnect_summary``:
Show all interconnect nodes in the system with their aggregated bandwidth
request. Indented under each node show bandwidth requests from each device.
``/sys/kernel/debug/interconnect/interconnect_graph``:
Show the interconnect graph in the graphviz dot format. It shows all
interconnect nodes and links in the system and groups together nodes from the
same provider as subgraphs. The format is human-readable and can also be piped
through dot to generate diagrams in many graphical formats::
$ cat /sys/kernel/debug/interconnect/interconnect_graph | \
dot -Tsvg > interconnect_graph.svg
...@@ -5199,10 +5199,11 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -5199,10 +5199,11 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
static int binder_open(struct inode *nodp, struct file *filp) static int binder_open(struct inode *nodp, struct file *filp)
{ {
struct binder_proc *proc; struct binder_proc *proc, *itr;
struct binder_device *binder_dev; struct binder_device *binder_dev;
struct binderfs_info *info; struct binderfs_info *info;
struct dentry *binder_binderfs_dir_entry_proc = NULL; struct dentry *binder_binderfs_dir_entry_proc = NULL;
bool existing_pid = false;
binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
current->group_leader->pid, current->pid); current->group_leader->pid, current->pid);
...@@ -5235,19 +5236,24 @@ static int binder_open(struct inode *nodp, struct file *filp) ...@@ -5235,19 +5236,24 @@ static int binder_open(struct inode *nodp, struct file *filp)
filp->private_data = proc; filp->private_data = proc;
mutex_lock(&binder_procs_lock); mutex_lock(&binder_procs_lock);
hlist_for_each_entry(itr, &binder_procs, proc_node) {
if (itr->pid == proc->pid) {
existing_pid = true;
break;
}
}
hlist_add_head(&proc->proc_node, &binder_procs); hlist_add_head(&proc->proc_node, &binder_procs);
mutex_unlock(&binder_procs_lock); mutex_unlock(&binder_procs_lock);
if (binder_debugfs_dir_entry_proc) { if (binder_debugfs_dir_entry_proc && !existing_pid) {
char strbuf[11]; char strbuf[11];
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
/* /*
* proc debug entries are shared between contexts, so * proc debug entries are shared between contexts.
* this will fail if the process tries to open the driver * Only create for the first PID to avoid debugfs log spamming
* again with a different context. The priting code will * The printing code will anyway print all contexts for a given
* anyway print all contexts that a given PID has, so this * PID so this is not a problem.
* is not a problem.
*/ */
proc->debugfs_entry = debugfs_create_file(strbuf, 0444, proc->debugfs_entry = debugfs_create_file(strbuf, 0444,
binder_debugfs_dir_entry_proc, binder_debugfs_dir_entry_proc,
...@@ -5255,19 +5261,16 @@ static int binder_open(struct inode *nodp, struct file *filp) ...@@ -5255,19 +5261,16 @@ static int binder_open(struct inode *nodp, struct file *filp)
&proc_fops); &proc_fops);
} }
if (binder_binderfs_dir_entry_proc) { if (binder_binderfs_dir_entry_proc && !existing_pid) {
char strbuf[11]; char strbuf[11];
struct dentry *binderfs_entry; struct dentry *binderfs_entry;
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
/* /*
* Similar to debugfs, the process specific log file is shared * Similar to debugfs, the process specific log file is shared
* between contexts. If the file has already been created for a * between contexts. Only create for the first PID.
* process, the following binderfs_create_file() call will * This is ok since same as debugfs, the log file will contain
* fail with error code EEXIST if another context of the same * information on all contexts of a given PID.
* process invoked binder_open(). This is ok since same as
* debugfs, the log file will contain information on all
* contexts of a given PID.
*/ */
binderfs_entry = binderfs_create_file(binder_binderfs_dir_entry_proc, binderfs_entry = binderfs_create_file(binder_binderfs_dir_entry_proc,
strbuf, &proc_fops, (void *)(unsigned long)proc->pid); strbuf, &proc_fops, (void *)(unsigned long)proc->pid);
...@@ -5277,12 +5280,10 @@ static int binder_open(struct inode *nodp, struct file *filp) ...@@ -5277,12 +5280,10 @@ static int binder_open(struct inode *nodp, struct file *filp)
int error; int error;
error = PTR_ERR(binderfs_entry); error = PTR_ERR(binderfs_entry);
if (error != -EEXIST) {
pr_warn("Unable to create file %s in binderfs (error %d)\n", pr_warn("Unable to create file %s in binderfs (error %d)\n",
strbuf, error); strbuf, error);
} }
} }
}
return 0; return 0;
} }
......
...@@ -715,9 +715,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_remove); ...@@ -715,9 +715,9 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev) struct fsl_mc_device *fsl_mc_get_endpoint(struct fsl_mc_device *mc_dev)
{ {
struct fsl_mc_device *mc_bus_dev, *endpoint; struct fsl_mc_device *mc_bus_dev, *endpoint;
struct fsl_mc_obj_desc endpoint_desc = { 0 }; struct fsl_mc_obj_desc endpoint_desc = {{ 0 }};
struct dprc_endpoint endpoint1 = { 0 }; struct dprc_endpoint endpoint1 = {{ 0 }};
struct dprc_endpoint endpoint2 = { 0 }; struct dprc_endpoint endpoint2 = {{ 0 }};
int state, err; int state, err;
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
......
...@@ -110,7 +110,7 @@ struct hpets { ...@@ -110,7 +110,7 @@ struct hpets {
unsigned long hp_delta; unsigned long hp_delta;
unsigned int hp_ntimer; unsigned int hp_ntimer;
unsigned int hp_which; unsigned int hp_which;
struct hpet_dev hp_dev[1]; struct hpet_dev hp_dev[];
}; };
static struct hpets *hpets; static struct hpets *hpets;
......
This diff is collapsed.
...@@ -249,7 +249,7 @@ static int sm5502_muic_set_path(struct sm5502_muic_info *info, ...@@ -249,7 +249,7 @@ static int sm5502_muic_set_path(struct sm5502_muic_info *info,
dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n", dev_err(info->dev, "Unknown DM_CON/DP_CON switch type (%d)\n",
con_sw); con_sw);
return -EINVAL; return -EINVAL;
}; }
switch (vbus_sw) { switch (vbus_sw) {
case VBUSIN_SWITCH_OPEN: case VBUSIN_SWITCH_OPEN:
...@@ -268,7 +268,7 @@ static int sm5502_muic_set_path(struct sm5502_muic_info *info, ...@@ -268,7 +268,7 @@ static int sm5502_muic_set_path(struct sm5502_muic_info *info,
default: default:
dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw); dev_err(info->dev, "Unknown VBUS switch type (%d)\n", vbus_sw);
return -EINVAL; return -EINVAL;
}; }
return 0; return 0;
} }
...@@ -357,13 +357,13 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info) ...@@ -357,13 +357,13 @@ static unsigned int sm5502_muic_get_cable_type(struct sm5502_muic_info *info)
"cannot identify the cable type: adc(0x%x)\n", "cannot identify the cable type: adc(0x%x)\n",
adc); adc);
return -EINVAL; return -EINVAL;
}; }
break; break;
default: default:
dev_err(info->dev, dev_err(info->dev,
"failed to identify the cable type: adc(0x%x)\n", adc); "failed to identify the cable type: adc(0x%x)\n", adc);
return -EINVAL; return -EINVAL;
}; }
return cable_type; return cable_type;
} }
...@@ -405,7 +405,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, ...@@ -405,7 +405,7 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info,
dev_dbg(info->dev, dev_dbg(info->dev,
"cannot handle this cable_type (0x%x)\n", cable_type); "cannot handle this cable_type (0x%x)\n", cable_type);
return 0; return 0;
}; }
/* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */ /* Change internal hardware path(DM_CON/DP_CON, VBUSIN) */
ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached); ret = sm5502_muic_set_path(info, con_sw, vbus_sw, attached);
......
...@@ -163,8 +163,15 @@ static int coreboot_table_probe(struct platform_device *pdev) ...@@ -163,8 +163,15 @@ static int coreboot_table_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int __cb_dev_unregister(struct device *dev, void *dummy)
{
device_unregister(dev);
return 0;
}
static int coreboot_table_remove(struct platform_device *pdev) static int coreboot_table_remove(struct platform_device *pdev)
{ {
bus_for_each_dev(&coreboot_bus_type, NULL, NULL, __cb_dev_unregister);
bus_unregister(&coreboot_bus_type); bus_unregister(&coreboot_bus_type);
return 0; return 0;
} }
......
...@@ -76,6 +76,7 @@ ...@@ -76,6 +76,7 @@
#define GSMI_CMD_LOG_S0IX_RESUME 0x0b #define GSMI_CMD_LOG_S0IX_RESUME 0x0b
#define GSMI_CMD_CLEAR_CONFIG 0x20 #define GSMI_CMD_CLEAR_CONFIG 0x20
#define GSMI_CMD_HANDSHAKE_TYPE 0xC1 #define GSMI_CMD_HANDSHAKE_TYPE 0xC1
#define GSMI_CMD_RESERVED 0xff
/* Magic entry type for kernel events */ /* Magic entry type for kernel events */
#define GSMI_LOG_ENTRY_TYPE_KERNEL 0xDEAD #define GSMI_LOG_ENTRY_TYPE_KERNEL 0xDEAD
...@@ -746,6 +747,7 @@ MODULE_DEVICE_TABLE(dmi, gsmi_dmi_table); ...@@ -746,6 +747,7 @@ MODULE_DEVICE_TABLE(dmi, gsmi_dmi_table);
static __init int gsmi_system_valid(void) static __init int gsmi_system_valid(void)
{ {
u32 hash; u32 hash;
u16 cmd, result;
if (!dmi_check_system(gsmi_dmi_table)) if (!dmi_check_system(gsmi_dmi_table))
return -ENODEV; return -ENODEV;
...@@ -780,6 +782,23 @@ static __init int gsmi_system_valid(void) ...@@ -780,6 +782,23 @@ static __init int gsmi_system_valid(void)
return -ENODEV; return -ENODEV;
} }
/* Test the smihandler with a bogus command. If it leaves the
* calling argument in %ax untouched, there is no handler for
* GSMI commands.
*/
cmd = GSMI_CALLBACK | GSMI_CMD_RESERVED << 8;
asm volatile (
"outb %%al, %%dx\n\t"
: "=a" (result)
: "0" (cmd),
"d" (acpi_gbl_FADT.smi_command)
: "memory", "cc"
);
if (cmd == result) {
pr_info("gsmi: no gsmi handler in firmware\n");
return -ENODEV;
}
/* Found */ /* Found */
return 0; return 0;
} }
...@@ -1016,6 +1035,9 @@ static __init int gsmi_init(void) ...@@ -1016,6 +1035,9 @@ static __init int gsmi_init(void)
dma_pool_destroy(gsmi_dev.dma_pool); dma_pool_destroy(gsmi_dev.dma_pool);
platform_device_unregister(gsmi_dev.pdev); platform_device_unregister(gsmi_dev.pdev);
pr_info("gsmi: failed to load: %d\n", ret); pr_info("gsmi: failed to load: %d\n", ret);
#ifdef CONFIG_PM
platform_driver_unregister(&gsmi_driver_info);
#endif
return ret; return ret;
} }
...@@ -1037,6 +1059,9 @@ static void __exit gsmi_exit(void) ...@@ -1037,6 +1059,9 @@ static void __exit gsmi_exit(void)
gsmi_buf_free(gsmi_dev.name_buf); gsmi_buf_free(gsmi_dev.name_buf);
dma_pool_destroy(gsmi_dev.dma_pool); dma_pool_destroy(gsmi_dev.dma_pool);
platform_device_unregister(gsmi_dev.pdev); platform_device_unregister(gsmi_dev.pdev);
#ifdef CONFIG_PM
platform_driver_unregister(&gsmi_driver_info);
#endif
} }
module_init(gsmi_init); module_init(gsmi_init);
......
...@@ -268,7 +268,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl, ...@@ -268,7 +268,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl,
*/ */
msleep(1000); msleep(1000);
count_in_sec--; count_in_sec--;
}; }
if (res.a0 == INTEL_SIP_SMC_STATUS_OK && count_in_sec) if (res.a0 == INTEL_SIP_SMC_STATUS_OK && count_in_sec)
cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED); cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED);
...@@ -512,7 +512,7 @@ static int svc_normal_to_secure_thread(void *data) ...@@ -512,7 +512,7 @@ static int svc_normal_to_secure_thread(void *data)
break; break;
} }
}; }
kfree(cbdata); kfree(cbdata);
kfree(pdata); kfree(pdata);
......
...@@ -813,10 +813,8 @@ static int afu_dev_init(struct platform_device *pdev) ...@@ -813,10 +813,8 @@ static int afu_dev_init(struct platform_device *pdev)
static int afu_dev_destroy(struct platform_device *pdev) static int afu_dev_destroy(struct platform_device *pdev)
{ {
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_afu *afu;
mutex_lock(&pdata->lock); mutex_lock(&pdata->lock);
afu = dfl_fpga_pdata_get_private(pdata);
afu_mmio_region_destroy(pdata); afu_mmio_region_destroy(pdata);
afu_dma_region_destroy(pdata); afu_dma_region_destroy(pdata);
dfl_fpga_pdata_set_private(pdata, NULL); dfl_fpga_pdata_set_private(pdata, NULL);
......
...@@ -675,10 +675,8 @@ static int fme_dev_init(struct platform_device *pdev) ...@@ -675,10 +675,8 @@ static int fme_dev_init(struct platform_device *pdev)
static void fme_dev_destroy(struct platform_device *pdev) static void fme_dev_destroy(struct platform_device *pdev)
{ {
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev); struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_fme *fme;
mutex_lock(&pdata->lock); mutex_lock(&pdata->lock);
fme = dfl_fpga_pdata_get_private(pdata);
dfl_fpga_pdata_set_private(pdata, NULL); dfl_fpga_pdata_set_private(pdata, NULL);
mutex_unlock(&pdata->lock); mutex_unlock(&pdata->lock);
} }
......
...@@ -119,10 +119,8 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) ...@@ -119,10 +119,8 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->io_base = devm_ioremap_resource(kdev, res); priv->io_base = devm_ioremap_resource(kdev, res);
if (IS_ERR(priv->io_base)) { if (IS_ERR(priv->io_base))
dev_err(kdev, "unable to remap registers\n");
return PTR_ERR(priv->io_base); return PTR_ERR(priv->io_base);
}
mgr = devm_fpga_mgr_create(kdev, "TS-73xx FPGA Manager", mgr = devm_fpga_mgr_create(kdev, "TS-73xx FPGA Manager",
&ts73xx_fpga_ops, priv); &ts73xx_fpga_ops, priv);
......
...@@ -101,6 +101,7 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) ...@@ -101,6 +101,7 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
priv->clk = devm_clk_get(&pdev->dev, "aclk"); priv->clk = devm_clk_get(&pdev->dev, "aclk");
if (IS_ERR(priv->clk)) { if (IS_ERR(priv->clk)) {
if (PTR_ERR(priv->clk) != -EPROBE_DEFER)
dev_err(&pdev->dev, "input clock not found\n"); dev_err(&pdev->dev, "input clock not found\n");
return PTR_ERR(priv->clk); return PTR_ERR(priv->clk);
} }
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
CFLAGS_core.o := -I$(src)
icc-core-objs := core.o icc-core-objs := core.o
obj-$(CONFIG_INTERCONNECT) += icc-core.o obj-$(CONFIG_INTERCONNECT) += icc-core.o
......
...@@ -19,45 +19,22 @@ ...@@ -19,45 +19,22 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/overflow.h> #include <linux/overflow.h>
#include "internal.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
static DEFINE_IDR(icc_idr); static DEFINE_IDR(icc_idr);
static LIST_HEAD(icc_providers); static LIST_HEAD(icc_providers);
static DEFINE_MUTEX(icc_lock); static DEFINE_MUTEX(icc_lock);
static struct dentry *icc_debugfs_dir; static struct dentry *icc_debugfs_dir;
/**
* struct icc_req - constraints that are attached to each node
* @req_node: entry in list of requests for the particular @node
* @node: the interconnect node to which this constraint applies
* @dev: reference to the device that sets the constraints
* @tag: path tag (optional)
* @avg_bw: an integer describing the average bandwidth in kBps
* @peak_bw: an integer describing the peak bandwidth in kBps
*/
struct icc_req {
struct hlist_node req_node;
struct icc_node *node;
struct device *dev;
u32 tag;
u32 avg_bw;
u32 peak_bw;
};
/**
* struct icc_path - interconnect path structure
* @num_nodes: number of hops (nodes)
* @reqs: array of the requests applicable to this path of nodes
*/
struct icc_path {
size_t num_nodes;
struct icc_req reqs[];
};
static void icc_summary_show_one(struct seq_file *s, struct icc_node *n) static void icc_summary_show_one(struct seq_file *s, struct icc_node *n)
{ {
if (!n) if (!n)
return; return;
seq_printf(s, "%-30s %12u %12u\n", seq_printf(s, "%-42s %12u %12u\n",
n->name, n->avg_bw, n->peak_bw); n->name, n->avg_bw, n->peak_bw);
} }
...@@ -65,8 +42,8 @@ static int icc_summary_show(struct seq_file *s, void *data) ...@@ -65,8 +42,8 @@ static int icc_summary_show(struct seq_file *s, void *data)
{ {
struct icc_provider *provider; struct icc_provider *provider;
seq_puts(s, " node avg peak\n"); seq_puts(s, " node tag avg peak\n");
seq_puts(s, "--------------------------------------------------------\n"); seq_puts(s, "--------------------------------------------------------------------\n");
mutex_lock(&icc_lock); mutex_lock(&icc_lock);
...@@ -81,8 +58,8 @@ static int icc_summary_show(struct seq_file *s, void *data) ...@@ -81,8 +58,8 @@ static int icc_summary_show(struct seq_file *s, void *data)
if (!r->dev) if (!r->dev)
continue; continue;
seq_printf(s, " %-26s %12u %12u\n", seq_printf(s, " %-27s %12u %12u %12u\n",
dev_name(r->dev), r->avg_bw, dev_name(r->dev), r->tag, r->avg_bw,
r->peak_bw); r->peak_bw);
} }
} }
...@@ -94,6 +71,70 @@ static int icc_summary_show(struct seq_file *s, void *data) ...@@ -94,6 +71,70 @@ static int icc_summary_show(struct seq_file *s, void *data)
} }
DEFINE_SHOW_ATTRIBUTE(icc_summary); DEFINE_SHOW_ATTRIBUTE(icc_summary);
static void icc_graph_show_link(struct seq_file *s, int level,
struct icc_node *n, struct icc_node *m)
{
seq_printf(s, "%s\"%d:%s\" -> \"%d:%s\"\n",
level == 2 ? "\t\t" : "\t",
n->id, n->name, m->id, m->name);
}
static void icc_graph_show_node(struct seq_file *s, struct icc_node *n)
{
seq_printf(s, "\t\t\"%d:%s\" [label=\"%d:%s",
n->id, n->name, n->id, n->name);
seq_printf(s, "\n\t\t\t|avg_bw=%ukBps", n->avg_bw);
seq_printf(s, "\n\t\t\t|peak_bw=%ukBps", n->peak_bw);
seq_puts(s, "\"]\n");
}
static int icc_graph_show(struct seq_file *s, void *data)
{
struct icc_provider *provider;
struct icc_node *n;
int cluster_index = 0;
int i;
seq_puts(s, "digraph {\n\trankdir = LR\n\tnode [shape = record]\n");
mutex_lock(&icc_lock);
/* draw providers as cluster subgraphs */
cluster_index = 0;
list_for_each_entry(provider, &icc_providers, provider_list) {
seq_printf(s, "\tsubgraph cluster_%d {\n", ++cluster_index);
if (provider->dev)
seq_printf(s, "\t\tlabel = \"%s\"\n",
dev_name(provider->dev));
/* draw nodes */
list_for_each_entry(n, &provider->nodes, node_list)
icc_graph_show_node(s, n);
/* draw internal links */
list_for_each_entry(n, &provider->nodes, node_list)
for (i = 0; i < n->num_links; ++i)
if (n->provider == n->links[i]->provider)
icc_graph_show_link(s, 2, n,
n->links[i]);
seq_puts(s, "\t}\n");
}
/* draw external links */
list_for_each_entry(provider, &icc_providers, provider_list)
list_for_each_entry(n, &provider->nodes, node_list)
for (i = 0; i < n->num_links; ++i)
if (n->provider != n->links[i]->provider)
icc_graph_show_link(s, 1, n,
n->links[i]);
mutex_unlock(&icc_lock);
seq_puts(s, "}");
return 0;
}
DEFINE_SHOW_ATTRIBUTE(icc_graph);
static struct icc_node *node_find(const int id) static struct icc_node *node_find(const int id)
{ {
return idr_find(&icc_idr, id); return idr_find(&icc_idr, id);
...@@ -244,6 +285,16 @@ static int apply_constraints(struct icc_path *path) ...@@ -244,6 +285,16 @@ static int apply_constraints(struct icc_path *path)
return ret; return ret;
} }
int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
EXPORT_SYMBOL_GPL(icc_std_aggregate);
/* of_icc_xlate_onecell() - Translate function using a single index. /* of_icc_xlate_onecell() - Translate function using a single index.
* @spec: OF phandle args to map into an interconnect node. * @spec: OF phandle args to map into an interconnect node.
* @data: private data (pointer to struct icc_onecell_data) * @data: private data (pointer to struct icc_onecell_data)
...@@ -382,9 +433,17 @@ struct icc_path *of_icc_get(struct device *dev, const char *name) ...@@ -382,9 +433,17 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
mutex_lock(&icc_lock); mutex_lock(&icc_lock);
path = path_find(dev, src_node, dst_node); path = path_find(dev, src_node, dst_node);
if (IS_ERR(path))
dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
mutex_unlock(&icc_lock); mutex_unlock(&icc_lock);
if (IS_ERR(path)) {
dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
return path;
}
if (name)
path->name = kstrdup_const(name, GFP_KERNEL);
else
path->name = kasprintf(GFP_KERNEL, "%s-%s",
src_node->name, dst_node->name);
return path; return path;
} }
...@@ -436,9 +495,12 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) ...@@ -436,9 +495,12 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
size_t i; size_t i;
int ret; int ret;
if (!path || !path->num_nodes) if (!path)
return 0; return 0;
if (WARN_ON(IS_ERR(path) || !path->num_nodes))
return -EINVAL;
mutex_lock(&icc_lock); mutex_lock(&icc_lock);
old_avg = path->reqs[0].avg_bw; old_avg = path->reqs[0].avg_bw;
...@@ -453,6 +515,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) ...@@ -453,6 +515,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
/* aggregate requests for this node */ /* aggregate requests for this node */
aggregate_requests(node); aggregate_requests(node);
trace_icc_set_bw(path, node, i, avg_bw, peak_bw);
} }
ret = apply_constraints(path); ret = apply_constraints(path);
...@@ -471,6 +535,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw) ...@@ -471,6 +535,8 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
mutex_unlock(&icc_lock); mutex_unlock(&icc_lock);
trace_icc_set_bw_end(path, ret);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(icc_set_bw); EXPORT_SYMBOL_GPL(icc_set_bw);
...@@ -507,9 +573,12 @@ struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id) ...@@ -507,9 +573,12 @@ struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id)
goto out; goto out;
path = path_find(dev, src, dst); path = path_find(dev, src, dst);
if (IS_ERR(path)) if (IS_ERR(path)) {
dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path)); dev_err(dev, "%s: invalid path=%ld\n", __func__, PTR_ERR(path));
goto out;
}
path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name);
out: out:
mutex_unlock(&icc_lock); mutex_unlock(&icc_lock);
return path; return path;
...@@ -545,6 +614,7 @@ void icc_put(struct icc_path *path) ...@@ -545,6 +614,7 @@ void icc_put(struct icc_path *path)
} }
mutex_unlock(&icc_lock); mutex_unlock(&icc_lock);
kfree_const(path->name);
kfree(path); kfree(path);
} }
EXPORT_SYMBOL_GPL(icc_put); EXPORT_SYMBOL_GPL(icc_put);
...@@ -742,6 +812,28 @@ void icc_node_del(struct icc_node *node) ...@@ -742,6 +812,28 @@ void icc_node_del(struct icc_node *node)
} }
EXPORT_SYMBOL_GPL(icc_node_del); EXPORT_SYMBOL_GPL(icc_node_del);
/**
* icc_nodes_remove() - remove all previously added nodes from provider
* @provider: the interconnect provider we are removing nodes from
*
* Return: 0 on success, or an error code otherwise
*/
int icc_nodes_remove(struct icc_provider *provider)
{
struct icc_node *n, *tmp;
if (WARN_ON(IS_ERR_OR_NULL(provider)))
return -EINVAL;
list_for_each_entry_safe_reverse(n, tmp, &provider->nodes, node_list) {
icc_node_del(n);
icc_node_destroy(n->id);
}
return 0;
}
EXPORT_SYMBOL_GPL(icc_nodes_remove);
/** /**
* icc_provider_add() - add a new interconnect provider * icc_provider_add() - add a new interconnect provider
* @provider: the interconnect provider that will be added into topology * @provider: the interconnect provider that will be added into topology
...@@ -802,6 +894,8 @@ static int __init icc_init(void) ...@@ -802,6 +894,8 @@ static int __init icc_init(void)
icc_debugfs_dir = debugfs_create_dir("interconnect", NULL); icc_debugfs_dir = debugfs_create_dir("interconnect", NULL);
debugfs_create_file("interconnect_summary", 0444, debugfs_create_file("interconnect_summary", 0444,
icc_debugfs_dir, NULL, &icc_summary_fops); icc_debugfs_dir, NULL, &icc_summary_fops);
debugfs_create_file("interconnect_graph", 0444,
icc_debugfs_dir, NULL, &icc_graph_fops);
return 0; return 0;
} }
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Interconnect framework internal structs
*
* Copyright (c) 2019, Linaro Ltd.
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#ifndef __DRIVERS_INTERCONNECT_INTERNAL_H
#define __DRIVERS_INTERCONNECT_INTERNAL_H
/**
* struct icc_req - constraints that are attached to each node
* @req_node: entry in list of requests for the particular @node
* @node: the interconnect node to which this constraint applies
* @dev: reference to the device that sets the constraints
* @tag: path tag (optional)
* @avg_bw: an integer describing the average bandwidth in kBps
* @peak_bw: an integer describing the peak bandwidth in kBps
*/
struct icc_req {
struct hlist_node req_node;
struct icc_node *node;
struct device *dev;
u32 tag;
u32 avg_bw;
u32 peak_bw;
};
/**
* struct icc_path - interconnect path structure
* @name: a string name of the path (useful for ftrace)
* @num_nodes: number of hops (nodes)
* @reqs: array of the requests applicable to this path of nodes
*/
struct icc_path {
const char *name;
size_t num_nodes;
struct icc_req reqs[];
};
#endif
...@@ -5,6 +5,15 @@ config INTERCONNECT_QCOM ...@@ -5,6 +5,15 @@ config INTERCONNECT_QCOM
help help
Support for Qualcomm's Network-on-Chip interconnect hardware. Support for Qualcomm's Network-on-Chip interconnect hardware.
config INTERCONNECT_QCOM_MSM8916
tristate "Qualcomm MSM8916 interconnect driver"
depends on INTERCONNECT_QCOM
depends on QCOM_SMD_RPM
select INTERCONNECT_QCOM_SMD_RPM
help
This is a driver for the Qualcomm Network-on-Chip on msm8916-based
platforms.
config INTERCONNECT_QCOM_MSM8974 config INTERCONNECT_QCOM_MSM8974
tristate "Qualcomm MSM8974 interconnect driver" tristate "Qualcomm MSM8974 interconnect driver"
depends on INTERCONNECT_QCOM depends on INTERCONNECT_QCOM
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
qnoc-msm8916-objs := msm8916.o
qnoc-msm8974-objs := msm8974.o qnoc-msm8974-objs := msm8974.o
qnoc-qcs404-objs := qcs404.o qnoc-qcs404-objs := qcs404.o
qnoc-sdm845-objs := sdm845.o qnoc-sdm845-objs := sdm845.o
icc-smd-rpm-objs := smd-rpm.o icc-smd-rpm-objs := smd-rpm.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o obj-$(CONFIG_INTERCONNECT_QCOM_SDM845) += qnoc-sdm845.o
......
This diff is collapsed.
...@@ -550,15 +550,6 @@ static struct msm8974_icc_desc msm8974_snoc = { ...@@ -550,15 +550,6 @@ static struct msm8974_icc_desc msm8974_snoc = {
.num_nodes = ARRAY_SIZE(msm8974_snoc_nodes), .num_nodes = ARRAY_SIZE(msm8974_snoc_nodes),
}; };
static int msm8974_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
static void msm8974_icc_rpm_smd_send(struct device *dev, int rsc_type, static void msm8974_icc_rpm_smd_send(struct device *dev, int rsc_type,
char *name, int id, u64 val) char *name, int id, u64 val)
{ {
...@@ -603,7 +594,7 @@ static int msm8974_icc_set(struct icc_node *src, struct icc_node *dst) ...@@ -603,7 +594,7 @@ static int msm8974_icc_set(struct icc_node *src, struct icc_node *dst)
qp = to_msm8974_icc_provider(provider); qp = to_msm8974_icc_provider(provider);
list_for_each_entry(n, &provider->nodes, node_list) list_for_each_entry(n, &provider->nodes, node_list)
msm8974_icc_aggregate(n, 0, n->avg_bw, n->peak_bw, provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
&agg_avg, &agg_peak); &agg_avg, &agg_peak);
sum_bw = icc_units_to_bps(agg_avg); sum_bw = icc_units_to_bps(agg_avg);
...@@ -652,7 +643,7 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -652,7 +643,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct icc_onecell_data *data; struct icc_onecell_data *data;
struct icc_provider *provider; struct icc_provider *provider;
struct icc_node *node, *tmp; struct icc_node *node;
size_t num_nodes, i; size_t num_nodes, i;
int ret; int ret;
...@@ -694,7 +685,7 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -694,7 +685,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&provider->nodes); INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev; provider->dev = dev;
provider->set = msm8974_icc_set; provider->set = msm8974_icc_set;
provider->aggregate = msm8974_icc_aggregate; provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell; provider->xlate = of_icc_xlate_onecell;
provider->data = data; provider->data = data;
...@@ -732,10 +723,7 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -732,10 +723,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
return 0; return 0;
err_del_icc: err_del_icc:
list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) { icc_nodes_remove(provider);
icc_node_del(node);
icc_node_destroy(node->id);
}
icc_provider_del(provider); icc_provider_del(provider);
err_disable_clks: err_disable_clks:
...@@ -747,16 +735,10 @@ static int msm8974_icc_probe(struct platform_device *pdev) ...@@ -747,16 +735,10 @@ static int msm8974_icc_probe(struct platform_device *pdev)
static int msm8974_icc_remove(struct platform_device *pdev) static int msm8974_icc_remove(struct platform_device *pdev)
{ {
struct msm8974_icc_provider *qp = platform_get_drvdata(pdev); struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
struct icc_provider *provider = &qp->provider;
struct icc_node *n, *tmp;
list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) { icc_nodes_remove(&qp->provider);
icc_node_del(n);
icc_node_destroy(n->id);
}
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return icc_provider_del(&qp->provider);
return icc_provider_del(provider);
} }
static const struct of_device_id msm8974_noc_of_match[] = { static const struct of_device_id msm8974_noc_of_match[] = {
......
...@@ -327,15 +327,6 @@ static struct qcom_icc_desc qcs404_snoc = { ...@@ -327,15 +327,6 @@ static struct qcom_icc_desc qcs404_snoc = {
.num_nodes = ARRAY_SIZE(qcs404_snoc_nodes), .num_nodes = ARRAY_SIZE(qcs404_snoc_nodes),
}; };
static int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
{
*agg_avg += avg_bw;
*agg_peak = max(*agg_peak, peak_bw);
return 0;
}
static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
{ {
struct qcom_icc_provider *qp; struct qcom_icc_provider *qp;
...@@ -354,7 +345,7 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst) ...@@ -354,7 +345,7 @@ static int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
qp = to_qcom_provider(provider); qp = to_qcom_provider(provider);
list_for_each_entry(n, &provider->nodes, node_list) list_for_each_entry(n, &provider->nodes, node_list)
qcom_icc_aggregate(n, 0, n->avg_bw, n->peak_bw, provider->aggregate(n, 0, n->avg_bw, n->peak_bw,
&agg_avg, &agg_peak); &agg_avg, &agg_peak);
sum_bw = icc_units_to_bps(agg_avg); sum_bw = icc_units_to_bps(agg_avg);
...@@ -414,7 +405,7 @@ static int qnoc_probe(struct platform_device *pdev) ...@@ -414,7 +405,7 @@ static int qnoc_probe(struct platform_device *pdev)
struct icc_provider *provider; struct icc_provider *provider;
struct qcom_icc_node **qnodes; struct qcom_icc_node **qnodes;
struct qcom_icc_provider *qp; struct qcom_icc_provider *qp;
struct icc_node *node, *tmp; struct icc_node *node;
size_t num_nodes, i; size_t num_nodes, i;
int ret; int ret;
...@@ -456,7 +447,7 @@ static int qnoc_probe(struct platform_device *pdev) ...@@ -456,7 +447,7 @@ static int qnoc_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&provider->nodes); INIT_LIST_HEAD(&provider->nodes);
provider->dev = dev; provider->dev = dev;
provider->set = qcom_icc_set; provider->set = qcom_icc_set;
provider->aggregate = qcom_icc_aggregate; provider->aggregate = icc_std_aggregate;
provider->xlate = of_icc_xlate_onecell; provider->xlate = of_icc_xlate_onecell;
provider->data = data; provider->data = data;
...@@ -494,10 +485,7 @@ static int qnoc_probe(struct platform_device *pdev) ...@@ -494,10 +485,7 @@ static int qnoc_probe(struct platform_device *pdev)
return 0; return 0;
err: err:
list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) { icc_nodes_remove(provider);
icc_node_del(node);
icc_node_destroy(node->id);
}
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
icc_provider_del(provider); icc_provider_del(provider);
...@@ -507,16 +495,10 @@ static int qnoc_probe(struct platform_device *pdev) ...@@ -507,16 +495,10 @@ static int qnoc_probe(struct platform_device *pdev)
static int qnoc_remove(struct platform_device *pdev) static int qnoc_remove(struct platform_device *pdev)
{ {
struct qcom_icc_provider *qp = platform_get_drvdata(pdev); struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
struct icc_provider *provider = &qp->provider;
struct icc_node *n, *tmp;
list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) { icc_nodes_remove(&qp->provider);
icc_node_del(n);
icc_node_destroy(n->id);
}
clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks); clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
return icc_provider_del(&qp->provider);
return icc_provider_del(provider);
} }
static const struct of_device_id qcs404_noc_of_match[] = { static const struct of_device_id qcs404_noc_of_match[] = {
......
...@@ -855,11 +855,7 @@ static int qnoc_probe(struct platform_device *pdev) ...@@ -855,11 +855,7 @@ static int qnoc_probe(struct platform_device *pdev)
return ret; return ret;
err: err:
list_for_each_entry(node, &provider->nodes, node_list) { icc_nodes_remove(provider);
icc_node_del(node);
icc_node_destroy(node->id);
}
icc_provider_del(provider); icc_provider_del(provider);
return ret; return ret;
} }
...@@ -867,15 +863,9 @@ static int qnoc_probe(struct platform_device *pdev) ...@@ -867,15 +863,9 @@ static int qnoc_probe(struct platform_device *pdev)
static int qnoc_remove(struct platform_device *pdev) static int qnoc_remove(struct platform_device *pdev)
{ {
struct qcom_icc_provider *qp = platform_get_drvdata(pdev); struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
struct icc_provider *provider = &qp->provider;
struct icc_node *n, *tmp;
list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
icc_node_del(n);
icc_node_destroy(n->id);
}
return icc_provider_del(provider); icc_nodes_remove(&qp->provider);
return icc_provider_del(&qp->provider);
} }
static const struct of_device_id qnoc_of_match[] = { static const struct of_device_id qnoc_of_match[] = {
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Interconnect framework tracepoints
* Copyright (c) 2019, Linaro Ltd.
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM interconnect
#if !defined(_TRACE_INTERCONNECT_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_INTERCONNECT_H
#include <linux/interconnect.h>
#include <linux/tracepoint.h>
TRACE_EVENT(icc_set_bw,
TP_PROTO(struct icc_path *p, struct icc_node *n, int i,
u32 avg_bw, u32 peak_bw),
TP_ARGS(p, n, i, avg_bw, peak_bw),
TP_STRUCT__entry(
__string(path_name, p->name)
__string(dev, dev_name(p->reqs[i].dev))
__string(node_name, n->name)
__field(u32, avg_bw)
__field(u32, peak_bw)
__field(u32, node_avg_bw)
__field(u32, node_peak_bw)
),
TP_fast_assign(
__assign_str(path_name, p->name);
__assign_str(dev, dev_name(p->reqs[i].dev));
__assign_str(node_name, n->name);
__entry->avg_bw = avg_bw;
__entry->peak_bw = peak_bw;
__entry->node_avg_bw = n->avg_bw;
__entry->node_peak_bw = n->peak_bw;
),
TP_printk("path=%s dev=%s node=%s avg_bw=%u peak_bw=%u agg_avg=%u agg_peak=%u",
__get_str(path_name),
__get_str(dev),
__get_str(node_name),
__entry->avg_bw,
__entry->peak_bw,
__entry->node_avg_bw,
__entry->node_peak_bw)
);
TRACE_EVENT(icc_set_bw_end,
TP_PROTO(struct icc_path *p, int ret),
TP_ARGS(p, ret),
TP_STRUCT__entry(
__string(path_name, p->name)
__string(dev, dev_name(p->reqs[0].dev))
__field(int, ret)
),
TP_fast_assign(
__assign_str(path_name, p->name);
__assign_str(dev, dev_name(p->reqs[0].dev));
__entry->ret = ret;
),
TP_printk("path=%s dev=%s ret=%d",
__get_str(path_name),
__get_str(dev),
__entry->ret)
);
#endif /* _TRACE_INTERCONNECT_H */
/* This part must be outside protection */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
...@@ -38,12 +38,18 @@ static const struct alcor_dev_cfg au6621_cfg = { ...@@ -38,12 +38,18 @@ static const struct alcor_dev_cfg au6621_cfg = {
.dma = 1, .dma = 1,
}; };
static const struct alcor_dev_cfg au6625_cfg = {
.dma = 0,
};
static const struct pci_device_id pci_ids[] = { static const struct pci_device_id pci_ids[] = {
{ PCI_DEVICE(PCI_ID_ALCOR_MICRO, PCI_ID_AU6601), { PCI_DEVICE(PCI_ID_ALCOR_MICRO, PCI_ID_AU6601),
.driver_data = (kernel_ulong_t)&alcor_cfg }, .driver_data = (kernel_ulong_t)&alcor_cfg },
{ PCI_DEVICE(PCI_ID_ALCOR_MICRO, PCI_ID_AU6621), { PCI_DEVICE(PCI_ID_ALCOR_MICRO, PCI_ID_AU6621),
.driver_data = (kernel_ulong_t)&au6621_cfg }, .driver_data = (kernel_ulong_t)&au6621_cfg },
{ }, { PCI_DEVICE(PCI_ID_ALCOR_MICRO, PCI_ID_AU6625),
.driver_data = (kernel_ulong_t)&au6625_cfg },
{},
}; };
MODULE_DEVICE_TABLE(pci, pci_ids); MODULE_DEVICE_TABLE(pci, pci_ids);
......
...@@ -628,7 +628,8 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, ...@@ -628,7 +628,8 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk) u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
{ {
int err, clk; int err, clk;
u8 n, clk_divider, mcu_cnt, div; u16 n;
u8 clk_divider, mcu_cnt, div;
static const u8 depth[] = { static const u8 depth[] = {
[RTSX_SSC_DEPTH_4M] = RTS5261_SSC_DEPTH_4M, [RTSX_SSC_DEPTH_4M] = RTS5261_SSC_DEPTH_4M,
[RTSX_SSC_DEPTH_2M] = RTS5261_SSC_DEPTH_2M, [RTSX_SSC_DEPTH_2M] = RTS5261_SSC_DEPTH_2M,
...@@ -661,13 +662,13 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, ...@@ -661,13 +662,13 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
return 0; return 0;
if (pcr->ops->conv_clk_and_div_n) if (pcr->ops->conv_clk_and_div_n)
n = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N); n = pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N);
else else
n = (u8)(clk - 4); n = clk - 4;
if ((clk <= 4) || (n > 396)) if ((clk <= 4) || (n > 396))
return -EINVAL; return -EINVAL;
mcu_cnt = (u8)(125/clk + 3); mcu_cnt = 125/clk + 3;
if (mcu_cnt > 15) if (mcu_cnt > 15)
mcu_cnt = 15; mcu_cnt = 15;
...@@ -676,7 +677,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, ...@@ -676,7 +677,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
if (pcr->ops->conv_clk_and_div_n) { if (pcr->ops->conv_clk_and_div_n) {
int dbl_clk = pcr->ops->conv_clk_and_div_n(n, int dbl_clk = pcr->ops->conv_clk_and_div_n(n,
DIV_N_TO_CLK) * 2; DIV_N_TO_CLK) * 2;
n = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk, n = pcr->ops->conv_clk_and_div_n(dbl_clk,
CLK_TO_DIV_N); CLK_TO_DIV_N);
} else { } else {
n = (n + 4) * 2 - 4; n = (n + 4) * 2 - 4;
......
...@@ -352,7 +352,7 @@ void cxl_context_free(struct cxl_context *ctx) ...@@ -352,7 +352,7 @@ void cxl_context_free(struct cxl_context *ctx)
void cxl_context_mm_count_get(struct cxl_context *ctx) void cxl_context_mm_count_get(struct cxl_context *ctx)
{ {
if (ctx->mm) if (ctx->mm)
atomic_inc(&ctx->mm->mm_count); mmgrab(ctx->mm);
} }
void cxl_context_mm_count_put(struct cxl_context *ctx) void cxl_context_mm_count_put(struct cxl_context *ctx)
......
...@@ -1084,7 +1084,7 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue) ...@@ -1084,7 +1084,7 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue)
queue->ddcb_daddr); queue->ddcb_daddr);
queue->ddcb_vaddr = NULL; queue->ddcb_vaddr = NULL;
queue->ddcb_daddr = 0ull; queue->ddcb_daddr = 0ull;
return -ENODEV; return rc;
} }
...@@ -1179,7 +1179,7 @@ static irqreturn_t genwqe_vf_isr(int irq, void *dev_id) ...@@ -1179,7 +1179,7 @@ static irqreturn_t genwqe_vf_isr(int irq, void *dev_id)
*/ */
static int genwqe_card_thread(void *data) static int genwqe_card_thread(void *data)
{ {
int should_stop = 0, rc = 0; int should_stop = 0;
struct genwqe_dev *cd = (struct genwqe_dev *)data; struct genwqe_dev *cd = (struct genwqe_dev *)data;
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
...@@ -1187,12 +1187,12 @@ static int genwqe_card_thread(void *data) ...@@ -1187,12 +1187,12 @@ static int genwqe_card_thread(void *data)
genwqe_check_ddcb_queue(cd, &cd->queue); genwqe_check_ddcb_queue(cd, &cd->queue);
if (GENWQE_POLLING_ENABLED) { if (GENWQE_POLLING_ENABLED) {
rc = wait_event_interruptible_timeout( wait_event_interruptible_timeout(
cd->queue_waitq, cd->queue_waitq,
genwqe_ddcbs_in_flight(cd) || genwqe_ddcbs_in_flight(cd) ||
(should_stop = kthread_should_stop()), 1); (should_stop = kthread_should_stop()), 1);
} else { } else {
rc = wait_event_interruptible_timeout( wait_event_interruptible_timeout(
cd->queue_waitq, cd->queue_waitq,
genwqe_next_ddcb_ready(cd) || genwqe_next_ddcb_ready(cd) ||
(should_stop = kthread_should_stop()), HZ); (should_stop = kthread_should_stop()), HZ);
......
...@@ -173,6 +173,7 @@ static int isl29020_probe(struct i2c_client *client, ...@@ -173,6 +173,7 @@ static int isl29020_probe(struct i2c_client *client,
static int isl29020_remove(struct i2c_client *client) static int isl29020_remove(struct i2c_client *client)
{ {
pm_runtime_disable(&client->dev);
sysfs_remove_group(&client->dev.kobj, &m_als_gr); sysfs_remove_group(&client->dev.kobj, &m_als_gr);
return 0; return 0;
} }
......
...@@ -765,7 +765,7 @@ static ssize_t uuid_show(struct device *dev, struct device_attribute *a, ...@@ -765,7 +765,7 @@ static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
struct mei_cl_device *cldev = to_mei_cl_device(dev); struct mei_cl_device *cldev = to_mei_cl_device(dev);
const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
return scnprintf(buf, PAGE_SIZE, "%pUl", uuid); return sprintf(buf, "%pUl", uuid);
} }
static DEVICE_ATTR_RO(uuid); static DEVICE_ATTR_RO(uuid);
...@@ -775,7 +775,7 @@ static ssize_t version_show(struct device *dev, struct device_attribute *a, ...@@ -775,7 +775,7 @@ static ssize_t version_show(struct device *dev, struct device_attribute *a,
struct mei_cl_device *cldev = to_mei_cl_device(dev); struct mei_cl_device *cldev = to_mei_cl_device(dev);
u8 version = mei_me_cl_ver(cldev->me_cl); u8 version = mei_me_cl_ver(cldev->me_cl);
return scnprintf(buf, PAGE_SIZE, "%02X", version); return sprintf(buf, "%02X", version);
} }
static DEVICE_ATTR_RO(version); static DEVICE_ATTR_RO(version);
...@@ -797,7 +797,7 @@ static ssize_t max_conn_show(struct device *dev, struct device_attribute *a, ...@@ -797,7 +797,7 @@ static ssize_t max_conn_show(struct device *dev, struct device_attribute *a,
struct mei_cl_device *cldev = to_mei_cl_device(dev); struct mei_cl_device *cldev = to_mei_cl_device(dev);
u8 maxconn = mei_me_cl_max_conn(cldev->me_cl); u8 maxconn = mei_me_cl_max_conn(cldev->me_cl);
return scnprintf(buf, PAGE_SIZE, "%d", maxconn); return sprintf(buf, "%d", maxconn);
} }
static DEVICE_ATTR_RO(max_conn); static DEVICE_ATTR_RO(max_conn);
...@@ -807,7 +807,7 @@ static ssize_t fixed_show(struct device *dev, struct device_attribute *a, ...@@ -807,7 +807,7 @@ static ssize_t fixed_show(struct device *dev, struct device_attribute *a,
struct mei_cl_device *cldev = to_mei_cl_device(dev); struct mei_cl_device *cldev = to_mei_cl_device(dev);
u8 fixed = mei_me_cl_fixed(cldev->me_cl); u8 fixed = mei_me_cl_fixed(cldev->me_cl);
return scnprintf(buf, PAGE_SIZE, "%d", fixed); return sprintf(buf, "%d", fixed);
} }
static DEVICE_ATTR_RO(fixed); static DEVICE_ATTR_RO(fixed);
...@@ -817,7 +817,7 @@ static ssize_t max_len_show(struct device *dev, struct device_attribute *a, ...@@ -817,7 +817,7 @@ static ssize_t max_len_show(struct device *dev, struct device_attribute *a,
struct mei_cl_device *cldev = to_mei_cl_device(dev); struct mei_cl_device *cldev = to_mei_cl_device(dev);
u32 maxlen = mei_me_cl_max_len(cldev->me_cl); u32 maxlen = mei_me_cl_max_len(cldev->me_cl);
return scnprintf(buf, PAGE_SIZE, "%u", maxlen); return sprintf(buf, "%u", maxlen);
} }
static DEVICE_ATTR_RO(max_len); static DEVICE_ATTR_RO(max_len);
......
...@@ -757,11 +757,38 @@ static const struct component_master_ops mei_component_master_ops = { ...@@ -757,11 +757,38 @@ static const struct component_master_ops mei_component_master_ops = {
.unbind = mei_component_master_unbind, .unbind = mei_component_master_unbind,
}; };
/**
* mei_hdcp_component_match - compare function for matching mei hdcp.
*
* The function checks if the driver is i915, the subcomponent is HDCP
* and the grand parent of hdcp and the parent of i915 are the same
* PCH device.
*
* @dev: master device
* @subcomponent: subcomponent to match (I915_COMPONENT_HDCP)
* @data: compare data (mei hdcp device)
*
* Return:
* * 1 - if components match
* * 0 - otherwise
*/
static int mei_hdcp_component_match(struct device *dev, int subcomponent, static int mei_hdcp_component_match(struct device *dev, int subcomponent,
void *data) void *data)
{ {
return !strcmp(dev->driver->name, "i915") && struct device *base = data;
subcomponent == I915_COMPONENT_HDCP;
if (strcmp(dev->driver->name, "i915") ||
subcomponent != I915_COMPONENT_HDCP)
return 0;
base = base->parent;
if (!base)
return 0;
base = base->parent;
dev = dev->parent;
return (base && dev && dev == base);
} }
static int mei_hdcp_probe(struct mei_cl_device *cldev, static int mei_hdcp_probe(struct mei_cl_device *cldev,
...@@ -785,7 +812,7 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev, ...@@ -785,7 +812,7 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev,
master_match = NULL; master_match = NULL;
component_match_add_typed(&cldev->dev, &master_match, component_match_add_typed(&cldev->dev, &master_match,
mei_hdcp_component_match, comp_master); mei_hdcp_component_match, &cldev->dev);
if (IS_ERR_OR_NULL(master_match)) { if (IS_ERR_OR_NULL(master_match)) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_exit; goto err_exit;
......
...@@ -81,10 +81,16 @@ ...@@ -81,10 +81,16 @@
#define MEI_DEV_ID_CMP_LP 0x02e0 /* Comet Point LP */ #define MEI_DEV_ID_CMP_LP 0x02e0 /* Comet Point LP */
#define MEI_DEV_ID_CMP_LP_3 0x02e4 /* Comet Point LP 3 (iTouch) */ #define MEI_DEV_ID_CMP_LP_3 0x02e4 /* Comet Point LP 3 (iTouch) */
#define MEI_DEV_ID_CMP_V 0xA3BA /* Comet Point Lake V */ #define MEI_DEV_ID_CMP_V 0xA3BA /* Comet Point Lake V */
#define MEI_DEV_ID_CMP_H 0x06e0 /* Comet Lake H */
#define MEI_DEV_ID_CMP_H_3 0x06e4 /* Comet Lake H 3 (iTouch) */
#define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */ #define MEI_DEV_ID_ICP_LP 0x34E0 /* Ice Lake Point LP */
#define MEI_DEV_ID_JSP_N 0x4DE0 /* Jasper Lake Point N */
#define MEI_DEV_ID_TGP_LP 0xA0E0 /* Tiger Lake Point LP */ #define MEI_DEV_ID_TGP_LP 0xA0E0 /* Tiger Lake Point LP */
#define MEI_DEV_ID_MCC 0x4B70 /* Mule Creek Canyon (EHL) */ #define MEI_DEV_ID_MCC 0x4B70 /* Mule Creek Canyon (EHL) */
......
...@@ -99,11 +99,15 @@ static const struct pci_device_id mei_me_pci_tbl[] = { ...@@ -99,11 +99,15 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP_3, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP_3, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_V, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_CMP_V, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H_3, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_JSP_N, MEI_ME_PCH15_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH15_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH15_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
......
...@@ -65,9 +65,6 @@ void __init mic_create_card_debug_dir(struct mic_driver *mdrv) ...@@ -65,9 +65,6 @@ void __init mic_create_card_debug_dir(struct mic_driver *mdrv)
*/ */
void mic_delete_card_debug_dir(struct mic_driver *mdrv) void mic_delete_card_debug_dir(struct mic_driver *mdrv)
{ {
if (!mdrv->dbg_dir)
return;
debugfs_remove_recursive(mdrv->dbg_dir); debugfs_remove_recursive(mdrv->dbg_dir);
} }
......
...@@ -102,9 +102,6 @@ void cosm_create_debug_dir(struct cosm_device *cdev) ...@@ -102,9 +102,6 @@ void cosm_create_debug_dir(struct cosm_device *cdev)
void cosm_delete_debug_dir(struct cosm_device *cdev) void cosm_delete_debug_dir(struct cosm_device *cdev)
{ {
if (!cdev->dbg_dir)
return;
debugfs_remove_recursive(cdev->dbg_dir); debugfs_remove_recursive(cdev->dbg_dir);
} }
......
...@@ -129,9 +129,6 @@ void mic_create_debug_dir(struct mic_device *mdev) ...@@ -129,9 +129,6 @@ void mic_create_debug_dir(struct mic_device *mdev)
*/ */
void mic_delete_debug_dir(struct mic_device *mdev) void mic_delete_debug_dir(struct mic_device *mdev)
{ {
if (!mdev->dbg_dir)
return;
debugfs_remove_recursive(mdev->dbg_dir); debugfs_remove_recursive(mdev->dbg_dir);
} }
......
...@@ -792,7 +792,7 @@ static int pti_pci_probe(struct pci_dev *pdev, ...@@ -792,7 +792,7 @@ static int pti_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
unsigned int a; unsigned int a;
int retval = -EINVAL; int retval;
int pci_bar = 1; int pci_bar = 1;
dev_dbg(&pdev->dev, "%s %s(%d): PTI PCI ID %04x:%04x\n", __FILE__, dev_dbg(&pdev->dev, "%s %s(%d): PTI PCI ID %04x:%04x\n", __FILE__,
...@@ -910,7 +910,7 @@ static struct pci_driver pti_pci_driver = { ...@@ -910,7 +910,7 @@ static struct pci_driver pti_pci_driver = {
*/ */
static int __init pti_init(void) static int __init pti_init(void)
{ {
int retval = -EINVAL; int retval;
/* First register module as tty device */ /* First register module as tty device */
......
...@@ -10,16 +10,16 @@ ...@@ -10,16 +10,16 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kexec.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/types.h> #include <linux/types.h>
#include <uapi/misc/pvpanic.h>
static void __iomem *base; static void __iomem *base;
#define PVPANIC_PANICKED (1 << 0)
MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>"); MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
MODULE_DESCRIPTION("pvpanic device driver"); MODULE_DESCRIPTION("pvpanic device driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -34,7 +34,13 @@ static int ...@@ -34,7 +34,13 @@ static int
pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, pvpanic_panic_notify(struct notifier_block *nb, unsigned long code,
void *unused) void *unused)
{ {
pvpanic_send_event(PVPANIC_PANICKED); unsigned int event = PVPANIC_PANICKED;
if (kexec_crash_loaded())
event = PVPANIC_CRASH_LOADED;
pvpanic_send_event(event);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
......
...@@ -85,6 +85,7 @@ void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src, ...@@ -85,6 +85,7 @@ void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src,
unsigned long base; unsigned long base;
int pages; int pages;
void *dst_cpy; void *dst_cpy;
int ret;
mutex_lock(&exec_pool_list_mutex); mutex_lock(&exec_pool_list_mutex);
list_for_each_entry(p, &exec_pool_list, list) { list_for_each_entry(p, &exec_pool_list, list) {
...@@ -104,16 +105,28 @@ void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src, ...@@ -104,16 +105,28 @@ void *sram_exec_copy(struct gen_pool *pool, void *dst, void *src,
mutex_lock(&part->lock); mutex_lock(&part->lock);
set_memory_nx((unsigned long)base, pages); ret = set_memory_nx((unsigned long)base, pages);
set_memory_rw((unsigned long)base, pages); if (ret)
goto error_out;
ret = set_memory_rw((unsigned long)base, pages);
if (ret)
goto error_out;
dst_cpy = fncpy(dst, src, size); dst_cpy = fncpy(dst, src, size);
set_memory_ro((unsigned long)base, pages); ret = set_memory_ro((unsigned long)base, pages);
set_memory_x((unsigned long)base, pages); if (ret)
goto error_out;
ret = set_memory_x((unsigned long)base, pages);
if (ret)
goto error_out;
mutex_unlock(&part->lock); mutex_unlock(&part->lock);
return dst_cpy; return dst_cpy;
error_out:
mutex_unlock(&part->lock);
return NULL;
} }
EXPORT_SYMBOL_GPL(sram_exec_copy); EXPORT_SYMBOL_GPL(sram_exec_copy);
...@@ -736,8 +736,8 @@ static int st_tty_open(struct tty_struct *tty) ...@@ -736,8 +736,8 @@ static int st_tty_open(struct tty_struct *tty)
static void st_tty_close(struct tty_struct *tty) static void st_tty_close(struct tty_struct *tty)
{ {
unsigned char i = ST_MAX_CHANNELS; unsigned char i;
unsigned long flags = 0; unsigned long flags;
struct st_data_s *st_gdata = tty->disc_data; struct st_data_s *st_gdata = tty->disc_data;
pr_info("%s ", __func__); pr_info("%s ", __func__);
......
...@@ -148,16 +148,14 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1) ...@@ -148,16 +148,14 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
u16 c0 = count_lut[ch0]; u16 c0 = count_lut[ch0];
u16 c1 = count_lut[ch1]; u16 c1 = count_lut[ch1];
/* Avoid division by 0 and count 1 cannot be greater than count 0 */
if (c1 <= c0)
if (c0) {
/* /*
* Calculate ratio. * Calculate ratio.
* Note: the "128" is a scaling factor * Note: the "128" is a scaling factor
*/ */
u8 r = 128; u8 r = c1 * 128 / c0;
/* Avoid division by 0 and count 1 cannot be greater than count 0 */
if (c1 <= c0)
if (c0) {
r = c1 * 128 / c0;
/* Calculate LUX */ /* Calculate LUX */
lux = ((c0 - c1) * ratio_lut[r]) / 256; lux = ((c0 - c1) * ratio_lut[r]) / 256;
......
...@@ -733,7 +733,7 @@ static int xsdfec_set_order(struct xsdfec_dev *xsdfec, void __user *arg) ...@@ -733,7 +733,7 @@ static int xsdfec_set_order(struct xsdfec_dev *xsdfec, void __user *arg)
enum xsdfec_order order; enum xsdfec_order order;
int err; int err;
err = get_user(order, (enum xsdfec_order *)arg); err = get_user(order, (enum xsdfec_order __user *)arg);
if (err) if (err)
return -EFAULT; return -EFAULT;
...@@ -1025,25 +1025,25 @@ static long xsdfec_dev_compat_ioctl(struct file *file, unsigned int cmd, ...@@ -1025,25 +1025,25 @@ static long xsdfec_dev_compat_ioctl(struct file *file, unsigned int cmd,
} }
#endif #endif
static unsigned int xsdfec_poll(struct file *file, poll_table *wait) static __poll_t xsdfec_poll(struct file *file, poll_table *wait)
{ {
unsigned int mask = 0; __poll_t mask = 0;
struct xsdfec_dev *xsdfec; struct xsdfec_dev *xsdfec;
xsdfec = container_of(file->private_data, struct xsdfec_dev, miscdev); xsdfec = container_of(file->private_data, struct xsdfec_dev, miscdev);
if (!xsdfec) if (!xsdfec)
return POLLNVAL | POLLHUP; return EPOLLNVAL | EPOLLHUP;
poll_wait(file, &xsdfec->waitq, wait); poll_wait(file, &xsdfec->waitq, wait);
/* XSDFEC ISR detected an error */ /* XSDFEC ISR detected an error */
spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags); spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags);
if (xsdfec->state_updated) if (xsdfec->state_updated)
mask |= POLLIN | POLLPRI; mask |= EPOLLIN | EPOLLPRI;
if (xsdfec->stats_updated) if (xsdfec->stats_updated)
mask |= POLLIN | POLLRDNORM; mask |= EPOLLIN | EPOLLRDNORM;
spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags); spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags);
return mask; return mask;
......
...@@ -109,6 +109,14 @@ config QCOM_QFPROM ...@@ -109,6 +109,14 @@ config QCOM_QFPROM
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called nvmem_qfprom. will be called nvmem_qfprom.
config NVMEM_SPMI_SDAM
tristate "SPMI SDAM Support"
depends on SPMI
help
This driver supports the Shared Direct Access Memory Module on
Qualcomm Technologies, Inc. PMICs. It provides the clients
an interface to read/write to the SDAM module's shared memory.
config ROCKCHIP_EFUSE config ROCKCHIP_EFUSE
tristate "Rockchip eFuse Support" tristate "Rockchip eFuse Support"
depends on ARCH_ROCKCHIP || COMPILE_TEST depends on ARCH_ROCKCHIP || COMPILE_TEST
......
...@@ -28,6 +28,8 @@ obj-$(CONFIG_MTK_EFUSE) += nvmem_mtk-efuse.o ...@@ -28,6 +28,8 @@ obj-$(CONFIG_MTK_EFUSE) += nvmem_mtk-efuse.o
nvmem_mtk-efuse-y := mtk-efuse.o nvmem_mtk-efuse-y := mtk-efuse.o
obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o
nvmem_qfprom-y := qfprom.o nvmem_qfprom-y := qfprom.o
obj-$(CONFIG_NVMEM_SPMI_SDAM) += nvmem_qcom-spmi-sdam.o
nvmem_qcom-spmi-sdam-y += qcom-spmi-sdam.o
obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
nvmem_rockchip_efuse-y := rockchip-efuse.o nvmem_rockchip_efuse-y := rockchip-efuse.o
obj-$(CONFIG_ROCKCHIP_OTP) += nvmem-rockchip-otp.o obj-$(CONFIG_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
......
...@@ -83,7 +83,7 @@ static void nvmem_cell_drop(struct nvmem_cell *cell) ...@@ -83,7 +83,7 @@ static void nvmem_cell_drop(struct nvmem_cell *cell)
list_del(&cell->node); list_del(&cell->node);
mutex_unlock(&nvmem_mutex); mutex_unlock(&nvmem_mutex);
of_node_put(cell->np); of_node_put(cell->np);
kfree(cell->name); kfree_const(cell->name);
kfree(cell); kfree(cell);
} }
...@@ -110,7 +110,9 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem, ...@@ -110,7 +110,9 @@ static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
cell->nvmem = nvmem; cell->nvmem = nvmem;
cell->offset = info->offset; cell->offset = info->offset;
cell->bytes = info->bytes; cell->bytes = info->bytes;
cell->name = info->name; cell->name = kstrdup_const(info->name, GFP_KERNEL);
if (!cell->name)
return -ENOMEM;
cell->bit_offset = info->bit_offset; cell->bit_offset = info->bit_offset;
cell->nbits = info->nbits; cell->nbits = info->nbits;
...@@ -300,7 +302,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) ...@@ -300,7 +302,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
dev_err(dev, "cell %s unaligned to nvmem stride %d\n", dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
cell->name, nvmem->stride); cell->name, nvmem->stride);
/* Cells already added will be freed later. */ /* Cells already added will be freed later. */
kfree(cell->name); kfree_const(cell->name);
kfree(cell); kfree(cell);
return -EINVAL; return -EINVAL;
} }
......
...@@ -15,8 +15,7 @@ ...@@ -15,8 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#define IMX_SIP_OTP 0xC200000A #define IMX_SIP_OTP_WRITE 0xc200000B
#define IMX_SIP_OTP_WRITE 0x2
enum ocotp_devtype { enum ocotp_devtype {
IMX8QXP, IMX8QXP,
...@@ -139,8 +138,8 @@ static int imx_scu_ocotp_read(void *context, unsigned int offset, ...@@ -139,8 +138,8 @@ static int imx_scu_ocotp_read(void *context, unsigned int offset,
void *p; void *p;
int i, ret; int i, ret;
index = offset >> 2; index = offset;
num_bytes = round_up((offset % 4) + bytes, 4); num_bytes = round_up(bytes, 4);
count = num_bytes >> 2; count = num_bytes >> 2;
if (count > (priv->data->nregs - index)) if (count > (priv->data->nregs - index))
...@@ -169,7 +168,7 @@ static int imx_scu_ocotp_read(void *context, unsigned int offset, ...@@ -169,7 +168,7 @@ static int imx_scu_ocotp_read(void *context, unsigned int offset,
buf++; buf++;
} }
memcpy(val, (u8 *)p + offset % 4, bytes); memcpy(val, (u8 *)p, bytes);
mutex_unlock(&scu_ocotp_mutex); mutex_unlock(&scu_ocotp_mutex);
...@@ -189,10 +188,10 @@ static int imx_scu_ocotp_write(void *context, unsigned int offset, ...@@ -189,10 +188,10 @@ static int imx_scu_ocotp_write(void *context, unsigned int offset,
int ret; int ret;
/* allow only writing one complete OTP word at a time */ /* allow only writing one complete OTP word at a time */
if ((bytes != 4) || (offset % 4)) if (bytes != 4)
return -EINVAL; return -EINVAL;
index = offset >> 2; index = offset;
if (in_hole(context, index)) if (in_hole(context, index))
return -EINVAL; return -EINVAL;
...@@ -212,8 +211,7 @@ static int imx_scu_ocotp_write(void *context, unsigned int offset, ...@@ -212,8 +211,7 @@ static int imx_scu_ocotp_write(void *context, unsigned int offset,
mutex_lock(&scu_ocotp_mutex); mutex_lock(&scu_ocotp_mutex);
arm_smccc_smc(IMX_SIP_OTP, IMX_SIP_OTP_WRITE, index, *buf, arm_smccc_smc(IMX_SIP_OTP_WRITE, index, *buf, 0, 0, 0, 0, 0, &res);
0, 0, 0, 0, &res);
mutex_unlock(&scu_ocotp_mutex); mutex_unlock(&scu_ocotp_mutex);
......
...@@ -44,6 +44,14 @@ ...@@ -44,6 +44,14 @@
#define IMX_OCOTP_BM_CTRL_ERROR 0x00000200 #define IMX_OCOTP_BM_CTRL_ERROR 0x00000200
#define IMX_OCOTP_BM_CTRL_REL_SHADOWS 0x00000400 #define IMX_OCOTP_BM_CTRL_REL_SHADOWS 0x00000400
#define IMX_OCOTP_BM_CTRL_DEFAULT \
{ \
.bm_addr = IMX_OCOTP_BM_CTRL_ADDR, \
.bm_busy = IMX_OCOTP_BM_CTRL_BUSY, \
.bm_error = IMX_OCOTP_BM_CTRL_ERROR, \
.bm_rel_shadows = IMX_OCOTP_BM_CTRL_REL_SHADOWS,\
}
#define TIMING_STROBE_PROG_US 10 /* Min time to blow a fuse */ #define TIMING_STROBE_PROG_US 10 /* Min time to blow a fuse */
#define TIMING_STROBE_READ_NS 37 /* Min time before read */ #define TIMING_STROBE_READ_NS 37 /* Min time before read */
#define TIMING_RELAX_NS 17 #define TIMING_RELAX_NS 17
...@@ -62,18 +70,31 @@ struct ocotp_priv { ...@@ -62,18 +70,31 @@ struct ocotp_priv {
struct nvmem_config *config; struct nvmem_config *config;
}; };
struct ocotp_ctrl_reg {
u32 bm_addr;
u32 bm_busy;
u32 bm_error;
u32 bm_rel_shadows;
};
struct ocotp_params { struct ocotp_params {
unsigned int nregs; unsigned int nregs;
unsigned int bank_address_words; unsigned int bank_address_words;
void (*set_timing)(struct ocotp_priv *priv); void (*set_timing)(struct ocotp_priv *priv);
struct ocotp_ctrl_reg ctrl;
}; };
static int imx_ocotp_wait_for_busy(void __iomem *base, u32 flags) static int imx_ocotp_wait_for_busy(struct ocotp_priv *priv, u32 flags)
{ {
int count; int count;
u32 c, mask; u32 c, mask;
u32 bm_ctrl_busy, bm_ctrl_error;
void __iomem *base = priv->base;
mask = IMX_OCOTP_BM_CTRL_BUSY | IMX_OCOTP_BM_CTRL_ERROR | flags; bm_ctrl_busy = priv->params->ctrl.bm_busy;
bm_ctrl_error = priv->params->ctrl.bm_error;
mask = bm_ctrl_busy | bm_ctrl_error | flags;
for (count = 10000; count >= 0; count--) { for (count = 10000; count >= 0; count--) {
c = readl(base + IMX_OCOTP_ADDR_CTRL); c = readl(base + IMX_OCOTP_ADDR_CTRL);
...@@ -97,7 +118,7 @@ static int imx_ocotp_wait_for_busy(void __iomem *base, u32 flags) ...@@ -97,7 +118,7 @@ static int imx_ocotp_wait_for_busy(void __iomem *base, u32 flags)
* - A read is performed to from a fuse word which has been read * - A read is performed to from a fuse word which has been read
* locked. * locked.
*/ */
if (c & IMX_OCOTP_BM_CTRL_ERROR) if (c & bm_ctrl_error)
return -EPERM; return -EPERM;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -105,15 +126,18 @@ static int imx_ocotp_wait_for_busy(void __iomem *base, u32 flags) ...@@ -105,15 +126,18 @@ static int imx_ocotp_wait_for_busy(void __iomem *base, u32 flags)
return 0; return 0;
} }
static void imx_ocotp_clr_err_if_set(void __iomem *base) static void imx_ocotp_clr_err_if_set(struct ocotp_priv *priv)
{ {
u32 c; u32 c, bm_ctrl_error;
void __iomem *base = priv->base;
bm_ctrl_error = priv->params->ctrl.bm_error;
c = readl(base + IMX_OCOTP_ADDR_CTRL); c = readl(base + IMX_OCOTP_ADDR_CTRL);
if (!(c & IMX_OCOTP_BM_CTRL_ERROR)) if (!(c & bm_ctrl_error))
return; return;
writel(IMX_OCOTP_BM_CTRL_ERROR, base + IMX_OCOTP_ADDR_CTRL_CLR); writel(bm_ctrl_error, base + IMX_OCOTP_ADDR_CTRL_CLR);
} }
static int imx_ocotp_read(void *context, unsigned int offset, static int imx_ocotp_read(void *context, unsigned int offset,
...@@ -140,7 +164,7 @@ static int imx_ocotp_read(void *context, unsigned int offset, ...@@ -140,7 +164,7 @@ static int imx_ocotp_read(void *context, unsigned int offset,
return ret; return ret;
} }
ret = imx_ocotp_wait_for_busy(priv->base, 0); ret = imx_ocotp_wait_for_busy(priv, 0);
if (ret < 0) { if (ret < 0) {
dev_err(priv->dev, "timeout during read setup\n"); dev_err(priv->dev, "timeout during read setup\n");
goto read_end; goto read_end;
...@@ -157,7 +181,7 @@ static int imx_ocotp_read(void *context, unsigned int offset, ...@@ -157,7 +181,7 @@ static int imx_ocotp_read(void *context, unsigned int offset,
* issued * issued
*/ */
if (*(buf - 1) == IMX_OCOTP_READ_LOCKED_VAL) if (*(buf - 1) == IMX_OCOTP_READ_LOCKED_VAL)
imx_ocotp_clr_err_if_set(priv->base); imx_ocotp_clr_err_if_set(priv);
} }
ret = 0; ret = 0;
...@@ -274,7 +298,7 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, ...@@ -274,7 +298,7 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val,
* write or reload must be completed before a write access can be * write or reload must be completed before a write access can be
* requested. * requested.
*/ */
ret = imx_ocotp_wait_for_busy(priv->base, 0); ret = imx_ocotp_wait_for_busy(priv, 0);
if (ret < 0) { if (ret < 0) {
dev_err(priv->dev, "timeout during timing setup\n"); dev_err(priv->dev, "timeout during timing setup\n");
goto write_end; goto write_end;
...@@ -306,8 +330,8 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, ...@@ -306,8 +330,8 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val,
} }
ctrl = readl(priv->base + IMX_OCOTP_ADDR_CTRL); ctrl = readl(priv->base + IMX_OCOTP_ADDR_CTRL);
ctrl &= ~IMX_OCOTP_BM_CTRL_ADDR; ctrl &= ~priv->params->ctrl.bm_addr;
ctrl |= waddr & IMX_OCOTP_BM_CTRL_ADDR; ctrl |= waddr & priv->params->ctrl.bm_addr;
ctrl |= IMX_OCOTP_WR_UNLOCK; ctrl |= IMX_OCOTP_WR_UNLOCK;
writel(ctrl, priv->base + IMX_OCOTP_ADDR_CTRL); writel(ctrl, priv->base + IMX_OCOTP_ADDR_CTRL);
...@@ -374,11 +398,11 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, ...@@ -374,11 +398,11 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val,
* be set. It must be cleared by software before any new write access * be set. It must be cleared by software before any new write access
* can be issued. * can be issued.
*/ */
ret = imx_ocotp_wait_for_busy(priv->base, 0); ret = imx_ocotp_wait_for_busy(priv, 0);
if (ret < 0) { if (ret < 0) {
if (ret == -EPERM) { if (ret == -EPERM) {
dev_err(priv->dev, "failed write to locked region"); dev_err(priv->dev, "failed write to locked region");
imx_ocotp_clr_err_if_set(priv->base); imx_ocotp_clr_err_if_set(priv);
} else { } else {
dev_err(priv->dev, "timeout during data write\n"); dev_err(priv->dev, "timeout during data write\n");
} }
...@@ -394,10 +418,10 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, ...@@ -394,10 +418,10 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val,
udelay(2); udelay(2);
/* reload all shadow registers */ /* reload all shadow registers */
writel(IMX_OCOTP_BM_CTRL_REL_SHADOWS, writel(priv->params->ctrl.bm_rel_shadows,
priv->base + IMX_OCOTP_ADDR_CTRL_SET); priv->base + IMX_OCOTP_ADDR_CTRL_SET);
ret = imx_ocotp_wait_for_busy(priv->base, ret = imx_ocotp_wait_for_busy(priv,
IMX_OCOTP_BM_CTRL_REL_SHADOWS); priv->params->ctrl.bm_rel_shadows);
if (ret < 0) { if (ret < 0) {
dev_err(priv->dev, "timeout during shadow register reload\n"); dev_err(priv->dev, "timeout during shadow register reload\n");
goto write_end; goto write_end;
...@@ -424,65 +448,76 @@ static const struct ocotp_params imx6q_params = { ...@@ -424,65 +448,76 @@ static const struct ocotp_params imx6q_params = {
.nregs = 128, .nregs = 128,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx6sl_params = { static const struct ocotp_params imx6sl_params = {
.nregs = 64, .nregs = 64,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx6sll_params = { static const struct ocotp_params imx6sll_params = {
.nregs = 128, .nregs = 128,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx6sx_params = { static const struct ocotp_params imx6sx_params = {
.nregs = 128, .nregs = 128,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx6ul_params = { static const struct ocotp_params imx6ul_params = {
.nregs = 128, .nregs = 128,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx6ull_params = { static const struct ocotp_params imx6ull_params = {
.nregs = 64, .nregs = 64,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx7d_params = { static const struct ocotp_params imx7d_params = {
.nregs = 64, .nregs = 64,
.bank_address_words = 4, .bank_address_words = 4,
.set_timing = imx_ocotp_set_imx7_timing, .set_timing = imx_ocotp_set_imx7_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx7ulp_params = { static const struct ocotp_params imx7ulp_params = {
.nregs = 256, .nregs = 256,
.bank_address_words = 0, .bank_address_words = 0,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx8mq_params = { static const struct ocotp_params imx8mq_params = {
.nregs = 256, .nregs = 256,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx8mm_params = { static const struct ocotp_params imx8mm_params = {
.nregs = 256, .nregs = 256,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct ocotp_params imx8mn_params = { static const struct ocotp_params imx8mn_params = {
.nregs = 256, .nregs = 256,
.bank_address_words = 0, .bank_address_words = 0,
.set_timing = imx_ocotp_set_imx6_timing, .set_timing = imx_ocotp_set_imx6_timing,
.ctrl = IMX_OCOTP_BM_CTRL_DEFAULT,
}; };
static const struct of_device_id imx_ocotp_dt_ids[] = { static const struct of_device_id imx_ocotp_dt_ids[] = {
...@@ -521,17 +556,17 @@ static int imx_ocotp_probe(struct platform_device *pdev) ...@@ -521,17 +556,17 @@ static int imx_ocotp_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk)) if (IS_ERR(priv->clk))
return PTR_ERR(priv->clk); return PTR_ERR(priv->clk);
clk_prepare_enable(priv->clk);
imx_ocotp_clr_err_if_set(priv->base);
clk_disable_unprepare(priv->clk);
priv->params = of_device_get_match_data(&pdev->dev); priv->params = of_device_get_match_data(&pdev->dev);
imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
imx_ocotp_nvmem_config.dev = dev; imx_ocotp_nvmem_config.dev = dev;
imx_ocotp_nvmem_config.priv = priv; imx_ocotp_nvmem_config.priv = priv;
priv->config = &imx_ocotp_nvmem_config; priv->config = &imx_ocotp_nvmem_config;
nvmem = devm_nvmem_register(dev, &imx_ocotp_nvmem_config);
clk_prepare_enable(priv->clk);
imx_ocotp_clr_err_if_set(priv);
clk_disable_unprepare(priv->clk);
nvmem = devm_nvmem_register(dev, &imx_ocotp_nvmem_config);
return PTR_ERR_OR_ZERO(nvmem); return PTR_ERR_OR_ZERO(nvmem);
} }
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/nvmem-provider.h>
#include <linux/regmap.h>
#define SDAM_MEM_START 0x40
#define REGISTER_MAP_ID 0x40
#define REGISTER_MAP_VERSION 0x41
#define SDAM_SIZE 0x44
#define SDAM_PBS_TRIG_SET 0xE5
#define SDAM_PBS_TRIG_CLR 0xE6
struct sdam_chip {
struct platform_device *pdev;
struct regmap *regmap;
struct nvmem_config sdam_config;
unsigned int base;
unsigned int size;
};
/* read only register offsets */
static const u8 sdam_ro_map[] = {
REGISTER_MAP_ID,
REGISTER_MAP_VERSION,
SDAM_SIZE
};
static bool sdam_is_valid(struct sdam_chip *sdam, unsigned int offset,
size_t len)
{
unsigned int sdam_mem_end = SDAM_MEM_START + sdam->size - 1;
if (!len)
return false;
if (offset >= SDAM_MEM_START && offset <= sdam_mem_end
&& (offset + len - 1) <= sdam_mem_end)
return true;
else if ((offset == SDAM_PBS_TRIG_SET || offset == SDAM_PBS_TRIG_CLR)
&& (len == 1))
return true;
return false;
}
static bool sdam_is_ro(unsigned int offset, size_t len)
{
int i;
for (i = 0; i < ARRAY_SIZE(sdam_ro_map); i++)
if (offset <= sdam_ro_map[i] && (offset + len) > sdam_ro_map[i])
return true;
return false;
}
static int sdam_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct sdam_chip *sdam = priv;
struct device *dev = &sdam->pdev->dev;
int rc;
if (!sdam_is_valid(sdam, offset, bytes)) {
dev_err(dev, "Invalid SDAM offset %#x len=%zd\n",
offset, bytes);
return -EINVAL;
}
rc = regmap_bulk_read(sdam->regmap, sdam->base + offset, val, bytes);
if (rc < 0)
dev_err(dev, "Failed to read SDAM offset %#x len=%zd, rc=%d\n",
offset, bytes, rc);
return rc;
}
static int sdam_write(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct sdam_chip *sdam = priv;
struct device *dev = &sdam->pdev->dev;
int rc;
if (!sdam_is_valid(sdam, offset, bytes)) {
dev_err(dev, "Invalid SDAM offset %#x len=%zd\n",
offset, bytes);
return -EINVAL;
}
if (sdam_is_ro(offset, bytes)) {
dev_err(dev, "Invalid write offset %#x len=%zd\n",
offset, bytes);
return -EINVAL;
}
rc = regmap_bulk_write(sdam->regmap, sdam->base + offset, val, bytes);
if (rc < 0)
dev_err(dev, "Failed to write SDAM offset %#x len=%zd, rc=%d\n",
offset, bytes, rc);
return rc;
}
static int sdam_probe(struct platform_device *pdev)
{
struct sdam_chip *sdam;
struct nvmem_device *nvmem;
unsigned int val;
int rc;
sdam = devm_kzalloc(&pdev->dev, sizeof(*sdam), GFP_KERNEL);
if (!sdam)
return -ENOMEM;
sdam->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!sdam->regmap) {
dev_err(&pdev->dev, "Failed to get regmap handle\n");
return -ENXIO;
}
rc = of_property_read_u32(pdev->dev.of_node, "reg", &sdam->base);
if (rc < 0) {
dev_err(&pdev->dev, "Failed to get SDAM base, rc=%d\n", rc);
return -EINVAL;
}
rc = regmap_read(sdam->regmap, sdam->base + SDAM_SIZE, &val);
if (rc < 0) {
dev_err(&pdev->dev, "Failed to read SDAM_SIZE rc=%d\n", rc);
return -EINVAL;
}
sdam->size = val * 32;
sdam->sdam_config.dev = &pdev->dev;
sdam->sdam_config.name = "spmi_sdam";
sdam->sdam_config.id = pdev->id;
sdam->sdam_config.owner = THIS_MODULE,
sdam->sdam_config.stride = 1;
sdam->sdam_config.word_size = 1;
sdam->sdam_config.reg_read = sdam_read;
sdam->sdam_config.reg_write = sdam_write;
sdam->sdam_config.priv = sdam;
nvmem = devm_nvmem_register(&pdev->dev, &sdam->sdam_config);
if (IS_ERR(nvmem)) {
dev_err(&pdev->dev,
"Failed to register SDAM nvmem device rc=%ld\n",
PTR_ERR(nvmem));
return -ENXIO;
}
dev_dbg(&pdev->dev,
"SDAM base=%#x size=%u registered successfully\n",
sdam->base, sdam->size);
return 0;
}
static const struct of_device_id sdam_match_table[] = {
{ .compatible = "qcom,spmi-sdam" },
{},
};
static struct platform_driver sdam_driver = {
.driver = {
.name = "qcom,spmi-sdam",
.of_match_table = sdam_match_table,
},
.probe = sdam_probe,
};
static int __init sdam_init(void)
{
return platform_driver_register(&sdam_driver);
}
subsys_initcall(sdam_init);
static void __exit sdam_exit(void)
{
return platform_driver_unregister(&sdam_driver);
}
module_exit(sdam_exit);
MODULE_DESCRIPTION("QCOM SPMI SDAM driver");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0 /* SPDX-License-Identifier: GPL-2.0 */
/* /*
* Copyright (C) 2015-2017 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de> * Copyright (C) 2015-2017 Pengutronix, Uwe Kleine-König <kernel@pengutronix.de>
*/ */
......
...@@ -641,6 +641,8 @@ static int qcom_slim_remove(struct platform_device *pdev) ...@@ -641,6 +641,8 @@ static int qcom_slim_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
slim_unregister_controller(&ctrl->ctrl); slim_unregister_controller(&ctrl->ctrl);
clk_disable_unprepare(ctrl->rclk);
clk_disable_unprepare(ctrl->hclk);
destroy_workqueue(ctrl->rxwq); destroy_workqueue(ctrl->rxwq);
return 0; return 0;
} }
......
...@@ -666,10 +666,12 @@ static int qcom_slim_ngd_init_rx_msgq(struct qcom_slim_ngd_ctrl *ctrl) ...@@ -666,10 +666,12 @@ static int qcom_slim_ngd_init_rx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
struct device *dev = ctrl->dev; struct device *dev = ctrl->dev;
int ret, size; int ret, size;
ctrl->dma_rx_channel = dma_request_slave_channel(dev, "rx"); ctrl->dma_rx_channel = dma_request_chan(dev, "rx");
if (!ctrl->dma_rx_channel) { if (IS_ERR(ctrl->dma_rx_channel)) {
dev_err(dev, "Failed to request dma channels"); dev_err(dev, "Failed to request RX dma channel");
return -EINVAL; ret = PTR_ERR(ctrl->dma_rx_channel);
ctrl->dma_rx_channel = NULL;
return ret;
} }
size = QCOM_SLIM_NGD_DESC_NUM * SLIM_MSGQ_BUF_LEN; size = QCOM_SLIM_NGD_DESC_NUM * SLIM_MSGQ_BUF_LEN;
...@@ -703,10 +705,12 @@ static int qcom_slim_ngd_init_tx_msgq(struct qcom_slim_ngd_ctrl *ctrl) ...@@ -703,10 +705,12 @@ static int qcom_slim_ngd_init_tx_msgq(struct qcom_slim_ngd_ctrl *ctrl)
int ret = 0; int ret = 0;
int size; int size;
ctrl->dma_tx_channel = dma_request_slave_channel(dev, "tx"); ctrl->dma_tx_channel = dma_request_chan(dev, "tx");
if (!ctrl->dma_tx_channel) { if (IS_ERR(ctrl->dma_tx_channel)) {
dev_err(dev, "Failed to request dma channels"); dev_err(dev, "Failed to request TX dma channel");
return -EINVAL; ret = PTR_ERR(ctrl->dma_tx_channel);
ctrl->dma_tx_channel = NULL;
return ret;
} }
size = ((QCOM_SLIM_NGD_DESC_NUM + 1) * SLIM_MSGQ_BUF_LEN); size = ((QCOM_SLIM_NGD_DESC_NUM + 1) * SLIM_MSGQ_BUF_LEN);
......
// SPDX-License-Identifier: GPL-2.0 /* SPDX-License-Identifier: GPL-2.0 */
/* /*
* Copyright (c) 2011-2017, The Linux Foundation * Copyright (c) 2011-2017, The Linux Foundation
*/ */
......
...@@ -31,4 +31,13 @@ config SOUNDWIRE_INTEL ...@@ -31,4 +31,13 @@ config SOUNDWIRE_INTEL
enable this config option to get the SoundWire support for that enable this config option to get the SoundWire support for that
device. device.
config SOUNDWIRE_QCOM
tristate "Qualcomm SoundWire Master driver"
depends on SLIMBUS
depends on SND_SOC
help
SoundWire Qualcomm Master driver.
If you have an Qualcomm platform which has a SoundWire Master then
enable this config option to get the SoundWire support for that
device
endif endif
...@@ -21,3 +21,7 @@ obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel.o ...@@ -21,3 +21,7 @@ obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel.o
soundwire-intel-init-objs := intel_init.o soundwire-intel-init-objs := intel_init.o
obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel-init.o obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel-init.o
#Qualcomm driver
soundwire-qcom-objs := qcom.o
obj-$(CONFIG_SOUNDWIRE_QCOM) += soundwire-qcom.o
...@@ -456,9 +456,11 @@ static int sdw_get_device_num(struct sdw_slave *slave) ...@@ -456,9 +456,11 @@ static int sdw_get_device_num(struct sdw_slave *slave)
static int sdw_assign_device_num(struct sdw_slave *slave) static int sdw_assign_device_num(struct sdw_slave *slave)
{ {
int ret, dev_num; int ret, dev_num;
bool new_device = false;
/* check first if device number is assigned, if so reuse that */ /* check first if device number is assigned, if so reuse that */
if (!slave->dev_num) { if (!slave->dev_num) {
if (!slave->dev_num_sticky) {
mutex_lock(&slave->bus->bus_lock); mutex_lock(&slave->bus->bus_lock);
dev_num = sdw_get_device_num(slave); dev_num = sdw_get_device_num(slave);
mutex_unlock(&slave->bus->bus_lock); mutex_unlock(&slave->bus->bus_lock);
...@@ -467,15 +469,22 @@ static int sdw_assign_device_num(struct sdw_slave *slave) ...@@ -467,15 +469,22 @@ static int sdw_assign_device_num(struct sdw_slave *slave)
dev_num); dev_num);
return dev_num; return dev_num;
} }
slave->dev_num = dev_num;
slave->dev_num_sticky = dev_num;
new_device = true;
} else { } else {
slave->dev_num = slave->dev_num_sticky;
}
}
if (!new_device)
dev_info(slave->bus->dev, dev_info(slave->bus->dev,
"Slave already registered dev_num:%d\n", "Slave already registered, reusing dev_num:%d\n",
slave->dev_num); slave->dev_num);
/* Clear the slave->dev_num to transfer message on device 0 */ /* Clear the slave->dev_num to transfer message on device 0 */
dev_num = slave->dev_num; dev_num = slave->dev_num;
slave->dev_num = 0; slave->dev_num = 0;
}
ret = sdw_write(slave, SDW_SCP_DEVNUMBER, dev_num); ret = sdw_write(slave, SDW_SCP_DEVNUMBER, dev_num);
if (ret < 0) { if (ret < 0) {
...@@ -485,7 +494,7 @@ static int sdw_assign_device_num(struct sdw_slave *slave) ...@@ -485,7 +494,7 @@ static int sdw_assign_device_num(struct sdw_slave *slave)
} }
/* After xfer of msg, restore dev_num */ /* After xfer of msg, restore dev_num */
slave->dev_num = dev_num; slave->dev_num = slave->dev_num_sticky;
return 0; return 0;
} }
...@@ -979,6 +988,24 @@ int sdw_handle_slave_status(struct sdw_bus *bus, ...@@ -979,6 +988,24 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
struct sdw_slave *slave; struct sdw_slave *slave;
int i, ret = 0; int i, ret = 0;
/* first check if any Slaves fell off the bus */
for (i = 1; i <= SDW_MAX_DEVICES; i++) {
mutex_lock(&bus->bus_lock);
if (test_bit(i, bus->assigned) == false) {
mutex_unlock(&bus->bus_lock);
continue;
}
mutex_unlock(&bus->bus_lock);
slave = sdw_get_slave(bus, i);
if (!slave)
continue;
if (status[i] == SDW_SLAVE_UNATTACHED &&
slave->status != SDW_SLAVE_UNATTACHED)
sdw_modify_slave_status(slave, SDW_SLAVE_UNATTACHED);
}
if (status[0] == SDW_SLAVE_ATTACHED) { if (status[0] == SDW_SLAVE_ATTACHED) {
dev_dbg(bus->dev, "Slave attached, programming device number\n"); dev_dbg(bus->dev, "Slave attached, programming device number\n");
ret = sdw_program_device_num(bus); ret = sdw_program_device_num(bus);
......
...@@ -74,6 +74,7 @@ MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask"); ...@@ -74,6 +74,7 @@ MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask");
#define CDNS_MCP_INTMASK 0x48 #define CDNS_MCP_INTMASK 0x48
#define CDNS_MCP_INT_IRQ BIT(31) #define CDNS_MCP_INT_IRQ BIT(31)
#define CDNS_MCP_INT_RESERVED1 GENMASK(30, 17)
#define CDNS_MCP_INT_WAKEUP BIT(16) #define CDNS_MCP_INT_WAKEUP BIT(16)
#define CDNS_MCP_INT_SLAVE_RSVD BIT(15) #define CDNS_MCP_INT_SLAVE_RSVD BIT(15)
#define CDNS_MCP_INT_SLAVE_ALERT BIT(14) #define CDNS_MCP_INT_SLAVE_ALERT BIT(14)
...@@ -85,10 +86,12 @@ MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask"); ...@@ -85,10 +86,12 @@ MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask");
#define CDNS_MCP_INT_DATA_CLASH BIT(9) #define CDNS_MCP_INT_DATA_CLASH BIT(9)
#define CDNS_MCP_INT_PARITY BIT(8) #define CDNS_MCP_INT_PARITY BIT(8)
#define CDNS_MCP_INT_CMD_ERR BIT(7) #define CDNS_MCP_INT_CMD_ERR BIT(7)
#define CDNS_MCP_INT_RESERVED2 GENMASK(6, 4)
#define CDNS_MCP_INT_RX_NE BIT(3) #define CDNS_MCP_INT_RX_NE BIT(3)
#define CDNS_MCP_INT_RX_WL BIT(2) #define CDNS_MCP_INT_RX_WL BIT(2)
#define CDNS_MCP_INT_TXE BIT(1) #define CDNS_MCP_INT_TXE BIT(1)
#define CDNS_MCP_INT_TXF BIT(0) #define CDNS_MCP_INT_TXF BIT(0)
#define CDNS_MCP_INT_RESERVED (CDNS_MCP_INT_RESERVED1 | CDNS_MCP_INT_RESERVED2)
#define CDNS_MCP_INTSET 0x4C #define CDNS_MCP_INTSET 0x4C
...@@ -444,7 +447,8 @@ _cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd, ...@@ -444,7 +447,8 @@ _cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd,
time = wait_for_completion_timeout(&cdns->tx_complete, time = wait_for_completion_timeout(&cdns->tx_complete,
msecs_to_jiffies(CDNS_TX_TIMEOUT)); msecs_to_jiffies(CDNS_TX_TIMEOUT));
if (!time) { if (!time) {
dev_err(cdns->dev, "IO transfer timed out\n"); dev_err(cdns->dev, "IO transfer timed out, cmd %d device %d addr %x len %d\n",
cmd, msg->dev_num, msg->addr, msg->len);
msg->len = 0; msg->len = 0;
return SDW_CMD_TIMEOUT; return SDW_CMD_TIMEOUT;
} }
...@@ -672,13 +676,36 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns, ...@@ -672,13 +676,36 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
/* first check if Slave reported multiple status */ /* first check if Slave reported multiple status */
if (set_status > 1) { if (set_status > 1) {
u32 val;
dev_warn_ratelimited(cdns->dev, dev_warn_ratelimited(cdns->dev,
"Slave reported multiple Status: %d\n", "Slave %d reported multiple Status: %d\n",
mask); i, mask);
/*
* TODO: we need to reread the status here by /* check latest status extracted from PING commands */
* issuing a PING cmd val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
*/ val >>= (i * 2);
switch (val & 0x3) {
case 0:
status[i] = SDW_SLAVE_UNATTACHED;
break;
case 1:
status[i] = SDW_SLAVE_ATTACHED;
break;
case 2:
status[i] = SDW_SLAVE_ALERT;
break;
case 3:
default:
status[i] = SDW_SLAVE_RESERVED;
break;
}
dev_warn_ratelimited(cdns->dev,
"Slave %d status updated to %d\n",
i, status[i]);
} }
} }
...@@ -705,6 +732,10 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id) ...@@ -705,6 +732,10 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
int_status = cdns_readl(cdns, CDNS_MCP_INTSTAT); int_status = cdns_readl(cdns, CDNS_MCP_INTSTAT);
/* check for reserved values read as zero */
if (int_status & CDNS_MCP_INT_RESERVED)
return IRQ_NONE;
if (!(int_status & CDNS_MCP_INT_IRQ)) if (!(int_status & CDNS_MCP_INT_IRQ))
return IRQ_NONE; return IRQ_NONE;
...@@ -812,8 +843,9 @@ int sdw_cdns_exit_reset(struct sdw_cdns *cdns) ...@@ -812,8 +843,9 @@ int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
EXPORT_SYMBOL(sdw_cdns_exit_reset); EXPORT_SYMBOL(sdw_cdns_exit_reset);
/** /**
* sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config * sdw_cdns_enable_interrupt() - Enable SDW interrupts
* @cdns: Cadence instance * @cdns: Cadence instance
* @state: True if we are trying to enable interrupt.
*/ */
int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state) int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state)
{ {
...@@ -849,12 +881,21 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state) ...@@ -849,12 +881,21 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state)
mask = interrupt_mask; mask = interrupt_mask;
update_masks: update_masks:
/* clear slave interrupt status before enabling interrupt */
if (state) {
u32 slave_state;
slave_state = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0);
cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave_state);
slave_state = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave_state);
}
cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0, slave_intmask0); cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0, slave_intmask0);
cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1, slave_intmask1); cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1, slave_intmask1);
cdns_writel(cdns, CDNS_MCP_INTMASK, mask); cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
/* commit changes */ return 0;
return cdns_update_config(cdns);
} }
EXPORT_SYMBOL(sdw_cdns_enable_interrupt); EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
...@@ -948,8 +989,6 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns, ...@@ -948,8 +989,6 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
ret = cdns_allocate_pdi(cdns, &stream->out, ret = cdns_allocate_pdi(cdns, &stream->out,
stream->num_out, offset); stream->num_out, offset);
offset += stream->num_out;
if (ret) if (ret)
return ret; return ret;
...@@ -1224,8 +1263,10 @@ EXPORT_SYMBOL(cdns_set_sdw_stream); ...@@ -1224,8 +1263,10 @@ EXPORT_SYMBOL(cdns_set_sdw_stream);
* cdns_find_pdi() - Find a free PDI * cdns_find_pdi() - Find a free PDI
* *
* @cdns: Cadence instance * @cdns: Cadence instance
* @offset: Starting offset
* @num: Number of PDIs * @num: Number of PDIs
* @pdi: PDI instances * @pdi: PDI instances
* @dai_id: DAI id
* *
* Find a PDI for a given PDI array. The PDI num and dai_id are * Find a PDI for a given PDI array. The PDI num and dai_id are
* expected to match, return NULL otherwise. * expected to match, return NULL otherwise.
...@@ -1277,6 +1318,7 @@ EXPORT_SYMBOL(sdw_cdns_config_stream); ...@@ -1277,6 +1318,7 @@ EXPORT_SYMBOL(sdw_cdns_config_stream);
* @stream: Stream to be allocated * @stream: Stream to be allocated
* @ch: Channel count * @ch: Channel count
* @dir: Data direction * @dir: Data direction
* @dai_id: DAI id
*/ */
struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns, struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
struct sdw_cdns_streams *stream, struct sdw_cdns_streams *stream,
......
...@@ -880,6 +880,9 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus) ...@@ -880,6 +880,9 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
"intel-sdw-ip-clock", "intel-sdw-ip-clock",
&prop->mclk_freq); &prop->mclk_freq);
/* the values reported by BIOS are the 2x clock, not the bus clock */
prop->mclk_freq /= 2;
fwnode_property_read_u32(link, fwnode_property_read_u32(link,
"intel-quirk-mask", "intel-quirk-mask",
&quirk_mask); &quirk_mask);
......
This diff is collapsed.
...@@ -1554,8 +1554,6 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream) ...@@ -1554,8 +1554,6 @@ int sdw_prepare_stream(struct sdw_stream_runtime *stream)
sdw_acquire_bus_lock(stream); sdw_acquire_bus_lock(stream);
ret = _sdw_prepare_stream(stream); ret = _sdw_prepare_stream(stream);
if (ret < 0)
pr_err("Prepare for stream:%s failed: %d\n", stream->name, ret);
sdw_release_bus_lock(stream); sdw_release_bus_lock(stream);
return ret; return ret;
...@@ -1622,8 +1620,6 @@ int sdw_enable_stream(struct sdw_stream_runtime *stream) ...@@ -1622,8 +1620,6 @@ int sdw_enable_stream(struct sdw_stream_runtime *stream)
sdw_acquire_bus_lock(stream); sdw_acquire_bus_lock(stream);
ret = _sdw_enable_stream(stream); ret = _sdw_enable_stream(stream);
if (ret < 0)
pr_err("Enable for stream:%s failed: %d\n", stream->name, ret);
sdw_release_bus_lock(stream); sdw_release_bus_lock(stream);
return ret; return ret;
...@@ -1698,8 +1694,6 @@ int sdw_disable_stream(struct sdw_stream_runtime *stream) ...@@ -1698,8 +1694,6 @@ int sdw_disable_stream(struct sdw_stream_runtime *stream)
sdw_acquire_bus_lock(stream); sdw_acquire_bus_lock(stream);
ret = _sdw_disable_stream(stream); ret = _sdw_disable_stream(stream);
if (ret < 0)
pr_err("Disable for stream:%s failed: %d\n", stream->name, ret);
sdw_release_bus_lock(stream); sdw_release_bus_lock(stream);
return ret; return ret;
...@@ -1756,8 +1750,6 @@ int sdw_deprepare_stream(struct sdw_stream_runtime *stream) ...@@ -1756,8 +1750,6 @@ int sdw_deprepare_stream(struct sdw_stream_runtime *stream)
sdw_acquire_bus_lock(stream); sdw_acquire_bus_lock(stream);
ret = _sdw_deprepare_stream(stream); ret = _sdw_deprepare_stream(stream);
if (ret < 0)
pr_err("De-prepare for stream:%d failed: %d\n", ret, ret);
sdw_release_bus_lock(stream); sdw_release_bus_lock(stream);
return ret; return ret;
......
...@@ -132,11 +132,13 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) ...@@ -132,11 +132,13 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)
if (irq_on) { if (irq_on) {
if (test_and_clear_bit(0, &priv->flags)) if (test_and_clear_bit(0, &priv->flags))
enable_irq(dev_info->irq); enable_irq(dev_info->irq);
spin_unlock_irqrestore(&priv->lock, flags);
} else { } else {
if (!test_and_set_bit(0, &priv->flags)) if (!test_and_set_bit(0, &priv->flags)) {
spin_unlock_irqrestore(&priv->lock, flags);
disable_irq(dev_info->irq); disable_irq(dev_info->irq);
} }
spin_unlock_irqrestore(&priv->lock, flags); }
return 0; return 0;
} }
......
...@@ -156,6 +156,8 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev) ...@@ -156,6 +156,8 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
uioinfo->irq = ret; uioinfo->irq = ret;
if (ret == -ENXIO && pdev->dev.of_node) if (ret == -ENXIO && pdev->dev.of_node)
uioinfo->irq = UIO_IRQ_NONE; uioinfo->irq = UIO_IRQ_NONE;
else if (ret == -EPROBE_DEFER)
return ret;
else if (ret < 0) { else if (ret < 0) {
dev_err(&pdev->dev, "failed to get IRQ\n"); dev_err(&pdev->dev, "failed to get IRQ\n");
return ret; return ret;
......
...@@ -1210,14 +1210,17 @@ static void setup_crash_devices_work_queue(struct work_struct *work) ...@@ -1210,14 +1210,17 @@ static void setup_crash_devices_work_queue(struct work_struct *work)
{ {
struct controlvm_message local_crash_bus_msg; struct controlvm_message local_crash_bus_msg;
struct controlvm_message local_crash_dev_msg; struct controlvm_message local_crash_dev_msg;
struct controlvm_message msg; struct controlvm_message msg = {
.hdr.id = CONTROLVM_CHIPSET_INIT,
.cmd.init_chipset = {
.bus_count = 23,
.switch_count = 0,
},
};
u32 local_crash_msg_offset; u32 local_crash_msg_offset;
u16 local_crash_msg_count; u16 local_crash_msg_count;
/* send init chipset msg */ /* send init chipset msg */
msg.hdr.id = CONTROLVM_CHIPSET_INIT;
msg.cmd.init_chipset.bus_count = 23;
msg.cmd.init_chipset.switch_count = 0;
chipset_init(&msg); chipset_init(&msg);
/* get saved message count */ /* get saved message count */
if (visorchannel_read(chipset_dev->controlvm_channel, if (visorchannel_read(chipset_dev->controlvm_channel,
......
...@@ -414,7 +414,8 @@ static void fake_lm_check(struct fake_driver *bridge, unsigned long long addr, ...@@ -414,7 +414,8 @@ static void fake_lm_check(struct fake_driver *bridge, unsigned long long addr,
} }
} }
static u8 fake_vmeread8(struct fake_driver *bridge, unsigned long long addr, static noinline_for_stack u8 fake_vmeread8(struct fake_driver *bridge,
unsigned long long addr,
u32 aspace, u32 cycle) u32 aspace, u32 cycle)
{ {
u8 retval = 0xff; u8 retval = 0xff;
...@@ -446,7 +447,8 @@ static u8 fake_vmeread8(struct fake_driver *bridge, unsigned long long addr, ...@@ -446,7 +447,8 @@ static u8 fake_vmeread8(struct fake_driver *bridge, unsigned long long addr,
return retval; return retval;
} }
static u16 fake_vmeread16(struct fake_driver *bridge, unsigned long long addr, static noinline_for_stack u16 fake_vmeread16(struct fake_driver *bridge,
unsigned long long addr,
u32 aspace, u32 cycle) u32 aspace, u32 cycle)
{ {
u16 retval = 0xffff; u16 retval = 0xffff;
...@@ -478,7 +480,8 @@ static u16 fake_vmeread16(struct fake_driver *bridge, unsigned long long addr, ...@@ -478,7 +480,8 @@ static u16 fake_vmeread16(struct fake_driver *bridge, unsigned long long addr,
return retval; return retval;
} }
static u32 fake_vmeread32(struct fake_driver *bridge, unsigned long long addr, static noinline_for_stack u32 fake_vmeread32(struct fake_driver *bridge,
unsigned long long addr,
u32 aspace, u32 cycle) u32 aspace, u32 cycle)
{ {
u32 retval = 0xffffffff; u32 retval = 0xffffffff;
...@@ -609,8 +612,9 @@ static ssize_t fake_master_read(struct vme_master_resource *image, void *buf, ...@@ -609,8 +612,9 @@ static ssize_t fake_master_read(struct vme_master_resource *image, void *buf,
return retval; return retval;
} }
static void fake_vmewrite8(struct fake_driver *bridge, u8 *buf, static noinline_for_stack void fake_vmewrite8(struct fake_driver *bridge,
unsigned long long addr, u32 aspace, u32 cycle) u8 *buf, unsigned long long addr,
u32 aspace, u32 cycle)
{ {
int i; int i;
unsigned long long start, end, offset; unsigned long long start, end, offset;
...@@ -639,8 +643,9 @@ static void fake_vmewrite8(struct fake_driver *bridge, u8 *buf, ...@@ -639,8 +643,9 @@ static void fake_vmewrite8(struct fake_driver *bridge, u8 *buf,
} }
static void fake_vmewrite16(struct fake_driver *bridge, u16 *buf, static noinline_for_stack void fake_vmewrite16(struct fake_driver *bridge,
unsigned long long addr, u32 aspace, u32 cycle) u16 *buf, unsigned long long addr,
u32 aspace, u32 cycle)
{ {
int i; int i;
unsigned long long start, end, offset; unsigned long long start, end, offset;
...@@ -669,8 +674,9 @@ static void fake_vmewrite16(struct fake_driver *bridge, u16 *buf, ...@@ -669,8 +674,9 @@ static void fake_vmewrite16(struct fake_driver *bridge, u16 *buf,
} }
static void fake_vmewrite32(struct fake_driver *bridge, u32 *buf, static noinline_for_stack void fake_vmewrite32(struct fake_driver *bridge,
unsigned long long addr, u32 aspace, u32 cycle) u32 *buf, unsigned long long addr,
u32 aspace, u32 cycle)
{ {
int i; int i;
unsigned long long start, end, offset; unsigned long long start, end, offset;
......
This diff is collapsed.
This diff is collapsed.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define PCI_ID_ALCOR_MICRO 0x1AEA #define PCI_ID_ALCOR_MICRO 0x1AEA
#define PCI_ID_AU6601 0x6601 #define PCI_ID_AU6601 0x6601
#define PCI_ID_AU6621 0x6621 #define PCI_ID_AU6621 0x6621
#define PCI_ID_AU6625 0x6625
#define MHZ_TO_HZ(freq) ((freq) * 1000 * 1000) #define MHZ_TO_HZ(freq) ((freq) * 1000 * 1000)
......
This diff is collapsed.
This diff is collapsed.
...@@ -546,7 +546,8 @@ struct sdw_slave_ops { ...@@ -546,7 +546,8 @@ struct sdw_slave_ops {
* @debugfs: Slave debugfs * @debugfs: Slave debugfs
* @node: node for bus list * @node: node for bus list
* @port_ready: Port ready completion flag for each Slave port * @port_ready: Port ready completion flag for each Slave port
* @dev_num: Device Number assigned by Bus * @dev_num: Current Device Number, values can be 0 or dev_num_sticky
* @dev_num_sticky: one-time static Device Number assigned by Bus
* @probed: boolean tracking driver state * @probed: boolean tracking driver state
* @probe_complete: completion utility to control potential races * @probe_complete: completion utility to control potential races
* on startup between driver probe/initialization and SoundWire * on startup between driver probe/initialization and SoundWire
...@@ -575,6 +576,7 @@ struct sdw_slave { ...@@ -575,6 +576,7 @@ struct sdw_slave {
struct list_head node; struct list_head node;
struct completion *port_ready; struct completion *port_ready;
u16 dev_num; u16 dev_num;
u16 dev_num_sticky;
bool probed; bool probed;
struct completion probe_complete; struct completion probe_complete;
struct completion enumeration_complete; struct completion enumeration_complete;
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment