Import of kernel-5.14.0-611.13.1.el9_7
This commit is contained in:
parent
1e764b8f70
commit
e239c331eb
76
Documentation/devicetree/bindings/dpll/dpll-device.yaml
Normal file
76
Documentation/devicetree/bindings/dpll/dpll-device.yaml
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/dpll/dpll-device.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Digital Phase-Locked Loop (DPLL) Device
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Ivan Vecera <ivecera@redhat.com>
|
||||||
|
|
||||||
|
description:
|
||||||
|
Digital Phase-Locked Loop (DPLL) device is used for precise clock
|
||||||
|
synchronization in networking and telecom hardware. The device can
|
||||||
|
have one or more channels (DPLLs) and one or more physical input and
|
||||||
|
output pins. Each DPLL channel can either produce pulse-per-clock signal
|
||||||
|
or drive ethernet equipment clock. The type of each channel can be
|
||||||
|
indicated by dpll-types property.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
$nodename:
|
||||||
|
pattern: "^dpll(@.*)?$"
|
||||||
|
|
||||||
|
"#address-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
"#size-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
dpll-types:
|
||||||
|
description: List of DPLL channel types, one per DPLL instance.
|
||||||
|
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||||
|
items:
|
||||||
|
enum: [pps, eec]
|
||||||
|
|
||||||
|
input-pins:
|
||||||
|
type: object
|
||||||
|
description: DPLL input pins
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
"#address-cells":
|
||||||
|
const: 1
|
||||||
|
"#size-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^pin@[0-9a-f]+$":
|
||||||
|
$ref: /schemas/dpll/dpll-pin.yaml
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- "#address-cells"
|
||||||
|
- "#size-cells"
|
||||||
|
|
||||||
|
output-pins:
|
||||||
|
type: object
|
||||||
|
description: DPLL output pins
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
properties:
|
||||||
|
"#address-cells":
|
||||||
|
const: 1
|
||||||
|
"#size-cells":
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"^pin@[0-9]+$":
|
||||||
|
$ref: /schemas/dpll/dpll-pin.yaml
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- "#address-cells"
|
||||||
|
- "#size-cells"
|
||||||
|
|
||||||
|
additionalProperties: true
|
||||||
45
Documentation/devicetree/bindings/dpll/dpll-pin.yaml
Normal file
45
Documentation/devicetree/bindings/dpll/dpll-pin.yaml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/dpll/dpll-pin.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: DPLL Pin
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Ivan Vecera <ivecera@redhat.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
The DPLL pin is either a physical input or output pin that is provided
|
||||||
|
by a DPLL( Digital Phase-Locked Loop) device. The pin is identified by
|
||||||
|
its physical order number that is stored in reg property and can have
|
||||||
|
an additional set of properties like supported (allowed) frequencies,
|
||||||
|
label, type and may support embedded sync.
|
||||||
|
|
||||||
|
Note that the pin in this context has nothing to do with pinctrl.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
description: Hardware index of the DPLL pin.
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
connection-type:
|
||||||
|
description: Connection type of the pin
|
||||||
|
$ref: /schemas/types.yaml#/definitions/string
|
||||||
|
enum: [ext, gnss, int, mux, synce]
|
||||||
|
|
||||||
|
esync-control:
|
||||||
|
description: Indicates whether the pin supports embedded sync functionality.
|
||||||
|
type: boolean
|
||||||
|
|
||||||
|
label:
|
||||||
|
description: String exposed as the pin board label
|
||||||
|
$ref: /schemas/types.yaml#/definitions/string
|
||||||
|
|
||||||
|
supported-frequencies-hz:
|
||||||
|
description: List of supported frequencies for this pin, expressed in Hz.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
115
Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml
Normal file
115
Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/dpll/microchip,zl30731.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Microchip Azurite DPLL device
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Ivan Vecera <ivecera@redhat.com>
|
||||||
|
|
||||||
|
description:
|
||||||
|
Microchip Azurite DPLL (ZL3073x) is a family of DPLL devices that
|
||||||
|
provides up to 5 independent DPLL channels, up to 10 differential or
|
||||||
|
single-ended inputs and 10 differential or 20 single-ended outputs.
|
||||||
|
These devices support both I2C and SPI interfaces.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- microchip,zl30731
|
||||||
|
- microchip,zl30732
|
||||||
|
- microchip,zl30733
|
||||||
|
- microchip,zl30734
|
||||||
|
- microchip,zl30735
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- $ref: /schemas/dpll/dpll-device.yaml#
|
||||||
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
i2c {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
dpll@70 {
|
||||||
|
compatible = "microchip,zl30732";
|
||||||
|
reg = <0x70>;
|
||||||
|
dpll-types = "pps", "eec";
|
||||||
|
|
||||||
|
input-pins {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
pin@0 { /* REF0P */
|
||||||
|
reg = <0>;
|
||||||
|
connection-type = "ext";
|
||||||
|
label = "Input 0";
|
||||||
|
supported-frequencies-hz = /bits/ 64 <1 1000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
output-pins {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
pin@3 { /* OUT1N */
|
||||||
|
reg = <3>;
|
||||||
|
connection-type = "gnss";
|
||||||
|
esync-control;
|
||||||
|
label = "Output 1";
|
||||||
|
supported-frequencies-hz = /bits/ 64 <1 10000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
- |
|
||||||
|
spi {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
dpll@70 {
|
||||||
|
compatible = "microchip,zl30731";
|
||||||
|
reg = <0x70>;
|
||||||
|
spi-max-frequency = <12500000>;
|
||||||
|
|
||||||
|
dpll-types = "pps";
|
||||||
|
|
||||||
|
input-pins {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
pin@0 { /* REF0P */
|
||||||
|
reg = <0>;
|
||||||
|
connection-type = "ext";
|
||||||
|
label = "Input 0";
|
||||||
|
supported-frequencies-hz = /bits/ 64 <1 1000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
output-pins {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
pin@3 { /* OUT1N */
|
||||||
|
reg = <3>;
|
||||||
|
connection-type = "gnss";
|
||||||
|
esync-control;
|
||||||
|
label = "Output 1";
|
||||||
|
supported-frequencies-hz = /bits/ 64 <1 10000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
||||||
@ -96,3 +96,4 @@ parameters, info versions, and other features it supports.
|
|||||||
prestera
|
prestera
|
||||||
iosm
|
iosm
|
||||||
sfc
|
sfc
|
||||||
|
zl3073x
|
||||||
|
|||||||
65
Documentation/networking/devlink/zl3073x.rst
Normal file
65
Documentation/networking/devlink/zl3073x.rst
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
.. SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
=======================
|
||||||
|
zl3073x devlink support
|
||||||
|
=======================
|
||||||
|
|
||||||
|
This document describes the devlink features implemented by the ``zl3073x``
|
||||||
|
device driver.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. list-table:: Generic parameters implemented
|
||||||
|
:widths: 5 5 90
|
||||||
|
|
||||||
|
* - Name
|
||||||
|
- Mode
|
||||||
|
- Notes
|
||||||
|
* - ``clock_id``
|
||||||
|
- driverinit
|
||||||
|
- Set the clock ID that is used by the driver for registering DPLL devices
|
||||||
|
and pins.
|
||||||
|
|
||||||
|
Info versions
|
||||||
|
=============
|
||||||
|
|
||||||
|
The ``zl3073x`` driver reports the following versions
|
||||||
|
|
||||||
|
.. list-table:: devlink info versions implemented
|
||||||
|
:widths: 5 5 5 90
|
||||||
|
|
||||||
|
* - Name
|
||||||
|
- Type
|
||||||
|
- Example
|
||||||
|
- Description
|
||||||
|
* - ``asic.id``
|
||||||
|
- fixed
|
||||||
|
- 1E94
|
||||||
|
- Chip identification number
|
||||||
|
* - ``asic.rev``
|
||||||
|
- fixed
|
||||||
|
- 300
|
||||||
|
- Chip revision number
|
||||||
|
* - ``fw``
|
||||||
|
- running
|
||||||
|
- 7006
|
||||||
|
- Firmware version number
|
||||||
|
* - ``custom_cfg``
|
||||||
|
- running
|
||||||
|
- 1.3.0.1
|
||||||
|
- Device configuration version customized by OEM
|
||||||
|
|
||||||
|
Flash Update
|
||||||
|
============
|
||||||
|
|
||||||
|
The ``zl3073x`` driver implements support for flash update using the
|
||||||
|
``devlink-flash`` interface. It supports updating the device flash using a
|
||||||
|
combined flash image ("bundle") that contains multiple components (firmware
|
||||||
|
parts and configurations).
|
||||||
|
|
||||||
|
During the flash procedure, the standard firmware interface is not available,
|
||||||
|
so the driver unregisters all DPLLs and associated pins, and re-registers them
|
||||||
|
once the flash procedure is complete.
|
||||||
|
|
||||||
|
The driver does not support any overwrite mask flags.
|
||||||
10
MAINTAINERS
10
MAINTAINERS
@ -5946,6 +5946,8 @@ M: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
|
|||||||
M: Jiri Pirko <jiri@resnulli.us>
|
M: Jiri Pirko <jiri@resnulli.us>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
F: Documentation/devicetree/bindings/dpll/dpll-device.yaml
|
||||||
|
F: Documentation/devicetree/bindings/dpll/dpll-pin.yaml
|
||||||
F: Documentation/driver-api/dpll.rst
|
F: Documentation/driver-api/dpll.rst
|
||||||
F: drivers/dpll/*
|
F: drivers/dpll/*
|
||||||
F: include/linux/dpll.h
|
F: include/linux/dpll.h
|
||||||
@ -12924,6 +12926,14 @@ L: linux-wireless@vger.kernel.org
|
|||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/wireless/microchip/wilc1000/
|
F: drivers/net/wireless/microchip/wilc1000/
|
||||||
|
|
||||||
|
MICROCHIP ZL3073X DRIVER
|
||||||
|
M: Ivan Vecera <ivecera@redhat.com>
|
||||||
|
M: Prathosh Satish <Prathosh.Satish@microchip.com>
|
||||||
|
L: netdev@vger.kernel.org
|
||||||
|
S: Supported
|
||||||
|
F: Documentation/devicetree/bindings/dpll/microchip,zl30731.yaml
|
||||||
|
F: drivers/dpll/zl3073x/
|
||||||
|
|
||||||
MICROSEMI MIPS SOCS
|
MICROSEMI MIPS SOCS
|
||||||
M: Alexandre Belloni <alexandre.belloni@bootlin.com>
|
M: Alexandre Belloni <alexandre.belloni@bootlin.com>
|
||||||
M: UNGLinuxDriver@microchip.com
|
M: UNGLinuxDriver@microchip.com
|
||||||
|
|||||||
@ -12,7 +12,7 @@ RHEL_MINOR = 7
|
|||||||
#
|
#
|
||||||
# Use this spot to avoid future merge conflicts.
|
# Use this spot to avoid future merge conflicts.
|
||||||
# Do not trim this comment.
|
# Do not trim this comment.
|
||||||
RHEL_RELEASE = 611.11.1
|
RHEL_RELEASE = 611.13.1
|
||||||
|
|
||||||
#
|
#
|
||||||
# ZSTREAM
|
# ZSTREAM
|
||||||
|
|||||||
@ -462,6 +462,195 @@ void hv_ivm_msr_read(u64 msr, u64 *value)
|
|||||||
hv_ghcb_msr_read(msr, value);
|
hv_ghcb_msr_read(msr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keep track of the PFN regions which were shared with the host. The access
|
||||||
|
* must be revoked upon kexec/kdump (see hv_ivm_clear_host_access()).
|
||||||
|
*/
|
||||||
|
struct hv_enc_pfn_region {
|
||||||
|
struct list_head list;
|
||||||
|
u64 pfn;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static LIST_HEAD(hv_list_enc);
|
||||||
|
static DEFINE_RAW_SPINLOCK(hv_list_enc_lock);
|
||||||
|
|
||||||
|
static int hv_list_enc_add(const u64 *pfn_list, int count)
|
||||||
|
{
|
||||||
|
struct hv_enc_pfn_region *ent;
|
||||||
|
unsigned long flags;
|
||||||
|
u64 pfn;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
pfn = pfn_list[i];
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||||
|
/* Check if the PFN already exists in some region first */
|
||||||
|
list_for_each_entry(ent, &hv_list_enc, list) {
|
||||||
|
if ((ent->pfn <= pfn) && (ent->pfn + ent->count - 1 >= pfn))
|
||||||
|
/* Nothing to do - pfn is already in the list */
|
||||||
|
goto unlock_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the PFN is adjacent to an existing region. Growing
|
||||||
|
* a region can make it adjacent to another one but merging is
|
||||||
|
* not (yet) implemented for simplicity. A PFN cannot be added
|
||||||
|
* to two regions to keep the logic in hv_list_enc_remove()
|
||||||
|
* correct.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(ent, &hv_list_enc, list) {
|
||||||
|
if (ent->pfn + ent->count == pfn) {
|
||||||
|
/* Grow existing region up */
|
||||||
|
ent->count++;
|
||||||
|
goto unlock_done;
|
||||||
|
} else if (pfn + 1 == ent->pfn) {
|
||||||
|
/* Grow existing region down */
|
||||||
|
ent->pfn--;
|
||||||
|
ent->count++;
|
||||||
|
goto unlock_done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||||
|
|
||||||
|
/* No adjacent region found -- create a new one */
|
||||||
|
ent = kzalloc(sizeof(struct hv_enc_pfn_region), GFP_KERNEL);
|
||||||
|
if (!ent)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ent->pfn = pfn;
|
||||||
|
ent->count = 1;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||||
|
list_add(&ent->list, &hv_list_enc);
|
||||||
|
|
||||||
|
unlock_done:
|
||||||
|
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hv_list_enc_remove(const u64 *pfn_list, int count)
|
||||||
|
{
|
||||||
|
struct hv_enc_pfn_region *ent, *t;
|
||||||
|
struct hv_enc_pfn_region new_region;
|
||||||
|
unsigned long flags;
|
||||||
|
u64 pfn;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
pfn = pfn_list[i];
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||||
|
list_for_each_entry_safe(ent, t, &hv_list_enc, list) {
|
||||||
|
if (pfn == ent->pfn + ent->count - 1) {
|
||||||
|
/* Removing tail pfn */
|
||||||
|
ent->count--;
|
||||||
|
if (!ent->count) {
|
||||||
|
list_del(&ent->list);
|
||||||
|
kfree(ent);
|
||||||
|
}
|
||||||
|
goto unlock_done;
|
||||||
|
} else if (pfn == ent->pfn) {
|
||||||
|
/* Removing head pfn */
|
||||||
|
ent->count--;
|
||||||
|
ent->pfn++;
|
||||||
|
if (!ent->count) {
|
||||||
|
list_del(&ent->list);
|
||||||
|
kfree(ent);
|
||||||
|
}
|
||||||
|
goto unlock_done;
|
||||||
|
} else if (pfn > ent->pfn && pfn < ent->pfn + ent->count - 1) {
|
||||||
|
/*
|
||||||
|
* Removing a pfn in the middle. Cut off the tail
|
||||||
|
* of the existing region and create a template for
|
||||||
|
* the new one.
|
||||||
|
*/
|
||||||
|
new_region.pfn = pfn + 1;
|
||||||
|
new_region.count = ent->count - (pfn - ent->pfn + 1);
|
||||||
|
ent->count = pfn - ent->pfn;
|
||||||
|
goto unlock_split;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
unlock_done:
|
||||||
|
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unlock_split:
|
||||||
|
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||||
|
|
||||||
|
ent = kzalloc(sizeof(struct hv_enc_pfn_region), GFP_KERNEL);
|
||||||
|
if (!ent)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ent->pfn = new_region.pfn;
|
||||||
|
ent->count = new_region.count;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&hv_list_enc_lock, flags);
|
||||||
|
list_add(&ent->list, &hv_list_enc);
|
||||||
|
raw_spin_unlock_irqrestore(&hv_list_enc_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop new private<->shared conversions */
|
||||||
|
static void hv_vtom_kexec_begin(void)
|
||||||
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crash kernel reaches here with interrupts disabled: can't wait for
|
||||||
|
* conversions to finish.
|
||||||
|
*
|
||||||
|
* If race happened, just report and proceed.
|
||||||
|
*/
|
||||||
|
if (!set_memory_enc_stop_conversion())
|
||||||
|
pr_warn("Failed to stop shared<->private conversions\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hv_vtom_kexec_finish(void)
|
||||||
|
{
|
||||||
|
struct hv_gpa_range_for_visibility *input;
|
||||||
|
struct hv_enc_pfn_region *ent;
|
||||||
|
unsigned long flags;
|
||||||
|
u64 hv_status;
|
||||||
|
int cur, i;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
|
||||||
|
|
||||||
|
if (unlikely(!input))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
list_for_each_entry(ent, &hv_list_enc, list) {
|
||||||
|
for (i = 0, cur = 0; i < ent->count; i++) {
|
||||||
|
input->gpa_page_list[cur] = ent->pfn + i;
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
if (cur == HV_MAX_MODIFY_GPA_REP_COUNT || i == ent->count - 1) {
|
||||||
|
input->partition_id = HV_PARTITION_ID_SELF;
|
||||||
|
input->host_visibility = VMBUS_PAGE_NOT_VISIBLE;
|
||||||
|
input->reserved0 = 0;
|
||||||
|
input->reserved1 = 0;
|
||||||
|
hv_status = hv_do_rep_hypercall(
|
||||||
|
HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY,
|
||||||
|
cur, 0, input, NULL);
|
||||||
|
WARN_ON_ONCE(!hv_result_success(hv_status));
|
||||||
|
cur = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
local_irq_restore(flags);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hv_mark_gpa_visibility - Set pages visible to host via hvcall.
|
* hv_mark_gpa_visibility - Set pages visible to host via hvcall.
|
||||||
*
|
*
|
||||||
@ -475,6 +664,7 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
|
|||||||
struct hv_gpa_range_for_visibility *input;
|
struct hv_gpa_range_for_visibility *input;
|
||||||
u64 hv_status;
|
u64 hv_status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* no-op if partition isolation is not enabled */
|
/* no-op if partition isolation is not enabled */
|
||||||
if (!hv_is_isolation_supported())
|
if (!hv_is_isolation_supported())
|
||||||
@ -486,6 +676,13 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (visibility == VMBUS_PAGE_NOT_VISIBLE)
|
||||||
|
ret = hv_list_enc_remove(pfn, count);
|
||||||
|
else
|
||||||
|
ret = hv_list_enc_add(pfn, count);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
|
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
|
||||||
|
|
||||||
@ -506,8 +703,18 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
|
|||||||
|
|
||||||
if (hv_result_success(hv_status))
|
if (hv_result_success(hv_status))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (visibility == VMBUS_PAGE_NOT_VISIBLE)
|
||||||
|
ret = hv_list_enc_add(pfn, count);
|
||||||
else
|
else
|
||||||
return -EFAULT;
|
ret = hv_list_enc_remove(pfn, count);
|
||||||
|
/*
|
||||||
|
* There's no good way to recover from -ENOMEM here, the accounting is
|
||||||
|
* wrong either way.
|
||||||
|
*/
|
||||||
|
WARN_ON_ONCE(ret);
|
||||||
|
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -669,6 +876,8 @@ void __init hv_vtom_init(void)
|
|||||||
x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required;
|
x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required;
|
||||||
x86_platform.guest.enc_status_change_prepare = hv_vtom_clear_present;
|
x86_platform.guest.enc_status_change_prepare = hv_vtom_clear_present;
|
||||||
x86_platform.guest.enc_status_change_finish = hv_vtom_set_host_visibility;
|
x86_platform.guest.enc_status_change_finish = hv_vtom_set_host_visibility;
|
||||||
|
x86_platform.guest.enc_kexec_begin = hv_vtom_kexec_begin;
|
||||||
|
x86_platform.guest.enc_kexec_finish = hv_vtom_kexec_finish;
|
||||||
|
|
||||||
/* Set WB as the default cache mode. */
|
/* Set WB as the default cache mode. */
|
||||||
mtrr_overwrite_state(NULL, 0, MTRR_TYPE_WRBACK);
|
mtrr_overwrite_state(NULL, 0, MTRR_TYPE_WRBACK);
|
||||||
|
|||||||
@ -4093,6 +4093,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7269,7 +7278,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
CONFIG_HTE_TEGRA194_TEST=m
|
CONFIG_HTE_TEGRA194_TEST=m
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4076,6 +4076,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7246,7 +7255,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
# CONFIG_HTE_TEGRA194_TEST is not set
|
# CONFIG_HTE_TEGRA194_TEST is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4097,6 +4097,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7274,7 +7283,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
CONFIG_HTE_TEGRA194_TEST=m
|
CONFIG_HTE_TEGRA194_TEST=m
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4096,6 +4096,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7273,7 +7282,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
CONFIG_HTE_TEGRA194_TEST=m
|
CONFIG_HTE_TEGRA194_TEST=m
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4080,6 +4080,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7251,7 +7260,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
# CONFIG_HTE_TEGRA194_TEST is not set
|
# CONFIG_HTE_TEGRA194_TEST is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4098,6 +4098,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7276,7 +7285,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
CONFIG_HTE_TEGRA194_TEST=m
|
CONFIG_HTE_TEGRA194_TEST=m
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4082,6 +4082,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7254,7 +7263,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
# CONFIG_HTE_TEGRA194_TEST is not set
|
# CONFIG_HTE_TEGRA194_TEST is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4080,6 +4080,15 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
CONFIG_GENERIC_PINCTRL_GROUPS=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
@ -7251,7 +7260,6 @@ CONFIG_INTERCONNECT_IMX8MP=m
|
|||||||
CONFIG_HTE=y
|
CONFIG_HTE=y
|
||||||
CONFIG_HTE_TEGRA194=m
|
CONFIG_HTE_TEGRA194=m
|
||||||
# CONFIG_HTE_TEGRA194_TEST is not set
|
# CONFIG_HTE_TEGRA194_TEST is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3325,6 +3325,14 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
CONFIG_GPIOLIB=y
|
CONFIG_GPIOLIB=y
|
||||||
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
||||||
@ -5679,7 +5687,6 @@ CONFIG_NVMEM_SYSFS=y
|
|||||||
# CONFIG_COUNTER is not set
|
# CONFIG_COUNTER is not set
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3342,6 +3342,14 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
CONFIG_GPIOLIB=y
|
CONFIG_GPIOLIB=y
|
||||||
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
||||||
@ -5696,7 +5704,6 @@ CONFIG_NVMEM_SYSFS=y
|
|||||||
# CONFIG_COUNTER is not set
|
# CONFIG_COUNTER is not set
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3345,6 +3345,14 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
CONFIG_GPIOLIB=y
|
CONFIG_GPIOLIB=y
|
||||||
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
||||||
@ -5693,7 +5701,6 @@ CONFIG_NVMEM_SYSFS=y
|
|||||||
# CONFIG_COUNTER is not set
|
# CONFIG_COUNTER is not set
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3328,6 +3328,14 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
CONFIG_GPIOLIB=y
|
CONFIG_GPIOLIB=y
|
||||||
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
|
||||||
@ -5676,7 +5684,6 @@ CONFIG_NVMEM_SYSFS=y
|
|||||||
# CONFIG_COUNTER is not set
|
# CONFIG_COUNTER is not set
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -2400,6 +2400,13 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
# CONFIG_ZL3073X_I2C is not set
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
# CONFIG_GPIOLIB is not set
|
# CONFIG_GPIOLIB is not set
|
||||||
# CONFIG_W1 is not set
|
# CONFIG_W1 is not set
|
||||||
@ -2979,7 +2986,6 @@ CONFIG_NVMEM_SYSFS=y
|
|||||||
# CONFIG_COUNTER is not set
|
# CONFIG_COUNTER is not set
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -1002,6 +1002,11 @@ CONFIG_PTP_1588_CLOCK_OPTIONAL=y
|
|||||||
# CONFIG_PTP_1588_CLOCK_MOCK is not set
|
# CONFIG_PTP_1588_CLOCK_MOCK is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
# CONFIG_GPIOLIB is not set
|
# CONFIG_GPIOLIB is not set
|
||||||
CONFIG_POWER_RESET=y
|
CONFIG_POWER_RESET=y
|
||||||
|
|||||||
@ -2423,6 +2423,13 @@ CONFIG_PTP_1588_CLOCK_MOCK=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
# CONFIG_ZL3073X_I2C is not set
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
# CONFIG_PINCTRL is not set
|
# CONFIG_PINCTRL is not set
|
||||||
# CONFIG_GPIOLIB is not set
|
# CONFIG_GPIOLIB is not set
|
||||||
# CONFIG_W1 is not set
|
# CONFIG_W1 is not set
|
||||||
@ -3002,7 +3009,6 @@ CONFIG_NVMEM_SYSFS=y
|
|||||||
# CONFIG_COUNTER is not set
|
# CONFIG_COUNTER is not set
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3934,7 +3934,7 @@ CONFIG_I2C_MUX=m
|
|||||||
# CONFIG_I2C_MUX_GPIO is not set
|
# CONFIG_I2C_MUX_GPIO is not set
|
||||||
# CONFIG_I2C_MUX_LTC4306 is not set
|
# CONFIG_I2C_MUX_LTC4306 is not set
|
||||||
# CONFIG_I2C_MUX_PCA9541 is not set
|
# CONFIG_I2C_MUX_PCA9541 is not set
|
||||||
# CONFIG_I2C_MUX_PCA954x is not set
|
CONFIG_I2C_MUX_PCA954x=m
|
||||||
# CONFIG_I2C_MUX_REG is not set
|
# CONFIG_I2C_MUX_REG is not set
|
||||||
CONFIG_I2C_MUX_MLXCPLD=m
|
CONFIG_I2C_MUX_MLXCPLD=m
|
||||||
# end of Multiplexer I2C Chip support
|
# end of Multiplexer I2C Chip support
|
||||||
@ -4092,6 +4092,15 @@ CONFIG_PTP_1588_CLOCK_VMW=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
CONFIG_PINCONF=y
|
CONFIG_PINCONF=y
|
||||||
@ -7970,7 +7979,6 @@ CONFIG_COUNTER=m
|
|||||||
CONFIG_INTEL_QEP=m
|
CONFIG_INTEL_QEP=m
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3940,7 +3940,7 @@ CONFIG_I2C_MUX=m
|
|||||||
# CONFIG_I2C_MUX_GPIO is not set
|
# CONFIG_I2C_MUX_GPIO is not set
|
||||||
# CONFIG_I2C_MUX_LTC4306 is not set
|
# CONFIG_I2C_MUX_LTC4306 is not set
|
||||||
# CONFIG_I2C_MUX_PCA9541 is not set
|
# CONFIG_I2C_MUX_PCA9541 is not set
|
||||||
# CONFIG_I2C_MUX_PCA954x is not set
|
CONFIG_I2C_MUX_PCA954x=m
|
||||||
# CONFIG_I2C_MUX_REG is not set
|
# CONFIG_I2C_MUX_REG is not set
|
||||||
CONFIG_I2C_MUX_MLXCPLD=m
|
CONFIG_I2C_MUX_MLXCPLD=m
|
||||||
# end of Multiplexer I2C Chip support
|
# end of Multiplexer I2C Chip support
|
||||||
@ -4098,6 +4098,15 @@ CONFIG_PTP_1588_CLOCK_VMW=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
CONFIG_PINCONF=y
|
CONFIG_PINCONF=y
|
||||||
@ -8022,7 +8031,6 @@ CONFIG_COUNTER=m
|
|||||||
CONFIG_INTEL_QEP=m
|
CONFIG_INTEL_QEP=m
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3924,7 +3924,7 @@ CONFIG_I2C_MUX=m
|
|||||||
# CONFIG_I2C_MUX_GPIO is not set
|
# CONFIG_I2C_MUX_GPIO is not set
|
||||||
# CONFIG_I2C_MUX_LTC4306 is not set
|
# CONFIG_I2C_MUX_LTC4306 is not set
|
||||||
# CONFIG_I2C_MUX_PCA9541 is not set
|
# CONFIG_I2C_MUX_PCA9541 is not set
|
||||||
# CONFIG_I2C_MUX_PCA954x is not set
|
CONFIG_I2C_MUX_PCA954x=m
|
||||||
# CONFIG_I2C_MUX_REG is not set
|
# CONFIG_I2C_MUX_REG is not set
|
||||||
CONFIG_I2C_MUX_MLXCPLD=m
|
CONFIG_I2C_MUX_MLXCPLD=m
|
||||||
# end of Multiplexer I2C Chip support
|
# end of Multiplexer I2C Chip support
|
||||||
@ -4082,6 +4082,15 @@ CONFIG_PTP_1588_CLOCK_VMW=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
CONFIG_PINCONF=y
|
CONFIG_PINCONF=y
|
||||||
@ -7995,7 +8004,6 @@ CONFIG_COUNTER=m
|
|||||||
CONFIG_INTEL_QEP=m
|
CONFIG_INTEL_QEP=m
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -3917,7 +3917,7 @@ CONFIG_I2C_MUX=m
|
|||||||
# CONFIG_I2C_MUX_GPIO is not set
|
# CONFIG_I2C_MUX_GPIO is not set
|
||||||
# CONFIG_I2C_MUX_LTC4306 is not set
|
# CONFIG_I2C_MUX_LTC4306 is not set
|
||||||
# CONFIG_I2C_MUX_PCA9541 is not set
|
# CONFIG_I2C_MUX_PCA9541 is not set
|
||||||
# CONFIG_I2C_MUX_PCA954x is not set
|
CONFIG_I2C_MUX_PCA954x=m
|
||||||
# CONFIG_I2C_MUX_REG is not set
|
# CONFIG_I2C_MUX_REG is not set
|
||||||
CONFIG_I2C_MUX_MLXCPLD=m
|
CONFIG_I2C_MUX_MLXCPLD=m
|
||||||
# end of Multiplexer I2C Chip support
|
# end of Multiplexer I2C Chip support
|
||||||
@ -4075,6 +4075,15 @@ CONFIG_PTP_1588_CLOCK_VMW=m
|
|||||||
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
# CONFIG_PTP_1588_CLOCK_OCP is not set
|
||||||
# end of PTP clock support
|
# end of PTP clock support
|
||||||
|
|
||||||
|
#
|
||||||
|
# DPLL device support
|
||||||
|
#
|
||||||
|
CONFIG_DPLL=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
|
# end of DPLL device support
|
||||||
|
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_PINMUX=y
|
CONFIG_PINMUX=y
|
||||||
CONFIG_PINCONF=y
|
CONFIG_PINCONF=y
|
||||||
@ -7943,7 +7952,6 @@ CONFIG_COUNTER=m
|
|||||||
CONFIG_INTEL_QEP=m
|
CONFIG_INTEL_QEP=m
|
||||||
# CONFIG_MOST is not set
|
# CONFIG_MOST is not set
|
||||||
# CONFIG_HTE is not set
|
# CONFIG_HTE is not set
|
||||||
CONFIG_DPLL=y
|
|
||||||
# end of Device Drivers
|
# end of Device Drivers
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -75,6 +75,8 @@ source "drivers/pps/Kconfig"
|
|||||||
|
|
||||||
source "drivers/ptp/Kconfig"
|
source "drivers/ptp/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/dpll/Kconfig"
|
||||||
|
|
||||||
source "drivers/pinctrl/Kconfig"
|
source "drivers/pinctrl/Kconfig"
|
||||||
|
|
||||||
source "drivers/gpio/Kconfig"
|
source "drivers/gpio/Kconfig"
|
||||||
@ -245,6 +247,4 @@ source "drivers/most/Kconfig"
|
|||||||
|
|
||||||
source "drivers/hte/Kconfig"
|
source "drivers/hte/Kconfig"
|
||||||
|
|
||||||
source "drivers/dpll/Kconfig"
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|||||||
@ -3,5 +3,11 @@
|
|||||||
# Generic DPLL drivers configuration
|
# Generic DPLL drivers configuration
|
||||||
#
|
#
|
||||||
|
|
||||||
|
menu "DPLL device support"
|
||||||
|
|
||||||
config DPLL
|
config DPLL
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
source "drivers/dpll/zl3073x/Kconfig"
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|||||||
@ -7,3 +7,5 @@ obj-$(CONFIG_DPLL) += dpll.o
|
|||||||
dpll-y += dpll_core.o
|
dpll-y += dpll_core.o
|
||||||
dpll-y += dpll_netlink.o
|
dpll-y += dpll_netlink.o
|
||||||
dpll-y += dpll_nl.o
|
dpll-y += dpll_nl.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_ZL3073X) += zl3073x/
|
||||||
|
|||||||
39
drivers/dpll/zl3073x/Kconfig
Normal file
39
drivers/dpll/zl3073x/Kconfig
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
config ZL3073X
|
||||||
|
tristate "Microchip Azurite DPLL/PTP/SyncE devices" if COMPILE_TEST
|
||||||
|
depends on NET
|
||||||
|
select DPLL
|
||||||
|
select NET_DEVLINK
|
||||||
|
select REGMAP
|
||||||
|
help
|
||||||
|
This driver supports Microchip Azurite family DPLL/PTP/SyncE
|
||||||
|
devices that support up to 5 independent DPLL channels,
|
||||||
|
10 input pins and up to 20 output pins.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here. The module
|
||||||
|
will be called zl3073x.
|
||||||
|
|
||||||
|
config ZL3073X_I2C
|
||||||
|
tristate "I2C bus implementation for Microchip Azurite devices"
|
||||||
|
depends on I2C && NET
|
||||||
|
select REGMAP_I2C
|
||||||
|
select ZL3073X
|
||||||
|
help
|
||||||
|
This is I2C bus implementation for Microchip Azurite DPLL/PTP/SyncE
|
||||||
|
devices.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module will
|
||||||
|
be called zl3073x_i2c.
|
||||||
|
|
||||||
|
config ZL3073X_SPI
|
||||||
|
tristate "SPI bus implementation for Microchip Azurite devices"
|
||||||
|
depends on NET && SPI
|
||||||
|
select REGMAP_SPI
|
||||||
|
select ZL3073X
|
||||||
|
help
|
||||||
|
This is SPI bus implementation for Microchip Azurite DPLL/PTP/SyncE
|
||||||
|
devices.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the module will
|
||||||
|
be called zl3073x_spi.
|
||||||
10
drivers/dpll/zl3073x/Makefile
Normal file
10
drivers/dpll/zl3073x/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
obj-$(CONFIG_ZL3073X) += zl3073x.o
|
||||||
|
zl3073x-objs := core.o devlink.o dpll.o flash.o fw.o prop.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_ZL3073X_I2C) += zl3073x_i2c.o
|
||||||
|
zl3073x_i2c-objs := i2c.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_ZL3073X_SPI) += zl3073x_spi.o
|
||||||
|
zl3073x_spi-objs := spi.o
|
||||||
1259
drivers/dpll/zl3073x/core.c
Normal file
1259
drivers/dpll/zl3073x/core.c
Normal file
File diff suppressed because it is too large
Load Diff
416
drivers/dpll/zl3073x/core.h
Normal file
416
drivers/dpll/zl3073x/core.h
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef _ZL3073X_CORE_H
|
||||||
|
#define _ZL3073X_CORE_H
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include "regs.h"
|
||||||
|
|
||||||
|
struct device;
|
||||||
|
struct regmap;
|
||||||
|
struct zl3073x_dpll;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hardware limits for ZL3073x chip family
|
||||||
|
*/
|
||||||
|
#define ZL3073X_MAX_CHANNELS 5
|
||||||
|
#define ZL3073X_NUM_REFS 10
|
||||||
|
#define ZL3073X_NUM_OUTS 10
|
||||||
|
#define ZL3073X_NUM_SYNTHS 5
|
||||||
|
#define ZL3073X_NUM_INPUT_PINS ZL3073X_NUM_REFS
|
||||||
|
#define ZL3073X_NUM_OUTPUT_PINS (ZL3073X_NUM_OUTS * 2)
|
||||||
|
#define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \
|
||||||
|
ZL3073X_NUM_OUTPUT_PINS)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_ref - input reference invariant info
|
||||||
|
* @enabled: input reference is enabled or disabled
|
||||||
|
* @diff: true if input reference is differential
|
||||||
|
* @ffo: current fractional frequency offset
|
||||||
|
*/
|
||||||
|
struct zl3073x_ref {
|
||||||
|
bool enabled;
|
||||||
|
bool diff;
|
||||||
|
s64 ffo;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_out - output invariant info
|
||||||
|
* @enabled: out is enabled or disabled
|
||||||
|
* @synth: synthesizer the out is connected to
|
||||||
|
* @signal_format: out signal format
|
||||||
|
*/
|
||||||
|
struct zl3073x_out {
|
||||||
|
bool enabled;
|
||||||
|
u8 synth;
|
||||||
|
u8 signal_format;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_synth - synthesizer invariant info
|
||||||
|
* @freq: synthesizer frequency
|
||||||
|
* @dpll: ID of DPLL the synthesizer is driven by
|
||||||
|
* @enabled: synth is enabled or disabled
|
||||||
|
*/
|
||||||
|
struct zl3073x_synth {
|
||||||
|
u32 freq;
|
||||||
|
u8 dpll;
|
||||||
|
bool enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_dev - zl3073x device
|
||||||
|
* @dev: pointer to device
|
||||||
|
* @regmap: regmap to access device registers
|
||||||
|
* @multiop_lock: to serialize multiple register operations
|
||||||
|
* @clock_id: clock id of the device
|
||||||
|
* @ref: array of input references' invariants
|
||||||
|
* @out: array of outs' invariants
|
||||||
|
* @synth: array of synths' invariants
|
||||||
|
* @dplls: list of DPLLs
|
||||||
|
* @kworker: thread for periodic work
|
||||||
|
* @work: periodic work
|
||||||
|
*/
|
||||||
|
struct zl3073x_dev {
|
||||||
|
struct device *dev;
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct mutex multiop_lock;
|
||||||
|
u64 clock_id;
|
||||||
|
|
||||||
|
/* Invariants */
|
||||||
|
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
|
||||||
|
struct zl3073x_out out[ZL3073X_NUM_OUTS];
|
||||||
|
struct zl3073x_synth synth[ZL3073X_NUM_SYNTHS];
|
||||||
|
|
||||||
|
/* DPLL channels */
|
||||||
|
struct list_head dplls;
|
||||||
|
|
||||||
|
/* Monitor */
|
||||||
|
struct kthread_worker *kworker;
|
||||||
|
struct kthread_delayed_work work;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zl3073x_chip_info {
|
||||||
|
const u16 *ids;
|
||||||
|
size_t num_ids;
|
||||||
|
int num_channels;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct zl3073x_chip_info zl30731_chip_info;
|
||||||
|
extern const struct zl3073x_chip_info zl30732_chip_info;
|
||||||
|
extern const struct zl3073x_chip_info zl30733_chip_info;
|
||||||
|
extern const struct zl3073x_chip_info zl30734_chip_info;
|
||||||
|
extern const struct zl3073x_chip_info zl30735_chip_info;
|
||||||
|
extern const struct regmap_config zl3073x_regmap_config;
|
||||||
|
|
||||||
|
struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
|
||||||
|
int zl3073x_dev_probe(struct zl3073x_dev *zldev,
|
||||||
|
const struct zl3073x_chip_info *chip_info);
|
||||||
|
|
||||||
|
int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full);
|
||||||
|
void zl3073x_dev_stop(struct zl3073x_dev *zldev);
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* Registers operations
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_hwreg_seq_item - HW register write sequence item
|
||||||
|
* @addr: HW register to be written
|
||||||
|
* @value: value to be written to HW register
|
||||||
|
* @mask: bitmask indicating bits to be updated
|
||||||
|
* @wait: number of ms to wait after register write
|
||||||
|
*/
|
||||||
|
struct zl3073x_hwreg_seq_item {
|
||||||
|
u32 addr;
|
||||||
|
u32 value;
|
||||||
|
u32 mask;
|
||||||
|
u32 wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HWREG_SEQ_ITEM(_addr, _value, _mask, _wait) \
|
||||||
|
{ \
|
||||||
|
.addr = _addr, \
|
||||||
|
.value = FIELD_PREP_CONST(_mask, _value), \
|
||||||
|
.mask = _mask, \
|
||||||
|
.wait = _wait, \
|
||||||
|
}
|
||||||
|
|
||||||
|
int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val,
|
||||||
|
unsigned int mask_reg, u16 mask_val);
|
||||||
|
int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask);
|
||||||
|
int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val);
|
||||||
|
int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val);
|
||||||
|
int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val);
|
||||||
|
int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val);
|
||||||
|
int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val);
|
||||||
|
int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val);
|
||||||
|
int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val);
|
||||||
|
int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val);
|
||||||
|
int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value);
|
||||||
|
int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value);
|
||||||
|
int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value,
|
||||||
|
u32 mask);
|
||||||
|
int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
|
||||||
|
const struct zl3073x_hwreg_seq_item *seq,
|
||||||
|
size_t num_items);
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
* Misc operations
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult);
|
||||||
|
int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
zl3073x_is_n_pin(u8 id)
|
||||||
|
{
|
||||||
|
/* P-pins ids are even while N-pins are odd */
|
||||||
|
return id & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
zl3073x_is_p_pin(u8 id)
|
||||||
|
{
|
||||||
|
return !zl3073x_is_n_pin(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_input_pin_ref_get - get reference for given input pin
|
||||||
|
* @id: input pin id
|
||||||
|
*
|
||||||
|
* Return: reference id for the given input pin
|
||||||
|
*/
|
||||||
|
static inline u8
|
||||||
|
zl3073x_input_pin_ref_get(u8 id)
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_output_pin_out_get - get output for the given output pin
|
||||||
|
* @id: output pin id
|
||||||
|
*
|
||||||
|
* Return: output id for the given output pin
|
||||||
|
*/
|
||||||
|
static inline u8
|
||||||
|
zl3073x_output_pin_out_get(u8 id)
|
||||||
|
{
|
||||||
|
/* Output pin pair shares the single output */
|
||||||
|
return id / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_ref_ffo_get - get current fractional frequency offset
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: input reference index
|
||||||
|
*
|
||||||
|
* Return: the latest measured fractional frequency offset
|
||||||
|
*/
|
||||||
|
static inline s64
|
||||||
|
zl3073x_ref_ffo_get(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->ref[index].ffo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_ref_is_diff - check if the given input reference is differential
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: input reference index
|
||||||
|
*
|
||||||
|
* Return: true if reference is differential, false if reference is single-ended
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
zl3073x_ref_is_diff(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->ref[index].diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_ref_is_enabled - check if the given input reference is enabled
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: input reference index
|
||||||
|
*
|
||||||
|
* Return: true if input refernce is enabled, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
zl3073x_ref_is_enabled(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->ref[index].enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_synth_dpll_get - get DPLL ID the synth is driven by
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: synth index
|
||||||
|
*
|
||||||
|
* Return: ID of DPLL the given synthetizer is driven by
|
||||||
|
*/
|
||||||
|
static inline u8
|
||||||
|
zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->synth[index].dpll;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_synth_freq_get - get synth current freq
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: synth index
|
||||||
|
*
|
||||||
|
* Return: frequency of given synthetizer
|
||||||
|
*/
|
||||||
|
static inline u32
|
||||||
|
zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->synth[index].freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_synth_is_enabled - check if the given synth is enabled
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: synth index
|
||||||
|
*
|
||||||
|
* Return: true if synth is enabled, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
zl3073x_synth_is_enabled(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->synth[index].enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_out_synth_get - get synth connected to given output
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: output index
|
||||||
|
*
|
||||||
|
* Return: index of synth connected to given output.
|
||||||
|
*/
|
||||||
|
static inline u8
|
||||||
|
zl3073x_out_synth_get(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->out[index].synth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_out_is_enabled - check if the given output is enabled
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: output index
|
||||||
|
*
|
||||||
|
* Return: true if the output is enabled, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
zl3073x_out_is_enabled(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
u8 synth;
|
||||||
|
|
||||||
|
/* Output is enabled only if associated synth is enabled */
|
||||||
|
synth = zl3073x_out_synth_get(zldev, index);
|
||||||
|
if (zl3073x_synth_is_enabled(zldev, synth))
|
||||||
|
return zldev->out[index].enabled;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_out_signal_format_get - get output signal format
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: output index
|
||||||
|
*
|
||||||
|
* Return: signal format of given output
|
||||||
|
*/
|
||||||
|
static inline u8
|
||||||
|
zl3073x_out_signal_format_get(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
return zldev->out[index].signal_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_out_dpll_get - get DPLL ID the output is driven by
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: output index
|
||||||
|
*
|
||||||
|
* Return: ID of DPLL the given output is driven by
|
||||||
|
*/
|
||||||
|
static inline
|
||||||
|
u8 zl3073x_out_dpll_get(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
u8 synth;
|
||||||
|
|
||||||
|
/* Get synthesizer connected to given output */
|
||||||
|
synth = zl3073x_out_synth_get(zldev, index);
|
||||||
|
|
||||||
|
/* Return DPLL that drives the synth */
|
||||||
|
return zl3073x_synth_dpll_get(zldev, synth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_out_is_diff - check if the given output is differential
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: output index
|
||||||
|
*
|
||||||
|
* Return: true if output is differential, false if output is single-ended
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
zl3073x_out_is_diff(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
switch (zl3073x_out_signal_format_get(zldev, index)) {
|
||||||
|
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS:
|
||||||
|
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DIFF:
|
||||||
|
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LOWVCM:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_output_pin_is_enabled - check if the given output pin is enabled
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @id: output pin id
|
||||||
|
*
|
||||||
|
* Checks if the output of the given output pin is enabled and also that
|
||||||
|
* its signal format also enables the given pin.
|
||||||
|
*
|
||||||
|
* Return: true if output pin is enabled, false if output pin is disabled
|
||||||
|
*/
|
||||||
|
static inline bool
|
||||||
|
zl3073x_output_pin_is_enabled(struct zl3073x_dev *zldev, u8 id)
|
||||||
|
{
|
||||||
|
u8 output = zl3073x_output_pin_out_get(id);
|
||||||
|
|
||||||
|
/* Check if the whole output is enabled */
|
||||||
|
if (!zl3073x_out_is_enabled(zldev, output))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Check signal format */
|
||||||
|
switch (zl3073x_out_signal_format_get(zldev, output)) {
|
||||||
|
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED:
|
||||||
|
/* Both output pins are disabled by signal format */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P:
|
||||||
|
/* Output is one single ended P-pin output */
|
||||||
|
if (zl3073x_is_n_pin(id))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N:
|
||||||
|
/* Output is one single ended N-pin output */
|
||||||
|
if (zl3073x_is_p_pin(id))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* For other format both pins are enabled */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _ZL3073X_CORE_H */
|
||||||
390
drivers/dpll/zl3073x/devlink.c
Normal file
390
drivers/dpll/zl3073x/devlink.c
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/sprintf.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <net/devlink.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "devlink.h"
|
||||||
|
#include "dpll.h"
|
||||||
|
#include "flash.h"
|
||||||
|
#include "fw.h"
|
||||||
|
#include "regs.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_devlink_info_get - Devlink device info callback
|
||||||
|
* @devlink: devlink structure pointer
|
||||||
|
* @req: devlink request pointer to store information
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct zl3073x_dev *zldev = devlink_priv(devlink);
|
||||||
|
u16 id, revision, fw_ver;
|
||||||
|
char buf[16];
|
||||||
|
u32 cfg_ver;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%X", id);
|
||||||
|
rc = devlink_info_version_fixed_put(req,
|
||||||
|
DEVLINK_INFO_VERSION_GENERIC_ASIC_ID,
|
||||||
|
buf);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%X", revision);
|
||||||
|
rc = devlink_info_version_fixed_put(req,
|
||||||
|
DEVLINK_INFO_VERSION_GENERIC_ASIC_REV,
|
||||||
|
buf);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%u", fw_ver);
|
||||||
|
rc = devlink_info_version_running_put(req,
|
||||||
|
DEVLINK_INFO_VERSION_GENERIC_FW,
|
||||||
|
buf);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* No custom config version */
|
||||||
|
if (cfg_ver == U32_MAX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%lu.%lu.%lu.%lu",
|
||||||
|
FIELD_GET(GENMASK(31, 24), cfg_ver),
|
||||||
|
FIELD_GET(GENMASK(23, 16), cfg_ver),
|
||||||
|
FIELD_GET(GENMASK(15, 8), cfg_ver),
|
||||||
|
FIELD_GET(GENMASK(7, 0), cfg_ver));
|
||||||
|
|
||||||
|
return devlink_info_version_running_put(req, "custom_cfg", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zl3073x_devlink_reload_down(struct devlink *devlink, bool netns_change,
|
||||||
|
enum devlink_reload_action action,
|
||||||
|
enum devlink_reload_limit limit,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct zl3073x_dev *zldev = devlink_priv(devlink);
|
||||||
|
|
||||||
|
if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Stop normal operation */
|
||||||
|
zl3073x_dev_stop(zldev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zl3073x_devlink_reload_up(struct devlink *devlink,
|
||||||
|
enum devlink_reload_action action,
|
||||||
|
enum devlink_reload_limit limit,
|
||||||
|
u32 *actions_performed,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct zl3073x_dev *zldev = devlink_priv(devlink);
|
||||||
|
union devlink_param_value val;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
rc = devl_param_driverinit_value_get(devlink,
|
||||||
|
DEVLINK_PARAM_GENERIC_ID_CLOCK_ID,
|
||||||
|
&val);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (zldev->clock_id != val.vu64) {
|
||||||
|
dev_dbg(zldev->dev,
|
||||||
|
"'clock_id' changed to %016llx\n", val.vu64);
|
||||||
|
zldev->clock_id = val.vu64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart normal operation */
|
||||||
|
rc = zl3073x_dev_start(zldev, false);
|
||||||
|
if (rc)
|
||||||
|
dev_warn(zldev->dev, "Failed to re-start normal operation\n");
|
||||||
|
|
||||||
|
*actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zl3073x_devlink_flash_notify(struct zl3073x_dev *zldev, const char *msg,
|
||||||
|
const char *component, u32 done, u32 total)
|
||||||
|
{
|
||||||
|
struct devlink *devlink = priv_to_devlink(zldev);
|
||||||
|
|
||||||
|
devlink_flash_update_status_notify(devlink, msg, component, done,
|
||||||
|
total);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_devlink_flash_prepare - Prepare and enter flash mode
|
||||||
|
* @zldev: zl3073x device pointer
|
||||||
|
* @zlfw: pointer to loaded firmware
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function stops normal operation and switches the device to flash mode.
|
||||||
|
* If an error occurs the normal operation is resumed.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_devlink_flash_prepare(struct zl3073x_dev *zldev,
|
||||||
|
struct zl3073x_fw *zlfw,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct zl3073x_fw_component *util;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
util = zlfw->component[ZL_FW_COMPONENT_UTIL];
|
||||||
|
if (!util) {
|
||||||
|
zl3073x_devlink_flash_notify(zldev,
|
||||||
|
"Utility is missing in firmware",
|
||||||
|
NULL, 0, 0);
|
||||||
|
return -ENOEXEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop normal operation prior entering flash mode */
|
||||||
|
zl3073x_dev_stop(zldev);
|
||||||
|
|
||||||
|
rc = zl3073x_flash_mode_enter(zldev, util->data, util->size, extack);
|
||||||
|
if (rc) {
|
||||||
|
zl3073x_devlink_flash_notify(zldev,
|
||||||
|
"Failed to enter flash mode",
|
||||||
|
NULL, 0, 0);
|
||||||
|
|
||||||
|
/* Resume normal operation */
|
||||||
|
zl3073x_dev_start(zldev, true);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_devlink_flash_finish - Leave flash mode and resume normal operation
|
||||||
|
* @zldev: zl3073x device pointer
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function switches the device back to standard mode and resumes normal
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_devlink_flash_finish(struct zl3073x_dev *zldev,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Reset device CPU to normal mode */
|
||||||
|
zl3073x_flash_mode_leave(zldev, extack);
|
||||||
|
|
||||||
|
/* Resume normal operation */
|
||||||
|
rc = zl3073x_dev_start(zldev, true);
|
||||||
|
if (rc)
|
||||||
|
zl3073x_devlink_flash_notify(zldev,
|
||||||
|
"Failed to start normal operation",
|
||||||
|
NULL, 0, 0);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_devlink_flash_update - Devlink flash update callback
|
||||||
|
* @devlink: devlink structure pointer
|
||||||
|
* @params: flashing parameters pointer
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_devlink_flash_update(struct devlink *devlink,
|
||||||
|
struct devlink_flash_update_params *params,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct zl3073x_dev *zldev = devlink_priv(devlink);
|
||||||
|
struct zl3073x_fw *zlfw;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
zlfw = zl3073x_fw_load(zldev, params->fw->data, params->fw->size,
|
||||||
|
extack);
|
||||||
|
if (IS_ERR(zlfw)) {
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Failed to load firmware",
|
||||||
|
NULL, 0, 0);
|
||||||
|
rc = PTR_ERR(zlfw);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop normal operation and enter flash mode */
|
||||||
|
rc = zl3073x_devlink_flash_prepare(zldev, zlfw, extack);
|
||||||
|
if (rc)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
rc = zl3073x_fw_flash(zldev, zlfw, extack);
|
||||||
|
if (rc) {
|
||||||
|
zl3073x_devlink_flash_finish(zldev, extack);
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resume normal mode */
|
||||||
|
rc = zl3073x_devlink_flash_finish(zldev, extack);
|
||||||
|
|
||||||
|
finish:
|
||||||
|
if (!IS_ERR(zlfw))
|
||||||
|
zl3073x_fw_free(zlfw);
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev,
|
||||||
|
rc ? "Flashing failed" : "Flashing done",
|
||||||
|
NULL, 0, 0);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct devlink_ops zl3073x_devlink_ops = {
|
||||||
|
.info_get = zl3073x_devlink_info_get,
|
||||||
|
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
|
||||||
|
.reload_down = zl3073x_devlink_reload_down,
|
||||||
|
.reload_up = zl3073x_devlink_reload_up,
|
||||||
|
.flash_update = zl3073x_devlink_flash_update,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
zl3073x_devlink_free(void *ptr)
|
||||||
|
{
|
||||||
|
devlink_free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_devm_alloc - allocates zl3073x device structure
|
||||||
|
* @dev: pointer to device structure
|
||||||
|
*
|
||||||
|
* Allocates zl3073x device structure as device resource.
|
||||||
|
*
|
||||||
|
* Return: pointer to zl3073x device on success, error pointer on error
|
||||||
|
*/
|
||||||
|
struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev)
|
||||||
|
{
|
||||||
|
struct zl3073x_dev *zldev;
|
||||||
|
struct devlink *devlink;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
devlink = devlink_alloc(&zl3073x_devlink_ops, sizeof(*zldev), dev);
|
||||||
|
if (!devlink)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
/* Add devres action to free devlink device */
|
||||||
|
rc = devm_add_action_or_reset(dev, zl3073x_devlink_free, devlink);
|
||||||
|
if (rc)
|
||||||
|
return ERR_PTR(rc);
|
||||||
|
|
||||||
|
zldev = devlink_priv(devlink);
|
||||||
|
zldev->dev = dev;
|
||||||
|
dev_set_drvdata(zldev->dev, zldev);
|
||||||
|
|
||||||
|
return zldev;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_NS_GPL(zl3073x_devm_alloc, ZL3073X);
|
||||||
|
|
||||||
|
static int
|
||||||
|
zl3073x_devlink_param_clock_id_validate(struct devlink *devlink, u32 id,
|
||||||
|
union devlink_param_value val,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
if (!val.vu64) {
|
||||||
|
NL_SET_ERR_MSG_MOD(extack, "'clock_id' must be non-zero");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct devlink_param zl3073x_devlink_params[] = {
|
||||||
|
DEVLINK_PARAM_GENERIC(CLOCK_ID, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
|
||||||
|
NULL, NULL,
|
||||||
|
zl3073x_devlink_param_clock_id_validate),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
zl3073x_devlink_unregister(void *ptr)
|
||||||
|
{
|
||||||
|
struct devlink *devlink = priv_to_devlink(ptr);
|
||||||
|
|
||||||
|
devl_lock(devlink);
|
||||||
|
|
||||||
|
/* Unregister devlink params */
|
||||||
|
devl_params_unregister(devlink, zl3073x_devlink_params,
|
||||||
|
ARRAY_SIZE(zl3073x_devlink_params));
|
||||||
|
|
||||||
|
/* Unregister devlink instance */
|
||||||
|
devl_unregister(devlink);
|
||||||
|
|
||||||
|
devl_unlock(devlink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_devlink_register - register devlink instance and params
|
||||||
|
* @zldev: zl3073x device to register the devlink for
|
||||||
|
*
|
||||||
|
* Register the devlink instance and parameters associated with the device.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
int zl3073x_devlink_register(struct zl3073x_dev *zldev)
|
||||||
|
{
|
||||||
|
struct devlink *devlink = priv_to_devlink(zldev);
|
||||||
|
union devlink_param_value value;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
devl_lock(devlink);
|
||||||
|
|
||||||
|
/* Register devlink params */
|
||||||
|
rc = devl_params_register(devlink, zl3073x_devlink_params,
|
||||||
|
ARRAY_SIZE(zl3073x_devlink_params));
|
||||||
|
if (rc) {
|
||||||
|
devl_unlock(devlink);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.vu64 = zldev->clock_id;
|
||||||
|
devl_param_driverinit_value_set(devlink,
|
||||||
|
DEVLINK_PARAM_GENERIC_ID_CLOCK_ID,
|
||||||
|
value);
|
||||||
|
|
||||||
|
/* Register devlink instance */
|
||||||
|
devl_register(devlink);
|
||||||
|
|
||||||
|
devl_unlock(devlink);
|
||||||
|
|
||||||
|
/* Add devres action to unregister devlink device */
|
||||||
|
return devm_add_action_or_reset(zldev->dev, zl3073x_devlink_unregister,
|
||||||
|
zldev);
|
||||||
|
}
|
||||||
15
drivers/dpll/zl3073x/devlink.h
Normal file
15
drivers/dpll/zl3073x/devlink.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef _ZL3073X_DEVLINK_H
|
||||||
|
#define _ZL3073X_DEVLINK_H
|
||||||
|
|
||||||
|
struct zl3073x_dev;
|
||||||
|
|
||||||
|
struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
|
||||||
|
|
||||||
|
int zl3073x_devlink_register(struct zl3073x_dev *zldev);
|
||||||
|
|
||||||
|
void zl3073x_devlink_flash_notify(struct zl3073x_dev *zldev, const char *msg,
|
||||||
|
const char *component, u32 done, u32 total);
|
||||||
|
|
||||||
|
#endif /* _ZL3073X_DEVLINK_H */
|
||||||
2318
drivers/dpll/zl3073x/dpll.c
Normal file
2318
drivers/dpll/zl3073x/dpll.c
Normal file
File diff suppressed because it is too large
Load Diff
46
drivers/dpll/zl3073x/dpll.h
Normal file
46
drivers/dpll/zl3073x/dpll.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef _ZL3073X_DPLL_H
|
||||||
|
#define _ZL3073X_DPLL_H
|
||||||
|
|
||||||
|
#include <linux/dpll.h>
|
||||||
|
#include <linux/list.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_dpll - ZL3073x DPLL sub-device structure
|
||||||
|
* @list: this DPLL list entry
|
||||||
|
* @dev: pointer to multi-function parent device
|
||||||
|
* @id: DPLL index
|
||||||
|
* @refsel_mode: reference selection mode
|
||||||
|
* @forced_ref: selected reference in forced reference lock mode
|
||||||
|
* @check_count: periodic check counter
|
||||||
|
* @phase_monitor: is phase offset monitor enabled
|
||||||
|
* @dpll_dev: pointer to registered DPLL device
|
||||||
|
* @lock_status: last saved DPLL lock status
|
||||||
|
* @pins: list of pins
|
||||||
|
*/
|
||||||
|
struct zl3073x_dpll {
|
||||||
|
struct list_head list;
|
||||||
|
struct zl3073x_dev *dev;
|
||||||
|
u8 id;
|
||||||
|
u8 refsel_mode;
|
||||||
|
u8 forced_ref;
|
||||||
|
u8 check_count;
|
||||||
|
bool phase_monitor;
|
||||||
|
struct dpll_device *dpll_dev;
|
||||||
|
enum dpll_lock_status lock_status;
|
||||||
|
struct list_head pins;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zl3073x_dpll *zl3073x_dpll_alloc(struct zl3073x_dev *zldev, u8 ch);
|
||||||
|
void zl3073x_dpll_free(struct zl3073x_dpll *zldpll);
|
||||||
|
|
||||||
|
int zl3073x_dpll_register(struct zl3073x_dpll *zldpll);
|
||||||
|
void zl3073x_dpll_unregister(struct zl3073x_dpll *zldpll);
|
||||||
|
|
||||||
|
int zl3073x_dpll_init_fine_phase_adjust(struct zl3073x_dev *zldev);
|
||||||
|
void zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll);
|
||||||
|
|
||||||
|
#endif /* _ZL3073X_DPLL_H */
|
||||||
666
drivers/dpll/zl3073x/flash.c
Normal file
666
drivers/dpll/zl3073x/flash.c
Normal file
@ -0,0 +1,666 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <linux/array_size.h>
|
||||||
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/bits.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/dev_printk.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/minmax.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/sched/signal.h>
|
||||||
|
#include <linux/sizes.h>
|
||||||
|
#include <linux/sprintf.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/unaligned.h>
|
||||||
|
#include <net/devlink.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "devlink.h"
|
||||||
|
#include "flash.h"
|
||||||
|
|
||||||
|
#define ZL_FLASH_ERR_PFX "FW update failed: "
|
||||||
|
#define ZL_FLASH_ERR_MSG(_extack, _msg, ...) \
|
||||||
|
NL_SET_ERR_MSG_FMT_MOD((_extack), ZL_FLASH_ERR_PFX _msg, \
|
||||||
|
## __VA_ARGS__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_download - Download image block to device memory
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @component: name of the component to be downloaded
|
||||||
|
* @addr: device memory target address
|
||||||
|
* @data: pointer to data to download
|
||||||
|
* @size: size of data to download
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_flash_download(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 addr, const void *data, size_t size,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
#define ZL_CHECK_DELAY 5000 /* Check for interrupt each 5 seconds */
|
||||||
|
unsigned long check_time;
|
||||||
|
const void *ptr, *end;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
dev_dbg(zldev->dev, "Downloading %zu bytes to device memory at 0x%0x\n",
|
||||||
|
size, addr);
|
||||||
|
|
||||||
|
check_time = jiffies + msecs_to_jiffies(ZL_CHECK_DELAY);
|
||||||
|
|
||||||
|
for (ptr = data, end = data + size; ptr < end; ptr += 4, addr += 4) {
|
||||||
|
/* Write current word to HW memory */
|
||||||
|
rc = zl3073x_write_hwreg(zldev, addr,
|
||||||
|
get_unaligned((u32 *)ptr));
|
||||||
|
if (rc) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack,
|
||||||
|
"failed to write to memory at 0x%0x",
|
||||||
|
addr);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time_is_before_jiffies(check_time)) {
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack,
|
||||||
|
"Flashing interrupted");
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_time = jiffies + msecs_to_jiffies(ZL_CHECK_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report status each 1 kB block */
|
||||||
|
if ((ptr - data) % 1024 == 0)
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Downloading image",
|
||||||
|
component, ptr - data,
|
||||||
|
size);
|
||||||
|
}
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Downloading image", component,
|
||||||
|
ptr - data, size);
|
||||||
|
|
||||||
|
dev_dbg(zldev->dev, "%zu bytes downloaded to device memory\n", size);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_error_check - Check for flash utility errors
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function checks for errors detected by the flash utility and
|
||||||
|
* reports them if any were found.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -EIO when errors are detected
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_flash_error_check(struct zl3073x_dev *zldev,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
u32 count, cause;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u32(zldev, ZL_REG_ERROR_COUNT, &count);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
else if (!count)
|
||||||
|
return 0; /* No error */
|
||||||
|
|
||||||
|
rc = zl3073x_read_u32(zldev, ZL_REG_ERROR_CAUSE, &cause);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Report errors */
|
||||||
|
ZL_FLASH_ERR_MSG(extack,
|
||||||
|
"utility error occurred: count=%u cause=0x%x", count,
|
||||||
|
cause);
|
||||||
|
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_wait_ready - Check or wait for utility to be ready to flash
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @timeout_ms: timeout for the waiting
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_flash_wait_ready(struct zl3073x_dev *zldev, unsigned int timeout_ms)
|
||||||
|
{
|
||||||
|
#define ZL_FLASH_POLL_DELAY_MS 100
|
||||||
|
unsigned long timeout;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
dev_dbg(zldev->dev, "Waiting for flashing to be ready\n");
|
||||||
|
|
||||||
|
timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
||||||
|
|
||||||
|
for (i = 0; time_is_after_jiffies(timeout); i++) {
|
||||||
|
u8 value;
|
||||||
|
|
||||||
|
/* Check for interrupt each 1s */
|
||||||
|
if (i > 9) {
|
||||||
|
if (signal_pending(current))
|
||||||
|
return -EINTR;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_WRITE_FLASH, &value);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
value = FIELD_GET(ZL_WRITE_FLASH_OP, value);
|
||||||
|
|
||||||
|
if (value == ZL_WRITE_FLASH_OP_DONE)
|
||||||
|
return 0; /* Successfully done */
|
||||||
|
|
||||||
|
msleep(ZL_FLASH_POLL_DELAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_cmd_wait - Perform flash operation and wait for finish
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @operation: operation to perform
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_flash_cmd_wait(struct zl3073x_dev *zldev, u32 operation,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
#define ZL_FLASH_PHASE1_TIMEOUT_MS 60000 /* up to 1 minute */
|
||||||
|
#define ZL_FLASH_PHASE2_TIMEOUT_MS 120000 /* up to 2 minutes */
|
||||||
|
u8 value;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
dev_dbg(zldev->dev, "Sending flash command: 0x%x\n", operation);
|
||||||
|
|
||||||
|
rc = zl3073x_flash_wait_ready(zldev, ZL_FLASH_PHASE1_TIMEOUT_MS);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Issue the requested operation */
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_WRITE_FLASH, &value);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
value &= ~ZL_WRITE_FLASH_OP;
|
||||||
|
value |= FIELD_PREP(ZL_WRITE_FLASH_OP, operation);
|
||||||
|
|
||||||
|
rc = zl3073x_write_u8(zldev, ZL_REG_WRITE_FLASH, value);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Wait for command completion */
|
||||||
|
rc = zl3073x_flash_wait_ready(zldev, ZL_FLASH_PHASE2_TIMEOUT_MS);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return zl3073x_flash_error_check(zldev, extack);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_get_sector_size - Get flash sector size
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @sector_size: sector size returned by the function
|
||||||
|
*
|
||||||
|
* The function reads the flash sector size detected by flash utility and
|
||||||
|
* stores it into @sector_size.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_flash_get_sector_size(struct zl3073x_dev *zldev, size_t *sector_size)
|
||||||
|
{
|
||||||
|
u8 flash_info;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_INFO, &flash_info);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
switch (FIELD_GET(ZL_FLASH_INFO_SECTOR_SIZE, flash_info)) {
|
||||||
|
case ZL_FLASH_INFO_SECTOR_4K:
|
||||||
|
*sector_size = SZ_4K;
|
||||||
|
break;
|
||||||
|
case ZL_FLASH_INFO_SECTOR_64K:
|
||||||
|
*sector_size = SZ_64K;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_block - Download and flash memory block
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @component: component name
|
||||||
|
* @operation: flash operation to perform
|
||||||
|
* @page: destination flash page
|
||||||
|
* @addr: device memory address to load data
|
||||||
|
* @data: pointer to data to be flashed
|
||||||
|
* @size: size of data
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function downloads the memory block given by the @data pointer and
|
||||||
|
* the size @size and flashes it into internal memory on flash page @page.
|
||||||
|
* The internal flash operation performed by the firmware is specified by
|
||||||
|
* the @operation parameter.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_flash_block(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 operation, u32 page, u32 addr, const void *data,
|
||||||
|
size_t size, struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Download block to device memory */
|
||||||
|
rc = zl3073x_flash_download(zldev, component, addr, data, size, extack);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Set address to flash from */
|
||||||
|
rc = zl3073x_write_u32(zldev, ZL_REG_IMAGE_START_ADDR, addr);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Set size of block to flash */
|
||||||
|
rc = zl3073x_write_u32(zldev, ZL_REG_IMAGE_SIZE, size);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Set destination page to flash */
|
||||||
|
rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_WRITE, page);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Set filling pattern */
|
||||||
|
rc = zl3073x_write_u32(zldev, ZL_REG_FILL_PATTERN, U32_MAX);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Flashing image", component, 0,
|
||||||
|
size);
|
||||||
|
|
||||||
|
dev_dbg(zldev->dev, "Flashing %zu bytes to page %u\n", size, page);
|
||||||
|
|
||||||
|
/* Execute sectors flash operation */
|
||||||
|
rc = zl3073x_flash_cmd_wait(zldev, operation, extack);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Flashing image", component, size,
|
||||||
|
size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_sectors - Flash sectors
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @component: component name
|
||||||
|
* @page: destination flash page
|
||||||
|
* @addr: device memory address to load data
|
||||||
|
* @data: pointer to data to be flashed
|
||||||
|
* @size: size of data
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function flashes given @data with size of @size to the internal flash
|
||||||
|
* memory block starting from page @page. The function uses sector flash
|
||||||
|
* method and has to take into account the flash sector size reported by
|
||||||
|
* flashing utility. Input data are spliced into blocks according this
|
||||||
|
* sector size and each block is flashed separately.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
int zl3073x_flash_sectors(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 page, u32 addr, const void *data, size_t size,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
#define ZL_FLASH_MAX_BLOCK_SIZE 0x0001E000
|
||||||
|
#define ZL_FLASH_PAGE_SIZE 256
|
||||||
|
size_t max_block_size, block_size, sector_size;
|
||||||
|
const void *ptr, *end;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Get flash sector size */
|
||||||
|
rc = zl3073x_flash_get_sector_size(zldev, §or_size);
|
||||||
|
if (rc) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack, "Failed to get flash sector size");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine max block size depending on sector size */
|
||||||
|
max_block_size = ALIGN_DOWN(ZL_FLASH_MAX_BLOCK_SIZE, sector_size);
|
||||||
|
|
||||||
|
for (ptr = data, end = data + size; ptr < end; ptr += block_size) {
|
||||||
|
char comp_str[32];
|
||||||
|
|
||||||
|
block_size = min_t(size_t, max_block_size, end - ptr);
|
||||||
|
|
||||||
|
/* Add suffix '-partN' if the requested component size is
|
||||||
|
* greater than max_block_size.
|
||||||
|
*/
|
||||||
|
if (max_block_size < size)
|
||||||
|
snprintf(comp_str, sizeof(comp_str), "%s-part%zu",
|
||||||
|
component, (ptr - data) / max_block_size + 1);
|
||||||
|
else
|
||||||
|
strscpy(comp_str, component);
|
||||||
|
|
||||||
|
/* Flash the memory block */
|
||||||
|
rc = zl3073x_flash_block(zldev, comp_str,
|
||||||
|
ZL_WRITE_FLASH_OP_SECTORS, page, addr,
|
||||||
|
ptr, block_size, extack);
|
||||||
|
if (rc)
|
||||||
|
goto finish;
|
||||||
|
|
||||||
|
/* Move to next page */
|
||||||
|
page += block_size / ZL_FLASH_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
finish:
|
||||||
|
zl3073x_devlink_flash_notify(zldev,
|
||||||
|
rc ? "Flashing failed" : "Flashing done",
|
||||||
|
component, 0, 0);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_page - Flash page
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @component: component name
|
||||||
|
* @page: destination flash page
|
||||||
|
* @addr: device memory address to load data
|
||||||
|
* @data: pointer to data to be flashed
|
||||||
|
* @size: size of data
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function flashes given @data with size of @size to the internal flash
|
||||||
|
* memory block starting with page @page.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
int zl3073x_flash_page(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 page, u32 addr, const void *data, size_t size,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Flash the memory block */
|
||||||
|
rc = zl3073x_flash_block(zldev, component, ZL_WRITE_FLASH_OP_PAGE, page,
|
||||||
|
addr, data, size, extack);
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev,
|
||||||
|
rc ? "Flashing failed" : "Flashing done",
|
||||||
|
component, 0, 0);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_page_copy - Copy flash page
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @component: component name
|
||||||
|
* @src_page: source page to copy
|
||||||
|
* @dst_page: destination page
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function copies one flash page specified by @src_page into the flash
|
||||||
|
* page specified by @dst_page.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
int zl3073x_flash_page_copy(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 src_page, u32 dst_page,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Set source page to be copied */
|
||||||
|
rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_READ, src_page);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Set destination page for the copy */
|
||||||
|
rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_WRITE, dst_page);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Perform copy operation */
|
||||||
|
rc = zl3073x_flash_cmd_wait(zldev, ZL_WRITE_FLASH_OP_COPY_PAGE, extack);
|
||||||
|
if (rc)
|
||||||
|
ZL_FLASH_ERR_MSG(extack, "Failed to copy page %u to page %u",
|
||||||
|
src_page, dst_page);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_mode_verify - Check flash utility
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
*
|
||||||
|
* Return: 0 if the flash utility is ready, <0 on error
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_flash_mode_verify(struct zl3073x_dev *zldev)
|
||||||
|
{
|
||||||
|
u8 family, release;
|
||||||
|
u32 hash;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u32(zldev, ZL_REG_FLASH_HASH, &hash);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_FAMILY, &family);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_RELEASE, &release);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
dev_dbg(zldev->dev,
|
||||||
|
"Flash utility check: hash 0x%08x, fam 0x%02x, rel 0x%02x\n",
|
||||||
|
hash, family, release);
|
||||||
|
|
||||||
|
/* Return success for correct family */
|
||||||
|
return (family == 0x21) ? 0 : -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zl3073x_flash_host_ctrl_enable(struct zl3073x_dev *zldev)
|
||||||
|
{
|
||||||
|
u8 host_ctrl;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Enable host control */
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_HOST_CONTROL, &host_ctrl);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
host_ctrl |= ZL_HOST_CONTROL_ENABLE;
|
||||||
|
|
||||||
|
return zl3073x_write_u8(zldev, ZL_REG_HOST_CONTROL, host_ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_mode_enter - Switch the device to flash mode
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @util_ptr: buffer with flash utility
|
||||||
|
* @util_size: size of buffer with flash utility
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function prepares and switches the device into flash mode.
|
||||||
|
*
|
||||||
|
* The procedure:
|
||||||
|
* 1) Stop device CPU by specific HW register sequence
|
||||||
|
* 2) Download flash utility to device memory
|
||||||
|
* 3) Resume device CPU by specific HW register sequence
|
||||||
|
* 4) Check communication with flash utility
|
||||||
|
* 5) Enable host control necessary to access flash API
|
||||||
|
* 6) Check for potential error detected by the utility
|
||||||
|
*
|
||||||
|
* The API provided by normal firmware is not available in flash mode
|
||||||
|
* so the caller has to ensure that this API is not used in this mode.
|
||||||
|
*
|
||||||
|
* After performing flash operation the caller should call
|
||||||
|
* @zl3073x_flash_mode_leave to return back to normal operation.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error.
|
||||||
|
*/
|
||||||
|
int zl3073x_flash_mode_enter(struct zl3073x_dev *zldev, const void *util_ptr,
|
||||||
|
size_t util_size, struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
/* Sequence to be written prior utility download */
|
||||||
|
static const struct zl3073x_hwreg_seq_item pre_seq[] = {
|
||||||
|
HWREG_SEQ_ITEM(0x80000400, 1, BIT(0), 0),
|
||||||
|
HWREG_SEQ_ITEM(0x80206340, 1, BIT(4), 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10000000, 1, BIT(2), 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10000024, 0x00000001, U32_MAX, 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10000020, 0x00000001, U32_MAX, 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10000000, 1, BIT(10), 1000),
|
||||||
|
};
|
||||||
|
/* Sequence to be written after utility download */
|
||||||
|
static const struct zl3073x_hwreg_seq_item post_seq[] = {
|
||||||
|
HWREG_SEQ_ITEM(0x10400004, 0x000000C0, U32_MAX, 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10400008, 0x00000000, U32_MAX, 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10400010, 0x20000000, U32_MAX, 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10400014, 0x20000004, U32_MAX, 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10000000, 1, GENMASK(10, 9), 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10000020, 0x00000000, U32_MAX, 0),
|
||||||
|
HWREG_SEQ_ITEM(0x10000000, 0, BIT(0), 1000),
|
||||||
|
};
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Prepare flash mode", "utility",
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
/* Execure pre-load sequence */
|
||||||
|
rc = zl3073x_write_hwreg_seq(zldev, pre_seq, ARRAY_SIZE(pre_seq));
|
||||||
|
if (rc) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack, "cannot execute pre-load sequence");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Download utility image to device memory */
|
||||||
|
rc = zl3073x_flash_download(zldev, "utility", 0x20000000, util_ptr,
|
||||||
|
util_size, extack);
|
||||||
|
if (rc) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack, "cannot download flash utility");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute post-load sequence */
|
||||||
|
rc = zl3073x_write_hwreg_seq(zldev, post_seq, ARRAY_SIZE(post_seq));
|
||||||
|
if (rc) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack, "cannot execute post-load sequence");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that utility identifies itself correctly */
|
||||||
|
rc = zl3073x_flash_mode_verify(zldev);
|
||||||
|
if (rc) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack, "flash utility check failed");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable host control */
|
||||||
|
rc = zl3073x_flash_host_ctrl_enable(zldev);
|
||||||
|
if (rc) {
|
||||||
|
ZL_FLASH_ERR_MSG(extack, "cannot enable host control");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Flash mode enabled", "utility",
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
zl3073x_flash_mode_leave(zldev, extack);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_flash_mode_leave - Leave flash mode
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function instructs the device to leave the flash mode and
|
||||||
|
* to return back to normal operation.
|
||||||
|
*
|
||||||
|
* The procedure:
|
||||||
|
* 1) Set reset flag
|
||||||
|
* 2) Reset the device CPU by specific HW register sequence
|
||||||
|
* 3) Wait for the device to be ready
|
||||||
|
* 4) Check the reset flag was cleared
|
||||||
|
*
|
||||||
|
* Return: 0 on success, <0 on error
|
||||||
|
*/
|
||||||
|
int zl3073x_flash_mode_leave(struct zl3073x_dev *zldev,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
/* Sequence to be written after flash */
|
||||||
|
static const struct zl3073x_hwreg_seq_item fw_reset_seq[] = {
|
||||||
|
HWREG_SEQ_ITEM(0x80000404, 1, BIT(0), 0),
|
||||||
|
HWREG_SEQ_ITEM(0x80000410, 1, BIT(0), 0),
|
||||||
|
};
|
||||||
|
u8 reset_status;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
zl3073x_devlink_flash_notify(zldev, "Leaving flash mode", "utility",
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
/* Read reset status register */
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_RESET_STATUS, &reset_status);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Set reset bit */
|
||||||
|
reset_status |= ZL_REG_RESET_STATUS_RESET;
|
||||||
|
|
||||||
|
/* Update reset status register */
|
||||||
|
rc = zl3073x_write_u8(zldev, ZL_REG_RESET_STATUS, reset_status);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* We do not check the return value here as the sequence resets
|
||||||
|
* the device CPU and the last write always return an error.
|
||||||
|
*/
|
||||||
|
zl3073x_write_hwreg_seq(zldev, fw_reset_seq, ARRAY_SIZE(fw_reset_seq));
|
||||||
|
|
||||||
|
/* Wait for the device to be ready */
|
||||||
|
msleep(500);
|
||||||
|
|
||||||
|
/* Read again the reset status register */
|
||||||
|
rc = zl3073x_read_u8(zldev, ZL_REG_RESET_STATUS, &reset_status);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Check the reset bit was cleared */
|
||||||
|
if (reset_status & ZL_REG_RESET_STATUS_RESET) {
|
||||||
|
dev_err(zldev->dev,
|
||||||
|
"Reset not confirmed after switch to normal mode\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
29
drivers/dpll/zl3073x/flash.h
Normal file
29
drivers/dpll/zl3073x/flash.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __ZL3073X_FLASH_H
|
||||||
|
#define __ZL3073X_FLASH_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
struct netlink_ext_ack;
|
||||||
|
struct zl3073x_dev;
|
||||||
|
|
||||||
|
int zl3073x_flash_mode_enter(struct zl3073x_dev *zldev, const void *util_ptr,
|
||||||
|
size_t util_size, struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
|
int zl3073x_flash_mode_leave(struct zl3073x_dev *zldev,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
|
int zl3073x_flash_page(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 page, u32 addr, const void *data, size_t size,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
|
int zl3073x_flash_page_copy(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 src_page, u32 dst_page,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
|
int zl3073x_flash_sectors(struct zl3073x_dev *zldev, const char *component,
|
||||||
|
u32 page, u32 addr, const void *data, size_t size,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
|
#endif /* __ZL3073X_FLASH_H */
|
||||||
419
drivers/dpll/zl3073x/fw.c
Normal file
419
drivers/dpll/zl3073x/fw.c
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <linux/array_size.h>
|
||||||
|
#include <linux/build_bug.h>
|
||||||
|
#include <linux/dev_printk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "flash.h"
|
||||||
|
#include "fw.h"
|
||||||
|
|
||||||
|
#define ZL3073X_FW_ERR_PFX "FW load failed: "
|
||||||
|
#define ZL3073X_FW_ERR_MSG(_extack, _msg, ...) \
|
||||||
|
NL_SET_ERR_MSG_FMT_MOD((_extack), ZL3073X_FW_ERR_PFX _msg, \
|
||||||
|
## __VA_ARGS__)
|
||||||
|
|
||||||
|
enum zl3073x_flash_type {
|
||||||
|
ZL3073X_FLASH_TYPE_NONE = 0,
|
||||||
|
ZL3073X_FLASH_TYPE_SECTORS,
|
||||||
|
ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zl3073x_fw_component_info {
|
||||||
|
const char *name;
|
||||||
|
size_t max_size;
|
||||||
|
enum zl3073x_flash_type flash_type;
|
||||||
|
u32 load_addr;
|
||||||
|
u32 dest_page;
|
||||||
|
u32 copy_page;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct zl3073x_fw_component_info component_info[] = {
|
||||||
|
[ZL_FW_COMPONENT_UTIL] = {
|
||||||
|
.name = "utility",
|
||||||
|
.max_size = 0x4000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_NONE,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_FW1] = {
|
||||||
|
.name = "firmware1",
|
||||||
|
.max_size = 0x35000,
|
||||||
|
.load_addr = 0x20002000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_SECTORS,
|
||||||
|
.dest_page = 0x020,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_FW2] = {
|
||||||
|
.name = "firmware2",
|
||||||
|
.max_size = 0x0040,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
|
||||||
|
.dest_page = 0x3e0,
|
||||||
|
.copy_page = 0x000,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_FW3] = {
|
||||||
|
.name = "firmware3",
|
||||||
|
.max_size = 0x0248,
|
||||||
|
.load_addr = 0x20000400,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
|
||||||
|
.dest_page = 0x3e4,
|
||||||
|
.copy_page = 0x004,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_CFG0] = {
|
||||||
|
.name = "config0",
|
||||||
|
.max_size = 0x1000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
.dest_page = 0x3d0,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_CFG1] = {
|
||||||
|
.name = "config1",
|
||||||
|
.max_size = 0x1000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
.dest_page = 0x3c0,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_CFG2] = {
|
||||||
|
.name = "config2",
|
||||||
|
.max_size = 0x1000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
.dest_page = 0x3b0,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_CFG3] = {
|
||||||
|
.name = "config3",
|
||||||
|
.max_size = 0x1000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
.dest_page = 0x3a0,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_CFG4] = {
|
||||||
|
.name = "config4",
|
||||||
|
.max_size = 0x1000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
.dest_page = 0x390,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_CFG5] = {
|
||||||
|
.name = "config5",
|
||||||
|
.max_size = 0x1000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
.dest_page = 0x380,
|
||||||
|
},
|
||||||
|
[ZL_FW_COMPONENT_CFG6] = {
|
||||||
|
.name = "config6",
|
||||||
|
.max_size = 0x1000,
|
||||||
|
.load_addr = 0x20000000,
|
||||||
|
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
|
||||||
|
.dest_page = 0x370,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
static_assert(ARRAY_SIZE(component_info) == ZL_FW_NUM_COMPONENTS);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_fw_component_alloc - Alloc structure to hold firmware component
|
||||||
|
* @size: size of buffer to store data
|
||||||
|
*
|
||||||
|
* Return: pointer to allocated component structure or NULL on error.
|
||||||
|
*/
|
||||||
|
static struct zl3073x_fw_component *
|
||||||
|
zl3073x_fw_component_alloc(size_t size)
|
||||||
|
{
|
||||||
|
struct zl3073x_fw_component *comp;
|
||||||
|
|
||||||
|
comp = kzalloc(sizeof(*comp), GFP_KERNEL);
|
||||||
|
if (!comp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
comp->size = size;
|
||||||
|
comp->data = kzalloc(size, GFP_KERNEL);
|
||||||
|
if (!comp->data) {
|
||||||
|
kfree(comp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_fw_component_free - Free allocated component structure
|
||||||
|
* @comp: pointer to allocated component
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
zl3073x_fw_component_free(struct zl3073x_fw_component *comp)
|
||||||
|
{
|
||||||
|
if (comp)
|
||||||
|
kfree(comp->data);
|
||||||
|
|
||||||
|
kfree(comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_fw_component_id_get - Get ID for firmware component name
|
||||||
|
* @name: input firmware component name
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* - ZL3073X_FW_COMPONENT_* ID for known component name
|
||||||
|
* - ZL3073X_FW_COMPONENT_INVALID if the given name is unknown
|
||||||
|
*/
|
||||||
|
static enum zl3073x_fw_component_id
|
||||||
|
zl3073x_fw_component_id_get(const char *name)
|
||||||
|
{
|
||||||
|
enum zl3073x_fw_component_id id;
|
||||||
|
|
||||||
|
for (id = 0; id < ZL_FW_NUM_COMPONENTS; id++)
|
||||||
|
if (!strcasecmp(name, component_info[id].name))
|
||||||
|
return id;
|
||||||
|
|
||||||
|
return ZL_FW_COMPONENT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_fw_component_load - Load component from firmware source
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @pcomp: pointer to loaded component
|
||||||
|
* @psrc: data pointer to load component from
|
||||||
|
* @psize: remaining bytes in buffer
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The function allocates single firmware component and loads the data from
|
||||||
|
* the buffer specified by @psrc and @psize. Pointer to allocated component
|
||||||
|
* is stored in output @pcomp. Source data pointer @psrc and remaining bytes
|
||||||
|
* @psize are updated accordingly.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* * 1 when component was allocated and loaded
|
||||||
|
* * 0 when there is no component to load
|
||||||
|
* * <0 on error
|
||||||
|
*/
|
||||||
|
static ssize_t
|
||||||
|
zl3073x_fw_component_load(struct zl3073x_dev *zldev,
|
||||||
|
struct zl3073x_fw_component **pcomp,
|
||||||
|
const char **psrc, size_t *psize,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
const struct zl3073x_fw_component_info *info;
|
||||||
|
struct zl3073x_fw_component *comp = NULL;
|
||||||
|
struct device *dev = zldev->dev;
|
||||||
|
enum zl3073x_fw_component_id id;
|
||||||
|
char buf[32], name[16];
|
||||||
|
u32 count, size, *dest;
|
||||||
|
int pos, rc;
|
||||||
|
|
||||||
|
/* Fetch image name and size from input */
|
||||||
|
strscpy(buf, *psrc, min(sizeof(buf), *psize));
|
||||||
|
rc = sscanf(buf, "%15s %u %n", name, &count, &pos);
|
||||||
|
if (!rc) {
|
||||||
|
/* No more data */
|
||||||
|
return 0;
|
||||||
|
} else if (rc == 1 || count > U32_MAX / sizeof(u32)) {
|
||||||
|
ZL3073X_FW_ERR_MSG(extack, "invalid component size");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
*psrc += pos;
|
||||||
|
*psize -= pos;
|
||||||
|
|
||||||
|
dev_dbg(dev, "Firmware component '%s' found\n", name);
|
||||||
|
|
||||||
|
id = zl3073x_fw_component_id_get(name);
|
||||||
|
if (id == ZL_FW_COMPONENT_INVALID) {
|
||||||
|
ZL3073X_FW_ERR_MSG(extack, "unknown component type '%s'", name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
info = &component_info[id];
|
||||||
|
size = count * sizeof(u32); /* get size in bytes */
|
||||||
|
|
||||||
|
/* Check image size validity */
|
||||||
|
if (size > component_info[id].max_size) {
|
||||||
|
ZL3073X_FW_ERR_MSG(extack,
|
||||||
|
"[%s] component is too big (%u bytes)\n",
|
||||||
|
info->name, size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(dev, "Indicated component image size: %u bytes\n", size);
|
||||||
|
|
||||||
|
/* Alloc component */
|
||||||
|
comp = zl3073x_fw_component_alloc(size);
|
||||||
|
if (!comp) {
|
||||||
|
ZL3073X_FW_ERR_MSG(extack, "failed to alloc memory");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
comp->id = id;
|
||||||
|
|
||||||
|
/* Load component data from firmware source */
|
||||||
|
for (dest = comp->data; count; count--, dest++) {
|
||||||
|
strscpy(buf, *psrc, min(sizeof(buf), *psize));
|
||||||
|
rc = sscanf(buf, "%x %n", dest, &pos);
|
||||||
|
if (!rc)
|
||||||
|
goto err_data;
|
||||||
|
|
||||||
|
*psrc += pos;
|
||||||
|
*psize -= pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pcomp = comp;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err_data:
|
||||||
|
ZL3073X_FW_ERR_MSG(extack, "[%s] invalid or missing data", info->name);
|
||||||
|
|
||||||
|
zl3073x_fw_component_free(comp);
|
||||||
|
|
||||||
|
return -ENODATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_fw_free - Free allocated firmware
|
||||||
|
* @fw: firmware pointer
|
||||||
|
*
|
||||||
|
* The function frees existing firmware allocated by @zl3073x_fw_load.
|
||||||
|
*/
|
||||||
|
void zl3073x_fw_free(struct zl3073x_fw *fw)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!fw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++)
|
||||||
|
zl3073x_fw_component_free(fw->component[i]);
|
||||||
|
|
||||||
|
kfree(fw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_fw_load - Load all components from source
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @data: source buffer pointer
|
||||||
|
* @size: size of source buffer
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* The functions allocate firmware structure and loads all components from
|
||||||
|
* the given buffer specified by @data and @size.
|
||||||
|
*
|
||||||
|
* Return: pointer to firmware on success, error pointer on error
|
||||||
|
*/
|
||||||
|
struct zl3073x_fw *zl3073x_fw_load(struct zl3073x_dev *zldev, const char *data,
|
||||||
|
size_t size, struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
struct zl3073x_fw_component *comp;
|
||||||
|
enum zl3073x_fw_component_id id;
|
||||||
|
struct zl3073x_fw *fw;
|
||||||
|
ssize_t rc;
|
||||||
|
|
||||||
|
/* Allocate firmware structure */
|
||||||
|
fw = kzalloc(sizeof(*fw), GFP_KERNEL);
|
||||||
|
if (!fw)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Load single component */
|
||||||
|
rc = zl3073x_fw_component_load(zldev, &comp, &data, &size,
|
||||||
|
extack);
|
||||||
|
if (rc <= 0)
|
||||||
|
/* Everything was read or error occurred */
|
||||||
|
break;
|
||||||
|
|
||||||
|
id = comp->id;
|
||||||
|
|
||||||
|
/* Report error if the given component is present twice
|
||||||
|
* or more.
|
||||||
|
*/
|
||||||
|
if (fw->component[id]) {
|
||||||
|
ZL3073X_FW_ERR_MSG(extack,
|
||||||
|
"duplicate component '%s' detected",
|
||||||
|
component_info[id].name);
|
||||||
|
zl3073x_fw_component_free(comp);
|
||||||
|
rc = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fw->component[id] = comp;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
/* Free allocated firmware in case of error */
|
||||||
|
zl3073x_fw_free(fw);
|
||||||
|
return ERR_PTR(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_fw_component_flash - Flash all components
|
||||||
|
* @zldev: zl3073x device structure
|
||||||
|
* @comp: pointer to components array
|
||||||
|
* @extack: netlink extack pointer to report errors
|
||||||
|
*
|
||||||
|
* Return: 0 in case of success or negative number otherwise.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_fw_component_flash(struct zl3073x_dev *zldev,
|
||||||
|
struct zl3073x_fw_component *comp,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
const struct zl3073x_fw_component_info *info;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
info = &component_info[comp->id];
|
||||||
|
|
||||||
|
switch (info->flash_type) {
|
||||||
|
case ZL3073X_FLASH_TYPE_NONE:
|
||||||
|
/* Non-flashable component - used for utility */
|
||||||
|
return 0;
|
||||||
|
case ZL3073X_FLASH_TYPE_SECTORS:
|
||||||
|
rc = zl3073x_flash_sectors(zldev, info->name, info->dest_page,
|
||||||
|
info->load_addr, comp->data,
|
||||||
|
comp->size, extack);
|
||||||
|
break;
|
||||||
|
case ZL3073X_FLASH_TYPE_PAGE:
|
||||||
|
rc = zl3073x_flash_page(zldev, info->name, info->dest_page,
|
||||||
|
info->load_addr, comp->data, comp->size,
|
||||||
|
extack);
|
||||||
|
break;
|
||||||
|
case ZL3073X_FLASH_TYPE_PAGE_AND_COPY:
|
||||||
|
rc = zl3073x_flash_page(zldev, info->name, info->dest_page,
|
||||||
|
info->load_addr, comp->data, comp->size,
|
||||||
|
extack);
|
||||||
|
if (!rc)
|
||||||
|
rc = zl3073x_flash_page_copy(zldev, info->name,
|
||||||
|
info->dest_page,
|
||||||
|
info->copy_page, extack);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (rc)
|
||||||
|
ZL3073X_FW_ERR_MSG(extack, "Failed to flash component '%s'",
|
||||||
|
info->name);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zl3073x_fw_flash(struct zl3073x_dev *zldev, struct zl3073x_fw *zlfw,
|
||||||
|
struct netlink_ext_ack *extack)
|
||||||
|
{
|
||||||
|
int i, rc = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++) {
|
||||||
|
if (!zlfw->component[i])
|
||||||
|
continue; /* Component is not present */
|
||||||
|
|
||||||
|
rc = zl3073x_fw_component_flash(zldev, zlfw->component[i],
|
||||||
|
extack);
|
||||||
|
if (rc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
52
drivers/dpll/zl3073x/fw.h
Normal file
52
drivers/dpll/zl3073x/fw.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef _ZL3073X_FW_H
|
||||||
|
#define _ZL3073X_FW_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* enum zl3073x_fw_component_id - Identifiers for possible flash components
|
||||||
|
*/
|
||||||
|
enum zl3073x_fw_component_id {
|
||||||
|
ZL_FW_COMPONENT_INVALID = -1,
|
||||||
|
ZL_FW_COMPONENT_UTIL = 0,
|
||||||
|
ZL_FW_COMPONENT_FW1,
|
||||||
|
ZL_FW_COMPONENT_FW2,
|
||||||
|
ZL_FW_COMPONENT_FW3,
|
||||||
|
ZL_FW_COMPONENT_CFG0,
|
||||||
|
ZL_FW_COMPONENT_CFG1,
|
||||||
|
ZL_FW_COMPONENT_CFG2,
|
||||||
|
ZL_FW_COMPONENT_CFG3,
|
||||||
|
ZL_FW_COMPONENT_CFG4,
|
||||||
|
ZL_FW_COMPONENT_CFG5,
|
||||||
|
ZL_FW_COMPONENT_CFG6,
|
||||||
|
ZL_FW_NUM_COMPONENTS
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_fw_component - Firmware component
|
||||||
|
* @id: Flash component ID
|
||||||
|
* @size: Size of the buffer
|
||||||
|
* @data: Pointer to buffer with component data
|
||||||
|
*/
|
||||||
|
struct zl3073x_fw_component {
|
||||||
|
enum zl3073x_fw_component_id id;
|
||||||
|
size_t size;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_fw - Firmware bundle
|
||||||
|
* @component: firmware components array
|
||||||
|
*/
|
||||||
|
struct zl3073x_fw {
|
||||||
|
struct zl3073x_fw_component *component[ZL_FW_NUM_COMPONENTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zl3073x_fw *zl3073x_fw_load(struct zl3073x_dev *zldev, const char *data,
|
||||||
|
size_t size, struct netlink_ext_ack *extack);
|
||||||
|
void zl3073x_fw_free(struct zl3073x_fw *fw);
|
||||||
|
|
||||||
|
int zl3073x_fw_flash(struct zl3073x_dev *zldev, struct zl3073x_fw *zlfw,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
|
#endif /* _ZL3073X_FW_H */
|
||||||
76
drivers/dpll/zl3073x/i2c.c
Normal file
76
drivers/dpll/zl3073x/i2c.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include <linux/dev_printk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
static int zl3073x_i2c_probe(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct device *dev = &client->dev;
|
||||||
|
struct zl3073x_dev *zldev;
|
||||||
|
|
||||||
|
zldev = zl3073x_devm_alloc(dev);
|
||||||
|
if (IS_ERR(zldev))
|
||||||
|
return PTR_ERR(zldev);
|
||||||
|
|
||||||
|
zldev->regmap = devm_regmap_init_i2c(client, &zl3073x_regmap_config);
|
||||||
|
if (IS_ERR(zldev->regmap))
|
||||||
|
return dev_err_probe(dev, PTR_ERR(zldev->regmap),
|
||||||
|
"Failed to initialize regmap\n");
|
||||||
|
|
||||||
|
return zl3073x_dev_probe(zldev, i2c_get_match_data(client));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id zl3073x_i2c_id[] = {
|
||||||
|
{
|
||||||
|
.name = "zl30731",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30731_chip_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30732",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30732_chip_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30733",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30733_chip_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30734",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30734_chip_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30735",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30735_chip_info,
|
||||||
|
},
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, zl3073x_i2c_id);
|
||||||
|
|
||||||
|
static const struct of_device_id zl3073x_i2c_of_match[] = {
|
||||||
|
{ .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, zl3073x_i2c_of_match);
|
||||||
|
|
||||||
|
static struct i2c_driver zl3073x_i2c_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "zl3073x-i2c",
|
||||||
|
.of_match_table = zl3073x_i2c_of_match,
|
||||||
|
},
|
||||||
|
.probe_new = zl3073x_i2c_probe,
|
||||||
|
.id_table = zl3073x_i2c_id,
|
||||||
|
};
|
||||||
|
module_i2c_driver(zl3073x_i2c_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>");
|
||||||
|
MODULE_DESCRIPTION("Microchip ZL3073x I2C driver");
|
||||||
|
MODULE_IMPORT_NS(ZL3073X);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
358
drivers/dpll/zl3073x/prop.c
Normal file
358
drivers/dpll/zl3073x/prop.c
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include <linux/array_size.h>
|
||||||
|
#include <linux/dev_printk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/fwnode.h>
|
||||||
|
#include <linux/property.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "prop.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_pin_check_freq - verify frequency for given pin
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @dir: pin direction
|
||||||
|
* @id: pin index
|
||||||
|
* @freq: frequency to check
|
||||||
|
*
|
||||||
|
* The function checks the given frequency is valid for the device. For input
|
||||||
|
* pins it checks that the frequency can be factorized using supported base
|
||||||
|
* frequencies. For output pins it checks that the frequency divides connected
|
||||||
|
* synth frequency without remainder.
|
||||||
|
*
|
||||||
|
* Return: true if the frequency is valid, false if not.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
zl3073x_pin_check_freq(struct zl3073x_dev *zldev, enum dpll_pin_direction dir,
|
||||||
|
u8 id, u64 freq)
|
||||||
|
{
|
||||||
|
if (freq > U32_MAX)
|
||||||
|
goto err_inv_freq;
|
||||||
|
|
||||||
|
if (dir == DPLL_PIN_DIRECTION_INPUT) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Check if the frequency can be factorized */
|
||||||
|
rc = zl3073x_ref_freq_factorize(freq, NULL, NULL);
|
||||||
|
if (rc)
|
||||||
|
goto err_inv_freq;
|
||||||
|
} else {
|
||||||
|
u32 synth_freq;
|
||||||
|
u8 out, synth;
|
||||||
|
|
||||||
|
/* Get output pin synthesizer */
|
||||||
|
out = zl3073x_output_pin_out_get(id);
|
||||||
|
synth = zl3073x_out_synth_get(zldev, out);
|
||||||
|
|
||||||
|
/* Get synth frequency */
|
||||||
|
synth_freq = zl3073x_synth_freq_get(zldev, synth);
|
||||||
|
|
||||||
|
/* Check the frequency divides synth frequency */
|
||||||
|
if (synth_freq % (u32)freq)
|
||||||
|
goto err_inv_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
err_inv_freq:
|
||||||
|
dev_warn(zldev->dev,
|
||||||
|
"Unsupported frequency %llu Hz in firmware node\n", freq);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_prop_pin_package_label_set - get package label for the pin
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @props: pointer to pin properties
|
||||||
|
* @dir: pin direction
|
||||||
|
* @id: pin index
|
||||||
|
*
|
||||||
|
* Generates package label string and stores it into pin properties structure.
|
||||||
|
*
|
||||||
|
* Possible formats:
|
||||||
|
* REF<n> - differential input reference
|
||||||
|
* REF<n>P & REF<n>N - single-ended input reference (P or N pin)
|
||||||
|
* OUT<n> - differential output
|
||||||
|
* OUT<n>P & OUT<n>N - single-ended output (P or N pin)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
zl3073x_prop_pin_package_label_set(struct zl3073x_dev *zldev,
|
||||||
|
struct zl3073x_pin_props *props,
|
||||||
|
enum dpll_pin_direction dir, u8 id)
|
||||||
|
{
|
||||||
|
const char *prefix, *suffix;
|
||||||
|
bool is_diff;
|
||||||
|
|
||||||
|
if (dir == DPLL_PIN_DIRECTION_INPUT) {
|
||||||
|
u8 ref;
|
||||||
|
|
||||||
|
prefix = "REF";
|
||||||
|
ref = zl3073x_input_pin_ref_get(id);
|
||||||
|
is_diff = zl3073x_ref_is_diff(zldev, ref);
|
||||||
|
} else {
|
||||||
|
u8 out;
|
||||||
|
|
||||||
|
prefix = "OUT";
|
||||||
|
out = zl3073x_output_pin_out_get(id);
|
||||||
|
is_diff = zl3073x_out_is_diff(zldev, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_diff)
|
||||||
|
suffix = zl3073x_is_p_pin(id) ? "P" : "N";
|
||||||
|
else
|
||||||
|
suffix = ""; /* No suffix for differential one */
|
||||||
|
|
||||||
|
snprintf(props->package_label, sizeof(props->package_label), "%s%u%s",
|
||||||
|
prefix, id / 2, suffix);
|
||||||
|
|
||||||
|
/* Set package_label pointer in DPLL core properties to generated
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
props->dpll_props.package_label = props->package_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_prop_pin_fwnode_get - get fwnode for given pin
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @props: pointer to pin properties
|
||||||
|
* @dir: pin direction
|
||||||
|
* @id: pin index
|
||||||
|
*
|
||||||
|
* Return: 0 on success, -ENOENT if the firmware node does not exist
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
zl3073x_prop_pin_fwnode_get(struct zl3073x_dev *zldev,
|
||||||
|
struct zl3073x_pin_props *props,
|
||||||
|
enum dpll_pin_direction dir, u8 id)
|
||||||
|
{
|
||||||
|
struct fwnode_handle *pins_node, *pin_node;
|
||||||
|
const char *node_name;
|
||||||
|
|
||||||
|
if (dir == DPLL_PIN_DIRECTION_INPUT)
|
||||||
|
node_name = "input-pins";
|
||||||
|
else
|
||||||
|
node_name = "output-pins";
|
||||||
|
|
||||||
|
/* Get node containing input or output pins */
|
||||||
|
pins_node = device_get_named_child_node(zldev->dev, node_name);
|
||||||
|
if (!pins_node) {
|
||||||
|
dev_dbg(zldev->dev, "'%s' sub-node is missing\n", node_name);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enumerate child pin nodes and find the requested one */
|
||||||
|
fwnode_for_each_child_node(pins_node, pin_node) {
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (fwnode_property_read_u32(pin_node, "reg", ®))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (id == reg)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release pin parent node */
|
||||||
|
fwnode_handle_put(pins_node);
|
||||||
|
|
||||||
|
/* Save found node */
|
||||||
|
props->fwnode = pin_node;
|
||||||
|
|
||||||
|
dev_dbg(zldev->dev, "Firmware node for %s %sfound\n",
|
||||||
|
props->package_label, pin_node ? "" : "NOT ");
|
||||||
|
|
||||||
|
return pin_node ? 0 : -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_pin_props_get - get pin properties
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @dir: pin direction
|
||||||
|
* @index: pin index
|
||||||
|
*
|
||||||
|
* The function looks for firmware node for the given pin if it is provided
|
||||||
|
* by the system firmware (DT or ACPI), allocates pin properties structure,
|
||||||
|
* generates package label string according pin type and optionally fetches
|
||||||
|
* board label, connection type, supported frequencies and esync capability
|
||||||
|
* from the firmware node if it does exist.
|
||||||
|
*
|
||||||
|
* Pointer that is returned by this function should be freed using
|
||||||
|
* @zl3073x_pin_props_put().
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* * pointer to allocated pin properties structure on success
|
||||||
|
* * error pointer in case of error
|
||||||
|
*/
|
||||||
|
struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||||
|
enum dpll_pin_direction dir,
|
||||||
|
u8 index)
|
||||||
|
{
|
||||||
|
struct dpll_pin_frequency *ranges;
|
||||||
|
struct zl3073x_pin_props *props;
|
||||||
|
int i, j, num_freqs, rc;
|
||||||
|
const char *type;
|
||||||
|
u64 *freqs;
|
||||||
|
|
||||||
|
props = kzalloc(sizeof(*props), GFP_KERNEL);
|
||||||
|
if (!props)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
/* Set default pin type and capabilities */
|
||||||
|
if (dir == DPLL_PIN_DIRECTION_INPUT) {
|
||||||
|
props->dpll_props.type = DPLL_PIN_TYPE_EXT;
|
||||||
|
props->dpll_props.capabilities =
|
||||||
|
DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
|
||||||
|
DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
|
||||||
|
} else {
|
||||||
|
props->dpll_props.type = DPLL_PIN_TYPE_GNSS;
|
||||||
|
}
|
||||||
|
|
||||||
|
props->dpll_props.phase_range.min = S32_MIN;
|
||||||
|
props->dpll_props.phase_range.max = S32_MAX;
|
||||||
|
|
||||||
|
zl3073x_prop_pin_package_label_set(zldev, props, dir, index);
|
||||||
|
|
||||||
|
/* Get firmware node for the given pin */
|
||||||
|
rc = zl3073x_prop_pin_fwnode_get(zldev, props, dir, index);
|
||||||
|
if (rc)
|
||||||
|
return props; /* Return if it does not exist */
|
||||||
|
|
||||||
|
/* Look for label property and store the value as board label */
|
||||||
|
fwnode_property_read_string(props->fwnode, "label",
|
||||||
|
&props->dpll_props.board_label);
|
||||||
|
|
||||||
|
/* Look for pin type property and translate its value to DPLL
|
||||||
|
* pin type enum if it is present.
|
||||||
|
*/
|
||||||
|
if (!fwnode_property_read_string(props->fwnode, "connection-type",
|
||||||
|
&type)) {
|
||||||
|
if (!strcmp(type, "ext"))
|
||||||
|
props->dpll_props.type = DPLL_PIN_TYPE_EXT;
|
||||||
|
else if (!strcmp(type, "gnss"))
|
||||||
|
props->dpll_props.type = DPLL_PIN_TYPE_GNSS;
|
||||||
|
else if (!strcmp(type, "int"))
|
||||||
|
props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
|
||||||
|
else if (!strcmp(type, "synce"))
|
||||||
|
props->dpll_props.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT;
|
||||||
|
else
|
||||||
|
dev_warn(zldev->dev,
|
||||||
|
"Unknown or unsupported pin type '%s'\n",
|
||||||
|
type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the pin supports embedded sync control */
|
||||||
|
props->esync_control = fwnode_property_read_bool(props->fwnode,
|
||||||
|
"esync-control");
|
||||||
|
|
||||||
|
/* Read supported frequencies property if it is specified */
|
||||||
|
num_freqs = fwnode_property_count_u64(props->fwnode,
|
||||||
|
"supported-frequencies-hz");
|
||||||
|
if (num_freqs <= 0)
|
||||||
|
/* Return if the property does not exist or number is 0 */
|
||||||
|
return props;
|
||||||
|
|
||||||
|
/* The firmware node specifies list of supported frequencies while
|
||||||
|
* DPLL core pin properties requires list of frequency ranges.
|
||||||
|
* So read the frequency list into temporary array.
|
||||||
|
*/
|
||||||
|
freqs = kcalloc(num_freqs, sizeof(*freqs), GFP_KERNEL);
|
||||||
|
if (!freqs) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_alloc_freqs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read frequencies list from firmware node */
|
||||||
|
fwnode_property_read_u64_array(props->fwnode,
|
||||||
|
"supported-frequencies-hz", freqs,
|
||||||
|
num_freqs);
|
||||||
|
|
||||||
|
/* Allocate frequency ranges list and fill it */
|
||||||
|
ranges = kcalloc(num_freqs, sizeof(*ranges), GFP_KERNEL);
|
||||||
|
if (!ranges) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_alloc_ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert list of frequencies to list of frequency ranges but
|
||||||
|
* filter-out frequencies that are not representable by device
|
||||||
|
*/
|
||||||
|
for (i = 0, j = 0; i < num_freqs; i++) {
|
||||||
|
struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]);
|
||||||
|
|
||||||
|
if (zl3073x_pin_check_freq(zldev, dir, index, freqs[i])) {
|
||||||
|
ranges[j] = freq;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save number of freq ranges and pointer to them into pin properties */
|
||||||
|
props->dpll_props.freq_supported = ranges;
|
||||||
|
props->dpll_props.freq_supported_num = j;
|
||||||
|
|
||||||
|
/* Free temporary array */
|
||||||
|
kfree(freqs);
|
||||||
|
|
||||||
|
return props;
|
||||||
|
|
||||||
|
err_alloc_ranges:
|
||||||
|
kfree(freqs);
|
||||||
|
err_alloc_freqs:
|
||||||
|
fwnode_handle_put(props->fwnode);
|
||||||
|
kfree(props);
|
||||||
|
|
||||||
|
return ERR_PTR(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_pin_props_put - release pin properties
|
||||||
|
* @props: pin properties to free
|
||||||
|
*
|
||||||
|
* The function deallocates given pin properties structure.
|
||||||
|
*/
|
||||||
|
void zl3073x_pin_props_put(struct zl3073x_pin_props *props)
|
||||||
|
{
|
||||||
|
/* Free supported frequency ranges list if it is present */
|
||||||
|
kfree(props->dpll_props.freq_supported);
|
||||||
|
|
||||||
|
/* Put firmware handle if it is present */
|
||||||
|
if (props->fwnode)
|
||||||
|
fwnode_handle_put(props->fwnode);
|
||||||
|
|
||||||
|
kfree(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* zl3073x_prop_dpll_type_get - get DPLL channel type
|
||||||
|
* @zldev: pointer to zl3073x device
|
||||||
|
* @index: DPLL channel index
|
||||||
|
*
|
||||||
|
* Return: DPLL type for given DPLL channel
|
||||||
|
*/
|
||||||
|
enum dpll_type
|
||||||
|
zl3073x_prop_dpll_type_get(struct zl3073x_dev *zldev, u8 index)
|
||||||
|
{
|
||||||
|
const char *types[ZL3073X_MAX_CHANNELS];
|
||||||
|
int count;
|
||||||
|
|
||||||
|
/* Read dpll types property from firmware */
|
||||||
|
count = device_property_read_string_array(zldev->dev, "dpll-types",
|
||||||
|
types, ARRAY_SIZE(types));
|
||||||
|
|
||||||
|
/* Return default if property or entry for given channel is missing */
|
||||||
|
if (index >= count)
|
||||||
|
return DPLL_TYPE_PPS;
|
||||||
|
|
||||||
|
if (!strcmp(types[index], "pps"))
|
||||||
|
return DPLL_TYPE_PPS;
|
||||||
|
else if (!strcmp(types[index], "eec"))
|
||||||
|
return DPLL_TYPE_EEC;
|
||||||
|
|
||||||
|
dev_info(zldev->dev, "Unknown DPLL type '%s', using default\n",
|
||||||
|
types[index]);
|
||||||
|
|
||||||
|
return DPLL_TYPE_PPS; /* Default */
|
||||||
|
}
|
||||||
34
drivers/dpll/zl3073x/prop.h
Normal file
34
drivers/dpll/zl3073x/prop.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef _ZL3073X_PROP_H
|
||||||
|
#define _ZL3073X_PROP_H
|
||||||
|
|
||||||
|
#include <linux/dpll.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
struct fwnode_handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct zl3073x_pin_props - pin properties
|
||||||
|
* @fwnode: pin firmware node
|
||||||
|
* @dpll_props: DPLL core pin properties
|
||||||
|
* @package_label: pin package label
|
||||||
|
* @esync_control: embedded sync support
|
||||||
|
*/
|
||||||
|
struct zl3073x_pin_props {
|
||||||
|
struct fwnode_handle *fwnode;
|
||||||
|
struct dpll_pin_properties dpll_props;
|
||||||
|
char package_label[8];
|
||||||
|
bool esync_control;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dpll_type zl3073x_prop_dpll_type_get(struct zl3073x_dev *zldev, u8 index);
|
||||||
|
|
||||||
|
struct zl3073x_pin_props *zl3073x_pin_props_get(struct zl3073x_dev *zldev,
|
||||||
|
enum dpll_pin_direction dir,
|
||||||
|
u8 index);
|
||||||
|
|
||||||
|
void zl3073x_pin_props_put(struct zl3073x_pin_props *props);
|
||||||
|
|
||||||
|
#endif /* _ZL3073X_PROP_H */
|
||||||
317
drivers/dpll/zl3073x/regs.h
Normal file
317
drivers/dpll/zl3073x/regs.h
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#ifndef _ZL3073X_REGS_H
|
||||||
|
#define _ZL3073X_REGS_H
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/bits.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register address structure:
|
||||||
|
* ===========================
|
||||||
|
* 25 19 18 16 15 7 6 0
|
||||||
|
* +------------------------------------------+
|
||||||
|
* | max_offset | size | page | page_offset |
|
||||||
|
* +------------------------------------------+
|
||||||
|
*
|
||||||
|
* page_offset ... <0x00..0x7F>
|
||||||
|
* page .......... HW page number
|
||||||
|
* size .......... register byte size (1, 2, 4 or 6)
|
||||||
|
* max_offset .... maximal offset for indexed registers
|
||||||
|
* (for non-indexed regs max_offset == page_offset)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ZL_REG_OFFSET_MASK GENMASK(6, 0)
|
||||||
|
#define ZL_REG_PAGE_MASK GENMASK(15, 7)
|
||||||
|
#define ZL_REG_SIZE_MASK GENMASK(18, 16)
|
||||||
|
#define ZL_REG_MAX_OFFSET_MASK GENMASK(25, 19)
|
||||||
|
#define ZL_REG_ADDR_MASK GENMASK(15, 0)
|
||||||
|
|
||||||
|
#define ZL_REG_OFFSET(_reg) FIELD_GET(ZL_REG_OFFSET_MASK, _reg)
|
||||||
|
#define ZL_REG_PAGE(_reg) FIELD_GET(ZL_REG_PAGE_MASK, _reg)
|
||||||
|
#define ZL_REG_MAX_OFFSET(_reg) FIELD_GET(ZL_REG_MAX_OFFSET_MASK, _reg)
|
||||||
|
#define ZL_REG_SIZE(_reg) FIELD_GET(ZL_REG_SIZE_MASK, _reg)
|
||||||
|
#define ZL_REG_ADDR(_reg) FIELD_GET(ZL_REG_ADDR_MASK, _reg)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZL_REG_IDX - define indexed register
|
||||||
|
* @_idx: index of register to access
|
||||||
|
* @_page: register page
|
||||||
|
* @_offset: register offset in page
|
||||||
|
* @_size: register byte size (1, 2, 4 or 6)
|
||||||
|
* @_items: number of register indices
|
||||||
|
* @_stride: stride between items in bytes
|
||||||
|
*
|
||||||
|
* All parameters except @_idx should be constant.
|
||||||
|
*/
|
||||||
|
#define ZL_REG_IDX(_idx, _page, _offset, _size, _items, _stride) \
|
||||||
|
(FIELD_PREP(ZL_REG_OFFSET_MASK, \
|
||||||
|
(_offset) + (_idx) * (_stride)) | \
|
||||||
|
FIELD_PREP_CONST(ZL_REG_PAGE_MASK, _page) | \
|
||||||
|
FIELD_PREP_CONST(ZL_REG_SIZE_MASK, _size) | \
|
||||||
|
FIELD_PREP_CONST(ZL_REG_MAX_OFFSET_MASK, \
|
||||||
|
(_offset) + ((_items) - 1) * (_stride)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZL_REG - define simple (non-indexed) register
|
||||||
|
* @_page: register page
|
||||||
|
* @_offset: register offset in page
|
||||||
|
* @_size: register byte size (1, 2, 4 or 6)
|
||||||
|
*
|
||||||
|
* All parameters should be constant.
|
||||||
|
*/
|
||||||
|
#define ZL_REG(_page, _offset, _size) \
|
||||||
|
ZL_REG_IDX(0, _page, _offset, _size, 1, 0)
|
||||||
|
|
||||||
|
/**************************
|
||||||
|
* Register Page 0, General
|
||||||
|
**************************/
|
||||||
|
|
||||||
|
#define ZL_REG_INFO ZL_REG(0, 0x00, 1)
|
||||||
|
#define ZL_INFO_READY BIT(7)
|
||||||
|
|
||||||
|
#define ZL_REG_ID ZL_REG(0, 0x01, 2)
|
||||||
|
#define ZL_REG_REVISION ZL_REG(0, 0x03, 2)
|
||||||
|
#define ZL_REG_FW_VER ZL_REG(0, 0x05, 2)
|
||||||
|
#define ZL_REG_CUSTOM_CONFIG_VER ZL_REG(0, 0x07, 4)
|
||||||
|
|
||||||
|
#define ZL_REG_RESET_STATUS ZL_REG(0, 0x18, 1)
|
||||||
|
#define ZL_REG_RESET_STATUS_RESET BIT(0)
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
* Register Page 2, Status
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
#define ZL_REG_REF_MON_STATUS(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 2, 0x02, 1, ZL3073X_NUM_REFS, 1)
|
||||||
|
#define ZL_REF_MON_STATUS_OK 0 /* all bits zeroed */
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_MON_STATUS(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 2, 0x10, 1, ZL3073X_MAX_CHANNELS, 1)
|
||||||
|
#define ZL_DPLL_MON_STATUS_STATE GENMASK(1, 0)
|
||||||
|
#define ZL_DPLL_MON_STATUS_STATE_ACQUIRING 0
|
||||||
|
#define ZL_DPLL_MON_STATUS_STATE_LOCK 1
|
||||||
|
#define ZL_DPLL_MON_STATUS_STATE_HOLDOVER 2
|
||||||
|
#define ZL_DPLL_MON_STATUS_HO_READY BIT(2)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_REFSEL_STATUS(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 2, 0x30, 1, ZL3073X_MAX_CHANNELS, 1)
|
||||||
|
#define ZL_DPLL_REFSEL_STATUS_REFSEL GENMASK(3, 0)
|
||||||
|
#define ZL_DPLL_REFSEL_STATUS_STATE GENMASK(6, 4)
|
||||||
|
#define ZL_DPLL_REFSEL_STATUS_STATE_LOCK 4
|
||||||
|
|
||||||
|
#define ZL_REG_REF_FREQ(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 2, 0x44, 4, ZL3073X_NUM_REFS, 4)
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
* Register Page 4, Ref
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
#define ZL_REG_REF_PHASE_ERR_READ_RQST ZL_REG(4, 0x0f, 1)
|
||||||
|
#define ZL_REF_PHASE_ERR_READ_RQST_RD BIT(0)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_FREQ_MEAS_CTRL ZL_REG(4, 0x1c, 1)
|
||||||
|
#define ZL_REF_FREQ_MEAS_CTRL GENMASK(1, 0)
|
||||||
|
#define ZL_REF_FREQ_MEAS_CTRL_REF_FREQ 1
|
||||||
|
#define ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF 2
|
||||||
|
#define ZL_REF_FREQ_MEAS_CTRL_DPLL_FREQ_OFF 3
|
||||||
|
|
||||||
|
#define ZL_REG_REF_FREQ_MEAS_MASK_3_0 ZL_REG(4, 0x1d, 1)
|
||||||
|
#define ZL_REF_FREQ_MEAS_MASK_3_0(_ref) BIT(_ref)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_FREQ_MEAS_MASK_4 ZL_REG(4, 0x1e, 1)
|
||||||
|
#define ZL_REF_FREQ_MEAS_MASK_4(_ref) BIT((_ref) - 8)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_MEAS_REF_FREQ_CTRL ZL_REG(4, 0x1f, 1)
|
||||||
|
#define ZL_DPLL_MEAS_REF_FREQ_CTRL_EN BIT(0)
|
||||||
|
#define ZL_DPLL_MEAS_REF_FREQ_CTRL_IDX GENMASK(6, 4)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_PHASE(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 4, 0x20, 6, ZL3073X_NUM_REFS, 6)
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
* Register Page 5, DPLL
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_MODE_REFSEL(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 5, 0x04, 1, ZL3073X_MAX_CHANNELS, 4)
|
||||||
|
#define ZL_DPLL_MODE_REFSEL_MODE GENMASK(2, 0)
|
||||||
|
#define ZL_DPLL_MODE_REFSEL_MODE_FREERUN 0
|
||||||
|
#define ZL_DPLL_MODE_REFSEL_MODE_HOLDOVER 1
|
||||||
|
#define ZL_DPLL_MODE_REFSEL_MODE_REFLOCK 2
|
||||||
|
#define ZL_DPLL_MODE_REFSEL_MODE_AUTO 3
|
||||||
|
#define ZL_DPLL_MODE_REFSEL_MODE_NCO 4
|
||||||
|
#define ZL_DPLL_MODE_REFSEL_REF GENMASK(7, 4)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_MEAS_CTRL ZL_REG(5, 0x50, 1)
|
||||||
|
#define ZL_DPLL_MEAS_CTRL_EN BIT(0)
|
||||||
|
#define ZL_DPLL_MEAS_CTRL_AVG_FACTOR GENMASK(7, 4)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_MEAS_IDX ZL_REG(5, 0x51, 1)
|
||||||
|
#define ZL_DPLL_MEAS_IDX GENMASK(2, 0)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_PHASE_ERR_READ_MASK ZL_REG(5, 0x54, 1)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_PHASE_ERR_DATA(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 5, 0x55, 6, ZL3073X_MAX_CHANNELS, 6)
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Register Page 9, Synth and Output
|
||||||
|
***********************************/
|
||||||
|
|
||||||
|
#define ZL_REG_SYNTH_CTRL(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 9, 0x00, 1, ZL3073X_NUM_SYNTHS, 1)
|
||||||
|
#define ZL_SYNTH_CTRL_EN BIT(0)
|
||||||
|
#define ZL_SYNTH_CTRL_DPLL_SEL GENMASK(6, 4)
|
||||||
|
|
||||||
|
#define ZL_REG_SYNTH_PHASE_SHIFT_CTRL ZL_REG(9, 0x1e, 1)
|
||||||
|
#define ZL_REG_SYNTH_PHASE_SHIFT_MASK ZL_REG(9, 0x1f, 1)
|
||||||
|
#define ZL_REG_SYNTH_PHASE_SHIFT_INTVL ZL_REG(9, 0x20, 1)
|
||||||
|
#define ZL_REG_SYNTH_PHASE_SHIFT_DATA ZL_REG(9, 0x21, 2)
|
||||||
|
|
||||||
|
#define ZL_REG_OUTPUT_CTRL(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 9, 0x28, 1, ZL3073X_NUM_OUTS, 1)
|
||||||
|
#define ZL_OUTPUT_CTRL_EN BIT(0)
|
||||||
|
#define ZL_OUTPUT_CTRL_SYNTH_SEL GENMASK(6, 4)
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
* Register Page 10, Ref Mailbox
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
#define ZL_REG_REF_MB_MASK ZL_REG(10, 0x02, 2)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_MB_SEM ZL_REG(10, 0x04, 1)
|
||||||
|
#define ZL_REF_MB_SEM_WR BIT(0)
|
||||||
|
#define ZL_REF_MB_SEM_RD BIT(1)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_FREQ_BASE ZL_REG(10, 0x05, 2)
|
||||||
|
#define ZL_REG_REF_FREQ_MULT ZL_REG(10, 0x07, 2)
|
||||||
|
#define ZL_REG_REF_RATIO_M ZL_REG(10, 0x09, 2)
|
||||||
|
#define ZL_REG_REF_RATIO_N ZL_REG(10, 0x0b, 2)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_CONFIG ZL_REG(10, 0x0d, 1)
|
||||||
|
#define ZL_REF_CONFIG_ENABLE BIT(0)
|
||||||
|
#define ZL_REF_CONFIG_DIFF_EN BIT(2)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_PHASE_OFFSET_COMP ZL_REG(10, 0x28, 6)
|
||||||
|
|
||||||
|
#define ZL_REG_REF_SYNC_CTRL ZL_REG(10, 0x2e, 1)
|
||||||
|
#define ZL_REF_SYNC_CTRL_MODE GENMASK(2, 0)
|
||||||
|
#define ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR_OFF 0
|
||||||
|
#define ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75 2
|
||||||
|
|
||||||
|
#define ZL_REG_REF_ESYNC_DIV ZL_REG(10, 0x30, 4)
|
||||||
|
#define ZL_REF_ESYNC_DIV_1HZ 0
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Register Page 12, DPLL Mailbox
|
||||||
|
********************************/
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_MB_MASK ZL_REG(12, 0x02, 2)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_MB_SEM ZL_REG(12, 0x04, 1)
|
||||||
|
#define ZL_DPLL_MB_SEM_WR BIT(0)
|
||||||
|
#define ZL_DPLL_MB_SEM_RD BIT(1)
|
||||||
|
|
||||||
|
#define ZL_REG_DPLL_REF_PRIO(_idx) \
|
||||||
|
ZL_REG_IDX(_idx, 12, 0x52, 1, ZL3073X_NUM_REFS / 2, 1)
|
||||||
|
#define ZL_DPLL_REF_PRIO_REF_P GENMASK(3, 0)
|
||||||
|
#define ZL_DPLL_REF_PRIO_REF_N GENMASK(7, 4)
|
||||||
|
#define ZL_DPLL_REF_PRIO_MAX 14
|
||||||
|
#define ZL_DPLL_REF_PRIO_NONE 15
|
||||||
|
|
||||||
|
/*********************************
|
||||||
|
* Register Page 13, Synth Mailbox
|
||||||
|
*********************************/
|
||||||
|
|
||||||
|
#define ZL_REG_SYNTH_MB_MASK ZL_REG(13, 0x02, 2)
|
||||||
|
|
||||||
|
#define ZL_REG_SYNTH_MB_SEM ZL_REG(13, 0x04, 1)
|
||||||
|
#define ZL_SYNTH_MB_SEM_WR BIT(0)
|
||||||
|
#define ZL_SYNTH_MB_SEM_RD BIT(1)
|
||||||
|
|
||||||
|
#define ZL_REG_SYNTH_FREQ_BASE ZL_REG(13, 0x06, 2)
|
||||||
|
#define ZL_REG_SYNTH_FREQ_MULT ZL_REG(13, 0x08, 4)
|
||||||
|
#define ZL_REG_SYNTH_FREQ_M ZL_REG(13, 0x0c, 2)
|
||||||
|
#define ZL_REG_SYNTH_FREQ_N ZL_REG(13, 0x0e, 2)
|
||||||
|
|
||||||
|
/**********************************
|
||||||
|
* Register Page 14, Output Mailbox
|
||||||
|
**********************************/
|
||||||
|
#define ZL_REG_OUTPUT_MB_MASK ZL_REG(14, 0x02, 2)
|
||||||
|
|
||||||
|
#define ZL_REG_OUTPUT_MB_SEM ZL_REG(14, 0x04, 1)
|
||||||
|
#define ZL_OUTPUT_MB_SEM_WR BIT(0)
|
||||||
|
#define ZL_OUTPUT_MB_SEM_RD BIT(1)
|
||||||
|
|
||||||
|
#define ZL_REG_OUTPUT_MODE ZL_REG(14, 0x05, 1)
|
||||||
|
#define ZL_OUTPUT_MODE_CLOCK_TYPE GENMASK(2, 0)
|
||||||
|
#define ZL_OUTPUT_MODE_CLOCK_TYPE_NORMAL 0
|
||||||
|
#define ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC 1
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT GENMASK(7, 4)
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED 0
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS 1
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_DIFF 2
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_LOWVCM 3
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2 4
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P 5
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N 6
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_INV 7
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV 12
|
||||||
|
#define ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV 15
|
||||||
|
|
||||||
|
#define ZL_REG_OUTPUT_DIV ZL_REG(14, 0x0c, 4)
|
||||||
|
#define ZL_REG_OUTPUT_WIDTH ZL_REG(14, 0x10, 4)
|
||||||
|
#define ZL_REG_OUTPUT_ESYNC_PERIOD ZL_REG(14, 0x14, 4)
|
||||||
|
#define ZL_REG_OUTPUT_ESYNC_WIDTH ZL_REG(14, 0x18, 4)
|
||||||
|
#define ZL_REG_OUTPUT_PHASE_COMP ZL_REG(14, 0x20, 4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register Page 255 - HW registers access
|
||||||
|
*/
|
||||||
|
#define ZL_REG_HWREG_OP ZL_REG(0xff, 0x00, 1)
|
||||||
|
#define ZL_HWREG_OP_WRITE 0x28
|
||||||
|
#define ZL_HWREG_OP_READ 0x29
|
||||||
|
#define ZL_HWREG_OP_PENDING BIT(1)
|
||||||
|
|
||||||
|
#define ZL_REG_HWREG_ADDR ZL_REG(0xff, 0x04, 4)
|
||||||
|
#define ZL_REG_HWREG_WRITE_DATA ZL_REG(0xff, 0x08, 4)
|
||||||
|
#define ZL_REG_HWREG_READ_DATA ZL_REG(0xff, 0x0c, 4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Registers available in flash mode
|
||||||
|
*/
|
||||||
|
#define ZL_REG_FLASH_HASH ZL_REG(0, 0x78, 4)
|
||||||
|
#define ZL_REG_FLASH_FAMILY ZL_REG(0, 0x7c, 1)
|
||||||
|
#define ZL_REG_FLASH_RELEASE ZL_REG(0, 0x7d, 1)
|
||||||
|
|
||||||
|
#define ZL_REG_HOST_CONTROL ZL_REG(1, 0x02, 1)
|
||||||
|
#define ZL_HOST_CONTROL_ENABLE BIT(0)
|
||||||
|
|
||||||
|
#define ZL_REG_IMAGE_START_ADDR ZL_REG(1, 0x04, 4)
|
||||||
|
#define ZL_REG_IMAGE_SIZE ZL_REG(1, 0x08, 4)
|
||||||
|
#define ZL_REG_FLASH_INDEX_READ ZL_REG(1, 0x0c, 4)
|
||||||
|
#define ZL_REG_FLASH_INDEX_WRITE ZL_REG(1, 0x10, 4)
|
||||||
|
#define ZL_REG_FILL_PATTERN ZL_REG(1, 0x14, 4)
|
||||||
|
|
||||||
|
#define ZL_REG_WRITE_FLASH ZL_REG(1, 0x18, 1)
|
||||||
|
#define ZL_WRITE_FLASH_OP GENMASK(2, 0)
|
||||||
|
#define ZL_WRITE_FLASH_OP_DONE 0x0
|
||||||
|
#define ZL_WRITE_FLASH_OP_SECTORS 0x2
|
||||||
|
#define ZL_WRITE_FLASH_OP_PAGE 0x3
|
||||||
|
#define ZL_WRITE_FLASH_OP_COPY_PAGE 0x4
|
||||||
|
|
||||||
|
#define ZL_REG_FLASH_INFO ZL_REG(2, 0x00, 1)
|
||||||
|
#define ZL_FLASH_INFO_SECTOR_SIZE GENMASK(3, 0)
|
||||||
|
#define ZL_FLASH_INFO_SECTOR_4K 0
|
||||||
|
#define ZL_FLASH_INFO_SECTOR_64K 1
|
||||||
|
|
||||||
|
#define ZL_REG_ERROR_COUNT ZL_REG(2, 0x04, 4)
|
||||||
|
#define ZL_REG_ERROR_CAUSE ZL_REG(2, 0x08, 4)
|
||||||
|
|
||||||
|
#define ZL_REG_OP_STATE ZL_REG(2, 0x14, 1)
|
||||||
|
#define ZL_OP_STATE_NO_COMMAND 0
|
||||||
|
#define ZL_OP_STATE_PENDING 1
|
||||||
|
#define ZL_OP_STATE_DONE 2
|
||||||
|
|
||||||
|
#endif /* _ZL3073X_REGS_H */
|
||||||
76
drivers/dpll/zl3073x/spi.c
Normal file
76
drivers/dpll/zl3073x/spi.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include <linux/dev_printk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
|
||||||
|
static int zl3073x_spi_probe(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct device *dev = &spi->dev;
|
||||||
|
struct zl3073x_dev *zldev;
|
||||||
|
|
||||||
|
zldev = zl3073x_devm_alloc(dev);
|
||||||
|
if (IS_ERR(zldev))
|
||||||
|
return PTR_ERR(zldev);
|
||||||
|
|
||||||
|
zldev->regmap = devm_regmap_init_spi(spi, &zl3073x_regmap_config);
|
||||||
|
if (IS_ERR(zldev->regmap))
|
||||||
|
return dev_err_probe(dev, PTR_ERR(zldev->regmap),
|
||||||
|
"Failed to initialize regmap\n");
|
||||||
|
|
||||||
|
return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct spi_device_id zl3073x_spi_id[] = {
|
||||||
|
{
|
||||||
|
.name = "zl30731",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30731_chip_info
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30732",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30732_chip_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30733",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30733_chip_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30734",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30734_chip_info,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "zl30735",
|
||||||
|
.driver_data = (kernel_ulong_t)&zl30735_chip_info,
|
||||||
|
},
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(spi, zl3073x_spi_id);
|
||||||
|
|
||||||
|
static const struct of_device_id zl3073x_spi_of_match[] = {
|
||||||
|
{ .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
|
||||||
|
{ .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, zl3073x_spi_of_match);
|
||||||
|
|
||||||
|
static struct spi_driver zl3073x_spi_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "zl3073x-spi",
|
||||||
|
.of_match_table = zl3073x_spi_of_match,
|
||||||
|
},
|
||||||
|
.probe = zl3073x_spi_probe,
|
||||||
|
.id_table = zl3073x_spi_id,
|
||||||
|
};
|
||||||
|
module_spi_driver(zl3073x_spi_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Ivan Vecera <ivecera@redhat.com>");
|
||||||
|
MODULE_DESCRIPTION("Microchip ZL3073x SPI driver");
|
||||||
|
MODULE_IMPORT_NS(ZL3073X);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
@ -1124,11 +1124,24 @@ static int octep_set_features(struct net_device *dev, netdev_features_t features
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool octep_is_vf_valid(struct octep_device *oct, int vf)
|
||||||
|
{
|
||||||
|
if (vf >= CFG_GET_ACTIVE_VFS(oct->conf)) {
|
||||||
|
netdev_err(oct->netdev, "Invalid VF ID %d\n", vf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int octep_get_vf_config(struct net_device *dev, int vf,
|
static int octep_get_vf_config(struct net_device *dev, int vf,
|
||||||
struct ifla_vf_info *ivi)
|
struct ifla_vf_info *ivi)
|
||||||
{
|
{
|
||||||
struct octep_device *oct = netdev_priv(dev);
|
struct octep_device *oct = netdev_priv(dev);
|
||||||
|
|
||||||
|
if (!octep_is_vf_valid(oct, vf))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
ivi->vf = vf;
|
ivi->vf = vf;
|
||||||
ether_addr_copy(ivi->mac, oct->vf_info[vf].mac_addr);
|
ether_addr_copy(ivi->mac, oct->vf_info[vf].mac_addr);
|
||||||
ivi->spoofchk = true;
|
ivi->spoofchk = true;
|
||||||
@ -1143,6 +1156,9 @@ static int octep_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
|
|||||||
struct octep_device *oct = netdev_priv(dev);
|
struct octep_device *oct = netdev_priv(dev);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (!octep_is_vf_valid(oct, vf))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (!is_valid_ether_addr(mac)) {
|
if (!is_valid_ether_addr(mac)) {
|
||||||
dev_err(&oct->pdev->dev, "Invalid MAC Address %pM\n", mac);
|
dev_err(&oct->pdev->dev, "Invalid MAC Address %pM\n", mac);
|
||||||
return -EADDRNOTAVAIL;
|
return -EADDRNOTAVAIL;
|
||||||
|
|||||||
@ -658,7 +658,7 @@ static void del_sw_hw_rule(struct fs_node *node)
|
|||||||
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) |
|
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) |
|
||||||
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
|
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
|
||||||
fte->act_dests.action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
fte->act_dests.action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||||
mlx5_fc_local_destroy(rule->dest_attr.counter);
|
mlx5_fc_local_put(rule->dest_attr.counter);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -345,6 +345,7 @@ struct mlx5_fc {
|
|||||||
/* last{packets,bytes} are used for calculating deltas since last reading. */
|
/* last{packets,bytes} are used for calculating deltas since last reading. */
|
||||||
u64 lastpackets;
|
u64 lastpackets;
|
||||||
u64 lastbytes;
|
u64 lastbytes;
|
||||||
|
RH_KABI_EXTEND(refcount_t fc_local_refcount)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mlx5_fc_bulk {
|
struct mlx5_fc_bulk {
|
||||||
|
|||||||
@ -562,17 +562,36 @@ mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size)
|
|||||||
counter->id = counter_id;
|
counter->id = counter_id;
|
||||||
fc_bulk->base_id = counter_id - offset;
|
fc_bulk->base_id = counter_id - offset;
|
||||||
fc_bulk->fs_bulk.bulk_len = bulk_size;
|
fc_bulk->fs_bulk.bulk_len = bulk_size;
|
||||||
|
refcount_set(&fc_bulk->hws_data.hws_action_refcount, 0);
|
||||||
|
mutex_init(&fc_bulk->hws_data.lock);
|
||||||
counter->bulk = fc_bulk;
|
counter->bulk = fc_bulk;
|
||||||
|
refcount_set(&counter->fc_local_refcount, 1);
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mlx5_fc_local_create);
|
EXPORT_SYMBOL(mlx5_fc_local_create);
|
||||||
|
|
||||||
void mlx5_fc_local_destroy(struct mlx5_fc *counter)
|
void mlx5_fc_local_destroy(struct mlx5_fc *counter)
|
||||||
{
|
{
|
||||||
if (!counter || counter->type != MLX5_FC_TYPE_LOCAL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
kfree(counter->bulk);
|
kfree(counter->bulk);
|
||||||
kfree(counter);
|
kfree(counter);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mlx5_fc_local_destroy);
|
EXPORT_SYMBOL(mlx5_fc_local_destroy);
|
||||||
|
|
||||||
|
void mlx5_fc_local_get(struct mlx5_fc *counter)
|
||||||
|
{
|
||||||
|
if (!counter || counter->type != MLX5_FC_TYPE_LOCAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
refcount_inc(&counter->fc_local_refcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx5_fc_local_put(struct mlx5_fc *counter)
|
||||||
|
{
|
||||||
|
if (!counter || counter->type != MLX5_FC_TYPE_LOCAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!refcount_dec_and_test(&counter->fc_local_refcount))
|
||||||
|
return;
|
||||||
|
|
||||||
|
mlx5_fc_local_destroy(counter);
|
||||||
|
}
|
||||||
|
|||||||
@ -407,15 +407,21 @@ struct mlx5hws_action *mlx5_fc_get_hws_action(struct mlx5hws_context *ctx,
|
|||||||
{
|
{
|
||||||
struct mlx5_fs_hws_create_action_ctx create_ctx;
|
struct mlx5_fs_hws_create_action_ctx create_ctx;
|
||||||
struct mlx5_fc_bulk *fc_bulk = counter->bulk;
|
struct mlx5_fc_bulk *fc_bulk = counter->bulk;
|
||||||
|
struct mlx5hws_action *hws_action;
|
||||||
|
|
||||||
create_ctx.hws_ctx = ctx;
|
create_ctx.hws_ctx = ctx;
|
||||||
create_ctx.id = fc_bulk->base_id;
|
create_ctx.id = fc_bulk->base_id;
|
||||||
create_ctx.actions_type = MLX5HWS_ACTION_TYP_CTR;
|
create_ctx.actions_type = MLX5HWS_ACTION_TYP_CTR;
|
||||||
|
|
||||||
return mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx);
|
mlx5_fc_local_get(counter);
|
||||||
|
hws_action = mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx);
|
||||||
|
if (!hws_action)
|
||||||
|
mlx5_fc_local_put(counter);
|
||||||
|
return hws_action;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mlx5_fc_put_hws_action(struct mlx5_fc *counter)
|
void mlx5_fc_put_hws_action(struct mlx5_fc *counter)
|
||||||
{
|
{
|
||||||
mlx5_fs_put_hws_action(&counter->bulk->hws_data);
|
mlx5_fs_put_hws_action(&counter->bulk->hws_data);
|
||||||
|
mlx5_fc_local_put(counter);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -360,6 +360,18 @@ const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(spi_get_device_id);
|
EXPORT_SYMBOL_GPL(spi_get_device_id);
|
||||||
|
|
||||||
|
const void *spi_get_device_match_data(const struct spi_device *sdev)
|
||||||
|
{
|
||||||
|
const void *match;
|
||||||
|
|
||||||
|
match = device_get_match_data(&sdev->dev);
|
||||||
|
if (match)
|
||||||
|
return match;
|
||||||
|
|
||||||
|
return (const void *)spi_get_device_id(sdev)->driver_data;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(spi_get_device_match_data);
|
||||||
|
|
||||||
static int spi_match_device(struct device *dev, struct device_driver *drv)
|
static int spi_match_device(struct device *dev, struct device_driver *drv)
|
||||||
{
|
{
|
||||||
const struct spi_device *spi = to_spi_device(dev);
|
const struct spi_device *spi = to_spi_device(dev);
|
||||||
|
|||||||
0
include/config/ZL3073X
Normal file
0
include/config/ZL3073X
Normal file
0
include/config/ZL3073X_I2C
Normal file
0
include/config/ZL3073X_I2C
Normal file
0
include/config/ZL3073X_SPI
Normal file
0
include/config/ZL3073X_SPI
Normal file
@ -27,6 +27,7 @@ CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
|
|||||||
CONFIG_RTLBTCOEXIST=m
|
CONFIG_RTLBTCOEXIST=m
|
||||||
CONFIG_NFT_NAT=m
|
CONFIG_NFT_NAT=m
|
||||||
CONFIG_POLYNOMIAL=m
|
CONFIG_POLYNOMIAL=m
|
||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
CONFIG_ZRAM_WRITEBACK=y
|
CONFIG_ZRAM_WRITEBACK=y
|
||||||
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
|
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
|
||||||
CONFIG_INPUT_KEYBOARD=y
|
CONFIG_INPUT_KEYBOARD=y
|
||||||
@ -925,6 +926,7 @@ CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y
|
|||||||
CONFIG_CB710_DEBUG_ASSUMPTIONS=y
|
CONFIG_CB710_DEBUG_ASSUMPTIONS=y
|
||||||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
CONFIG_SPLIT_PTLOCK_CPUS=4
|
||||||
CONFIG_SBITMAP=y
|
CONFIG_SBITMAP=y
|
||||||
|
CONFIG_ZL3073X=m
|
||||||
CONFIG_IMX_INTMUX=y
|
CONFIG_IMX_INTMUX=y
|
||||||
CONFIG_MSPRO_BLOCK=m
|
CONFIG_MSPRO_BLOCK=m
|
||||||
CONFIG_GPIO_XLP=m
|
CONFIG_GPIO_XLP=m
|
||||||
@ -2949,6 +2951,7 @@ CONFIG_IPV6_OPTIMISTIC_DAD=y
|
|||||||
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
|
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
|
||||||
CONFIG_NETFS_SUPPORT=m
|
CONFIG_NETFS_SUPPORT=m
|
||||||
CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
|
CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
|
||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
CONFIG_MD_AUTODETECT=y
|
CONFIG_MD_AUTODETECT=y
|
||||||
CONFIG_PANIC_ON_OOPS_VALUE=1
|
CONFIG_PANIC_ON_OOPS_VALUE=1
|
||||||
CONFIG_PLDMFW=y
|
CONFIG_PLDMFW=y
|
||||||
|
|||||||
@ -146,7 +146,6 @@ deps_config := \
|
|||||||
fs/ext4/Kconfig \
|
fs/ext4/Kconfig \
|
||||||
fs/ext2/Kconfig \
|
fs/ext2/Kconfig \
|
||||||
fs/Kconfig \
|
fs/Kconfig \
|
||||||
drivers/dpll/Kconfig \
|
|
||||||
drivers/hte/Kconfig \
|
drivers/hte/Kconfig \
|
||||||
drivers/most/Kconfig \
|
drivers/most/Kconfig \
|
||||||
drivers/counter/Kconfig \
|
drivers/counter/Kconfig \
|
||||||
@ -934,6 +933,8 @@ deps_config := \
|
|||||||
drivers/pinctrl/aspeed/Kconfig \
|
drivers/pinctrl/aspeed/Kconfig \
|
||||||
drivers/pinctrl/actions/Kconfig \
|
drivers/pinctrl/actions/Kconfig \
|
||||||
drivers/pinctrl/Kconfig \
|
drivers/pinctrl/Kconfig \
|
||||||
|
drivers/dpll/zl3073x/Kconfig \
|
||||||
|
drivers/dpll/Kconfig \
|
||||||
drivers/ptp/Kconfig \
|
drivers/ptp/Kconfig \
|
||||||
drivers/pps/generators/Kconfig \
|
drivers/pps/generators/Kconfig \
|
||||||
drivers/pps/clients/Kconfig \
|
drivers/pps/clients/Kconfig \
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
#define CONFIG_RTLBTCOEXIST_MODULE 1
|
#define CONFIG_RTLBTCOEXIST_MODULE 1
|
||||||
#define CONFIG_NFT_NAT_MODULE 1
|
#define CONFIG_NFT_NAT_MODULE 1
|
||||||
#define CONFIG_POLYNOMIAL_MODULE 1
|
#define CONFIG_POLYNOMIAL_MODULE 1
|
||||||
|
#define CONFIG_ZL3073X_SPI_MODULE 1
|
||||||
#define CONFIG_ZRAM_WRITEBACK 1
|
#define CONFIG_ZRAM_WRITEBACK 1
|
||||||
#define CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK 1
|
#define CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK 1
|
||||||
#define CONFIG_INPUT_KEYBOARD 1
|
#define CONFIG_INPUT_KEYBOARD 1
|
||||||
@ -927,6 +928,7 @@
|
|||||||
#define CONFIG_CB710_DEBUG_ASSUMPTIONS 1
|
#define CONFIG_CB710_DEBUG_ASSUMPTIONS 1
|
||||||
#define CONFIG_SPLIT_PTLOCK_CPUS 4
|
#define CONFIG_SPLIT_PTLOCK_CPUS 4
|
||||||
#define CONFIG_SBITMAP 1
|
#define CONFIG_SBITMAP 1
|
||||||
|
#define CONFIG_ZL3073X_MODULE 1
|
||||||
#define CONFIG_IMX_INTMUX 1
|
#define CONFIG_IMX_INTMUX 1
|
||||||
#define CONFIG_MSPRO_BLOCK_MODULE 1
|
#define CONFIG_MSPRO_BLOCK_MODULE 1
|
||||||
#define CONFIG_GPIO_XLP_MODULE 1
|
#define CONFIG_GPIO_XLP_MODULE 1
|
||||||
@ -2951,6 +2953,7 @@
|
|||||||
#define CONFIG_ARCH_HAS_ELF_RANDOMIZE 1
|
#define CONFIG_ARCH_HAS_ELF_RANDOMIZE 1
|
||||||
#define CONFIG_NETFS_SUPPORT_MODULE 1
|
#define CONFIG_NETFS_SUPPORT_MODULE 1
|
||||||
#define CONFIG_HAVE_FUNCTION_ARG_ACCESS_API 1
|
#define CONFIG_HAVE_FUNCTION_ARG_ACCESS_API 1
|
||||||
|
#define CONFIG_ZL3073X_I2C_MODULE 1
|
||||||
#define CONFIG_MD_AUTODETECT 1
|
#define CONFIG_MD_AUTODETECT 1
|
||||||
#define CONFIG_PANIC_ON_OOPS_VALUE 1
|
#define CONFIG_PANIC_ON_OOPS_VALUE 1
|
||||||
#define CONFIG_PLDMFW 1
|
#define CONFIG_PLDMFW 1
|
||||||
|
|||||||
@ -308,6 +308,8 @@ struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
|
|||||||
void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
|
void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
|
||||||
struct mlx5_fc *mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size);
|
struct mlx5_fc *mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size);
|
||||||
void mlx5_fc_local_destroy(struct mlx5_fc *counter);
|
void mlx5_fc_local_destroy(struct mlx5_fc *counter);
|
||||||
|
void mlx5_fc_local_get(struct mlx5_fc *counter);
|
||||||
|
void mlx5_fc_local_put(struct mlx5_fc *counter);
|
||||||
u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
|
u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
|
||||||
void mlx5_fc_query_cached(struct mlx5_fc *counter,
|
void mlx5_fc_query_cached(struct mlx5_fc *counter,
|
||||||
u64 *bytes, u64 *packets, u64 *lastuse);
|
u64 *bytes, u64 *packets, u64 *lastuse);
|
||||||
|
|||||||
@ -1590,6 +1590,9 @@ extern void spi_unregister_device(struct spi_device *spi);
|
|||||||
extern const struct spi_device_id *
|
extern const struct spi_device_id *
|
||||||
spi_get_device_id(const struct spi_device *sdev);
|
spi_get_device_id(const struct spi_device *sdev);
|
||||||
|
|
||||||
|
extern const void *
|
||||||
|
spi_get_device_match_data(const struct spi_device *sdev);
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer)
|
spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -212,6 +212,7 @@ void j1939_priv_get(struct j1939_priv *priv);
|
|||||||
|
|
||||||
/* notify/alert all j1939 sockets bound to ifindex */
|
/* notify/alert all j1939 sockets bound to ifindex */
|
||||||
void j1939_sk_netdev_event_netdown(struct j1939_priv *priv);
|
void j1939_sk_netdev_event_netdown(struct j1939_priv *priv);
|
||||||
|
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv);
|
||||||
int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk);
|
int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk);
|
||||||
void j1939_tp_init(struct j1939_priv *priv);
|
void j1939_tp_init(struct j1939_priv *priv);
|
||||||
|
|
||||||
|
|||||||
@ -381,6 +381,11 @@ static int j1939_netdev_notify(struct notifier_block *nb,
|
|||||||
j1939_sk_netdev_event_netdown(priv);
|
j1939_sk_netdev_event_netdown(priv);
|
||||||
j1939_ecu_unmap_all(priv);
|
j1939_ecu_unmap_all(priv);
|
||||||
break;
|
break;
|
||||||
|
case NETDEV_UNREGISTER:
|
||||||
|
j1939_cancel_active_session(priv, NULL);
|
||||||
|
j1939_sk_netdev_event_netdown(priv);
|
||||||
|
j1939_sk_netdev_event_unregister(priv);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
j1939_priv_put(priv);
|
j1939_priv_put(priv);
|
||||||
|
|||||||
@ -1296,6 +1296,55 @@ void j1939_sk_netdev_event_netdown(struct j1939_priv *priv)
|
|||||||
read_unlock_bh(&priv->j1939_socks_lock);
|
read_unlock_bh(&priv->j1939_socks_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void j1939_sk_netdev_event_unregister(struct j1939_priv *priv)
|
||||||
|
{
|
||||||
|
struct sock *sk;
|
||||||
|
struct j1939_sock *jsk;
|
||||||
|
bool wait_rcu = false;
|
||||||
|
|
||||||
|
rescan: /* The caller is holding a ref on this "priv" via j1939_priv_get_by_ndev(). */
|
||||||
|
read_lock_bh(&priv->j1939_socks_lock);
|
||||||
|
list_for_each_entry(jsk, &priv->j1939_socks, list) {
|
||||||
|
/* Skip if j1939_jsk_add() is not called on this socket. */
|
||||||
|
if (!(jsk->state & J1939_SOCK_BOUND))
|
||||||
|
continue;
|
||||||
|
sk = &jsk->sk;
|
||||||
|
sock_hold(sk);
|
||||||
|
read_unlock_bh(&priv->j1939_socks_lock);
|
||||||
|
/* Check if j1939_jsk_del() is not yet called on this socket after holding
|
||||||
|
* socket's lock, for both j1939_sk_bind() and j1939_sk_release() call
|
||||||
|
* j1939_jsk_del() with socket's lock held.
|
||||||
|
*/
|
||||||
|
lock_sock(sk);
|
||||||
|
if (jsk->state & J1939_SOCK_BOUND) {
|
||||||
|
/* Neither j1939_sk_bind() nor j1939_sk_release() called j1939_jsk_del().
|
||||||
|
* Make this socket no longer bound, by pretending as if j1939_sk_bind()
|
||||||
|
* dropped old references but did not get new references.
|
||||||
|
*/
|
||||||
|
j1939_jsk_del(priv, jsk);
|
||||||
|
j1939_local_ecu_put(priv, jsk->addr.src_name, jsk->addr.sa);
|
||||||
|
j1939_netdev_stop(priv);
|
||||||
|
/* Call j1939_priv_put() now and prevent j1939_sk_sock_destruct() from
|
||||||
|
* calling the corresponding j1939_priv_put().
|
||||||
|
*
|
||||||
|
* j1939_sk_sock_destruct() is supposed to call j1939_priv_put() after
|
||||||
|
* an RCU grace period. But since the caller is holding a ref on this
|
||||||
|
* "priv", we can defer synchronize_rcu() until immediately before
|
||||||
|
* the caller calls j1939_priv_put().
|
||||||
|
*/
|
||||||
|
j1939_priv_put(priv);
|
||||||
|
jsk->priv = NULL;
|
||||||
|
wait_rcu = true;
|
||||||
|
}
|
||||||
|
release_sock(sk);
|
||||||
|
sock_put(sk);
|
||||||
|
goto rescan;
|
||||||
|
}
|
||||||
|
read_unlock_bh(&priv->j1939_socks_lock);
|
||||||
|
if (wait_rcu)
|
||||||
|
synchronize_rcu();
|
||||||
|
}
|
||||||
|
|
||||||
static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
|
static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
|
|||||||
1
redhat/configs/common/generic/CONFIG_ZL3073X
Normal file
1
redhat/configs/common/generic/CONFIG_ZL3073X
Normal file
@ -0,0 +1 @@
|
|||||||
|
CONFIG_ZL3073X=m
|
||||||
1
redhat/configs/common/generic/CONFIG_ZL3073X_I2C
Normal file
1
redhat/configs/common/generic/CONFIG_ZL3073X_I2C
Normal file
@ -0,0 +1 @@
|
|||||||
|
CONFIG_ZL3073X_I2C=m
|
||||||
1
redhat/configs/common/generic/CONFIG_ZL3073X_SPI
Normal file
1
redhat/configs/common/generic/CONFIG_ZL3073X_SPI
Normal file
@ -0,0 +1 @@
|
|||||||
|
CONFIG_ZL3073X_SPI=m
|
||||||
1
redhat/configs/common/generic/s390x/CONFIG_ZL3073X
Normal file
1
redhat/configs/common/generic/s390x/CONFIG_ZL3073X
Normal file
@ -0,0 +1 @@
|
|||||||
|
# CONFIG_ZL3073X is not set
|
||||||
1
redhat/configs/common/generic/s390x/CONFIG_ZL3073X_I2C
Normal file
1
redhat/configs/common/generic/s390x/CONFIG_ZL3073X_I2C
Normal file
@ -0,0 +1 @@
|
|||||||
|
# CONFIG_ZL3073X_I2C is not set
|
||||||
1
redhat/configs/common/generic/s390x/CONFIG_ZL3073X_SPI
Normal file
1
redhat/configs/common/generic/s390x/CONFIG_ZL3073X_SPI
Normal file
@ -0,0 +1 @@
|
|||||||
|
# CONFIG_ZL3073X_SPI is not set
|
||||||
1
redhat/configs/common/generic/x86/CONFIG_I2C_MUX_PCA954x
Normal file
1
redhat/configs/common/generic/x86/CONFIG_I2C_MUX_PCA954x
Normal file
@ -0,0 +1 @@
|
|||||||
|
CONFIG_I2C_MUX_PCA954x=m
|
||||||
@ -1,3 +1,45 @@
|
|||||||
|
* Sat Nov 29 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-611.13.1.el9_7]
|
||||||
|
- can: j1939: add missing calls in NETDEV_UNREGISTER notification handler (CKI Backport Bot) [RHEL-124105] {CVE-2025-39925}
|
||||||
|
- can: j1939: implement NETDEV_UNREGISTER notification handler (CKI Backport Bot) [RHEL-124105] {CVE-2025-39925}
|
||||||
|
Resolves: RHEL-124105
|
||||||
|
|
||||||
|
* Thu Nov 27 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-611.12.1.el9_7]
|
||||||
|
- x86/hyperv: Fix kdump on Azure CVMs (Li Tian) [RHEL-129776]
|
||||||
|
- net/mlx5: fs, fix UAF in flow counter release (Michal Schmidt) [RHEL-124428] {CVE-2025-39979}
|
||||||
|
- octeon_ep: Validate the VF ID (Kamal Heib) [RHEL-117604]
|
||||||
|
- dpll: zl3073x: fix kernel-doc name and missing parameter in fw.c (Ivan Vecera) [RHEL-116162]
|
||||||
|
- dpll: zl3073x: Fix output pin registration (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Increase maximum size of flash utility (Ivan Vecera) [RHEL-116162]
|
||||||
|
- dpll: zl3073x: Fix double free in zl3073x_devlink_flash_update() (Ivan Vecera) [RHEL-116162]
|
||||||
|
- dpll: zl3073x: Implement devlink flash callback (Ivan Vecera) [RHEL-116162]
|
||||||
|
- dpll: zl3073x: Add firmware loading functionality (Ivan Vecera) [RHEL-116162]
|
||||||
|
- dpll: zl3073x: Add low-level flash functions (Ivan Vecera) [RHEL-116162]
|
||||||
|
- dpll: zl3073x: Add functions to access hardware registers (Ivan Vecera) [RHEL-116162]
|
||||||
|
- dpll: zl3073x: Handle missing or corrupted flash configuration (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Refactor DPLL initialization (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: ZL3073X_I2C and ZL3073X_SPI should depend on NET (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: Make ZL3073X invisible (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Fix build failure (Ivan Vecera) [RHEL-113083]
|
||||||
|
- redhat/configs: enable CONFIG_ZL3073X* (Ivan Vecera) [RHEL-113083]
|
||||||
|
- redhat/configs: enable CONFIG_I2C_MUX_PCA954x on x86 (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Add support to get fractional frequency offset (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Add support to adjust phase (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Implement phase offset monitor feature (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Add support to get phase offset on connected input pin (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Add support to get/set esync on pins (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Add support to get/set frequency on pins (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Implement input pin state setting in automatic mode (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Add support to get/set priority on input pins (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Implement input pin selection in manual mode (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Register DPLL devices and pins (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Read DPLL types and pin properties from system firmware (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: zl3073x: Fetch invariants during probe (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dpll: Add basic Microchip ZL3073x support (Ivan Vecera) [RHEL-113083]
|
||||||
|
- spi: Introduce spi_get_device_match_data() helper (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dt-bindings: dpll: Add support for Microchip Azurite chip family (Ivan Vecera) [RHEL-113083]
|
||||||
|
- dt-bindings: dpll: Add DPLL device and pin (Ivan Vecera) [RHEL-113083]
|
||||||
|
Resolves: RHEL-113083, RHEL-116162, RHEL-117604, RHEL-124428, RHEL-129776
|
||||||
|
|
||||||
* Tue Nov 25 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-611.11.1.el9_7]
|
* Tue Nov 25 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-611.11.1.el9_7]
|
||||||
- tcp: Don't call reqsk_fastopen_remove() in tcp_conn_request(). (Antoine Tenart) [RHEL-120668]
|
- tcp: Don't call reqsk_fastopen_remove() in tcp_conn_request(). (Antoine Tenart) [RHEL-120668]
|
||||||
- tcp: Clear tcp_sk(sk)->fastopen_rsk in tcp_disconnect(). (Antoine Tenart) [RHEL-120668] {CVE-2025-39955}
|
- tcp: Clear tcp_sk(sk)->fastopen_rsk in tcp_disconnect(). (Antoine Tenart) [RHEL-120668] {CVE-2025-39955}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user