mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 20:32:04 +09:00
Merge 24f7cf9b85 ("Merge tag 'mac80211-next-for-net-next-2021-10-21' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next") into android-mainline
Steps on the way to 5.16-rc1 Resolves conflicts in: include/net/sock.h Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I65e908f7cb0a0588b4eb37afb0ce221981d0aab5
This commit is contained in:
73
Documentation/devicetree/bindings/net/asix,ax88796c.yaml
Normal file
73
Documentation/devicetree/bindings/net/asix,ax88796c.yaml
Normal file
@@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/asix,ax88796c.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ASIX AX88796C SPI Ethernet Adapter
|
||||
|
||||
maintainers:
|
||||
- Łukasz Stelmach <l.stelmach@samsung.com>
|
||||
|
||||
description: |
|
||||
ASIX AX88796C is an Ethernet controller with a built in PHY. This
|
||||
describes SPI mode of the chip.
|
||||
|
||||
The node for this driver must be a child node of an SPI controller,
|
||||
hence all mandatory properties described in
|
||||
../spi/spi-controller.yaml must be specified.
|
||||
|
||||
allOf:
|
||||
- $ref: ethernet-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: asix,ax88796c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 40000000
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
A GPIO line handling reset of the chip. As the line is active low,
|
||||
it should be marked GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
local-mac-address: true
|
||||
|
||||
mac-address: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- spi-max-frequency
|
||||
- interrupts
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Artik5 eval board
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethernet@0 {
|
||||
compatible = "asix,ax88796c";
|
||||
reg = <0x0>;
|
||||
local-mac-address = [00 00 00 00 00 00]; /* Filled in by a bootloader */
|
||||
interrupt-parent = <&gpx2>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
||||
spi-max-frequency = <40000000>;
|
||||
reset-gpios = <&gpe0 2 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
@@ -46,6 +46,9 @@ patternProperties:
|
||||
type: object
|
||||
description: Ethernet switch ports
|
||||
|
||||
allOf:
|
||||
- $ref: "http://devicetree.org/schemas/net/ethernet-controller.yaml#"
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: Port number
|
||||
@@ -73,11 +76,14 @@ patternProperties:
|
||||
dsa-tag-protocol:
|
||||
description:
|
||||
Instead of the default, the switch will use this tag protocol if
|
||||
possible. Useful when a device supports multiple protcols and
|
||||
possible. Useful when a device supports multiple protocols and
|
||||
the default is incompatible with the Ethernet device.
|
||||
enum:
|
||||
- dsa
|
||||
- edsa
|
||||
- ocelot
|
||||
- ocelot-8021q
|
||||
- seville
|
||||
|
||||
phy-handle: true
|
||||
|
||||
@@ -91,6 +97,10 @@ patternProperties:
|
||||
|
||||
managed: true
|
||||
|
||||
rx-internal-delay-ps: true
|
||||
|
||||
tx-internal-delay-ps: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
|
||||
@@ -74,10 +74,42 @@ properties:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
patternProperties:
|
||||
"^(ethernet-)?ports$":
|
||||
patternProperties:
|
||||
"^(ethernet-)?port@[0-9]+$":
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
phy-mode:
|
||||
contains:
|
||||
enum:
|
||||
- rgmii
|
||||
- rgmii-rxid
|
||||
- rgmii-txid
|
||||
- rgmii-id
|
||||
then:
|
||||
properties:
|
||||
rx-internal-delay-ps:
|
||||
$ref: "#/$defs/internal-delay-ps"
|
||||
tx-internal-delay-ps:
|
||||
$ref: "#/$defs/internal-delay-ps"
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
$defs:
|
||||
internal-delay-ps:
|
||||
description:
|
||||
Disable tunable delay lines using 0 ps, or enable them and select
|
||||
the phase between 1640 ps (73.8 degree shift at 1Gbps) and 2260 ps
|
||||
(101.7 degree shift) in increments of 0.9 degrees (20 ps).
|
||||
enum:
|
||||
[0, 1640, 1660, 1680, 1700, 1720, 1740, 1760, 1780, 1800, 1820, 1840,
|
||||
1860, 1880, 1900, 1920, 1940, 1960, 1980, 2000, 2020, 2040, 2060, 2080,
|
||||
2100, 2120, 2140, 2160, 2180, 2200, 2220, 2240, 2260]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
@@ -97,29 +129,40 @@ examples:
|
||||
port@0 {
|
||||
phy-handle = <&rgmii_phy6>;
|
||||
phy-mode = "rgmii-id";
|
||||
rx-internal-delay-ps = <0>;
|
||||
tx-internal-delay-ps = <0>;
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
port@1 {
|
||||
phy-handle = <&rgmii_phy3>;
|
||||
phy-mode = "rgmii-id";
|
||||
rx-internal-delay-ps = <0>;
|
||||
tx-internal-delay-ps = <0>;
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
phy-handle = <&rgmii_phy4>;
|
||||
phy-mode = "rgmii-id";
|
||||
rx-internal-delay-ps = <0>;
|
||||
tx-internal-delay-ps = <0>;
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
phy-handle = <&rgmii_phy4>;
|
||||
phy-mode = "rgmii-id";
|
||||
rx-internal-delay-ps = <0>;
|
||||
tx-internal-delay-ps = <0>;
|
||||
reg = <3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
ethernet = <&enet2>;
|
||||
phy-mode = "rgmii";
|
||||
rx-internal-delay-ps = <0>;
|
||||
tx-internal-delay-ps = <0>;
|
||||
reg = <4>;
|
||||
|
||||
fixed-link {
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
* Qualcomm Atheros QCA8xxx switch family
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be one of:
|
||||
"qca,qca8327"
|
||||
"qca,qca8334"
|
||||
"qca,qca8337"
|
||||
|
||||
- #size-cells: must be 0
|
||||
- #address-cells: must be 1
|
||||
|
||||
Optional properties:
|
||||
|
||||
- reset-gpios: GPIO to be used to reset the whole device
|
||||
|
||||
Subnodes:
|
||||
|
||||
The integrated switch subnode should be specified according to the binding
|
||||
described in dsa/dsa.txt. If the QCA8K switch is connect to a SoC's external
|
||||
mdio-bus each subnode describing a port needs to have a valid phandle
|
||||
referencing the internal PHY it is connected to. This is because there's no
|
||||
N:N mapping of port and PHY id.
|
||||
To declare the internal mdio-bus configuration, declare a mdio node in the
|
||||
switch node and declare the phandle for the port referencing the internal
|
||||
PHY is connected to. In this config a internal mdio-bus is registered and
|
||||
the mdio MASTER is used as communication.
|
||||
|
||||
Don't use mixed external and internal mdio-bus configurations, as this is
|
||||
not supported by the hardware.
|
||||
|
||||
The CPU port of this switch is always port 0.
|
||||
|
||||
A CPU port node has the following optional node:
|
||||
|
||||
- fixed-link : Fixed-link subnode describing a link to a non-MDIO
|
||||
managed entity. See
|
||||
Documentation/devicetree/bindings/net/fixed-link.txt
|
||||
for details.
|
||||
|
||||
For QCA8K the 'fixed-link' sub-node supports only the following properties:
|
||||
|
||||
- 'speed' (integer, mandatory), to indicate the link speed. Accepted
|
||||
values are 10, 100 and 1000
|
||||
- 'full-duplex' (boolean, optional), to indicate that full duplex is
|
||||
used. When absent, half duplex is assumed.
|
||||
|
||||
Examples:
|
||||
|
||||
for the external mdio-bus configuration:
|
||||
|
||||
&mdio0 {
|
||||
phy_port1: phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
phy_port2: phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
phy_port3: phy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
phy_port4: phy@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
|
||||
phy_port5: phy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
|
||||
switch@10 {
|
||||
compatible = "qca,qca8337";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
||||
reg = <0x10>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac1>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = 1000;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
phy-handle = <&phy_port1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
phy-handle = <&phy_port2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
phy-handle = <&phy_port3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
phy-handle = <&phy_port4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "wan";
|
||||
phy-handle = <&phy_port5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
for the internal master mdio-bus configuration:
|
||||
|
||||
&mdio0 {
|
||||
switch@10 {
|
||||
compatible = "qca,qca8337";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
||||
reg = <0x10>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac1>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = 1000;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&phy_port1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&phy_port2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&phy_port3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&phy_port4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "wan";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&phy_port5>;
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy_port1: phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
phy_port2: phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
phy_port3: phy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
phy_port4: phy@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
|
||||
phy_port5: phy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
362
Documentation/devicetree/bindings/net/dsa/qca8k.yaml
Normal file
362
Documentation/devicetree/bindings/net/dsa/qca8k.yaml
Normal file
@@ -0,0 +1,362 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/dsa/qca8k.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Atheros QCA83xx switch family
|
||||
|
||||
maintainers:
|
||||
- John Crispin <john@phrozen.org>
|
||||
|
||||
description:
|
||||
If the QCA8K switch is connect to an SoC's external mdio-bus, each subnode
|
||||
describing a port needs to have a valid phandle referencing the internal PHY
|
||||
it is connected to. This is because there is no N:N mapping of port and PHY
|
||||
ID. To declare the internal mdio-bus configuration, declare an MDIO node in
|
||||
the switch node and declare the phandle for the port, referencing the internal
|
||||
PHY it is connected to. In this config, an internal mdio-bus is registered and
|
||||
the MDIO master is used for communication. Mixed external and internal
|
||||
mdio-bus configurations are not supported by the hardware.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- enum:
|
||||
- qca,qca8327
|
||||
- qca,qca8328
|
||||
- qca,qca8334
|
||||
- qca,qca8337
|
||||
description: |
|
||||
qca,qca8328: referenced as AR8328(N)-AK1(A/B) QFN 176 pin package
|
||||
qca,qca8327: referenced as AR8327(N)-AL1A DR-QFN 148 pin package
|
||||
qca,qca8334: referenced as QCA8334-AL3C QFN 88 pin package
|
||||
qca,qca8337: referenced as QCA8337N-AL3(B/C) DR-QFN 148 pin package
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
GPIO to be used to reset the whole device
|
||||
maxItems: 1
|
||||
|
||||
qca,ignore-power-on-sel:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Ignore power-on pin strapping to configure LED open-drain or EEPROM
|
||||
presence. This is needed for devices with incorrect configuration or when
|
||||
the OEM has decided not to use pin strapping and falls back to SW regs.
|
||||
|
||||
qca,led-open-drain:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Set LEDs to open-drain mode. This requires the qca,ignore-power-on-sel to
|
||||
be set, otherwise the driver will fail at probe. This is required if the
|
||||
OEM does not use pin strapping to set this mode and prefers to set it
|
||||
using SW regs. The pin strappings related to LED open-drain mode are
|
||||
B68 on the QCA832x and B49 on the QCA833x.
|
||||
|
||||
mdio:
|
||||
type: object
|
||||
description: Qca8k switch have an internal mdio to access switch port.
|
||||
If this is not present, the legacy mapping is used and the
|
||||
internal mdio access is used.
|
||||
With the legacy mapping the reg corresponding to the internal
|
||||
mdio is the switch reg with an offset of -1.
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^(ethernet-)?phy@[0-4]$":
|
||||
type: object
|
||||
|
||||
allOf:
|
||||
- $ref: "http://devicetree.org/schemas/net/mdio.yaml#"
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
patternProperties:
|
||||
"^(ethernet-)?ports$":
|
||||
type: object
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^(ethernet-)?port@[0-6]$":
|
||||
type: object
|
||||
description: Ethernet switch ports
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: Port number
|
||||
|
||||
label:
|
||||
description:
|
||||
Describes the label associated with this port, which will become
|
||||
the netdev name
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
|
||||
link:
|
||||
description:
|
||||
Should be a list of phandles to other switch's DSA port. This
|
||||
port is used as the outgoing port towards the phandle ports. The
|
||||
full routing information must be given, not just the one hop
|
||||
routes to neighbouring switches
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
|
||||
ethernet:
|
||||
description:
|
||||
Should be a phandle to a valid Ethernet device node. This host
|
||||
device is what the switch port is connected to
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
phy-handle: true
|
||||
|
||||
phy-mode: true
|
||||
|
||||
fixed-link: true
|
||||
|
||||
mac-address: true
|
||||
|
||||
sfp: true
|
||||
|
||||
qca,sgmii-rxclk-falling-edge:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Set the receive clock phase to falling edge. Mostly commonly used on
|
||||
the QCA8327 with CPU port 0 set to SGMII.
|
||||
|
||||
qca,sgmii-txclk-falling-edge:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Set the transmit clock phase to falling edge.
|
||||
|
||||
qca,sgmii-enable-pll:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
For SGMII CPU port, explicitly enable PLL, TX and RX chain along with
|
||||
Signal Detection. On the QCA8327 this should not be enabled, otherwise
|
||||
the SGMII port will not initialize. When used on the QCA8337, revision 3
|
||||
or greater, a warning will be displayed. When the CPU port is set to
|
||||
SGMII on the QCA8337, it is advised to set this unless a communication
|
||||
issue is observed.
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- ports
|
||||
- required:
|
||||
- ethernet-ports
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
external_phy_port1: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
external_phy_port2: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
external_phy_port3: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
external_phy_port4: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
|
||||
external_phy_port5: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
|
||||
switch@10 {
|
||||
compatible = "qca,qca8337";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
||||
reg = <0x10>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac1>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
phy-handle = <&external_phy_port1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
phy-handle = <&external_phy_port2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
phy-handle = <&external_phy_port3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
phy-handle = <&external_phy_port4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "wan";
|
||||
phy-handle = <&external_phy_port5>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
switch@10 {
|
||||
compatible = "qca,qca8337";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reset-gpios = <&gpio 42 GPIO_ACTIVE_LOW>;
|
||||
reg = <0x10>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac1>;
|
||||
phy-mode = "rgmii";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy_port1>;
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy_port2>;
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy_port3>;
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy_port4>;
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "wan";
|
||||
phy-mode = "internal";
|
||||
phy-handle = <&internal_phy_port5>;
|
||||
};
|
||||
|
||||
port@6 {
|
||||
reg = <0>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac1>;
|
||||
phy-mode = "sgmii";
|
||||
|
||||
qca,sgmii-rxclk-falling-edge;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
internal_phy_port1: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
internal_phy_port2: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
internal_phy_port3: ethernet-phy@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
|
||||
internal_phy_port4: ethernet-phy@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
|
||||
internal_phy_port5: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -9,6 +9,7 @@ SMI-based Realtek devices.
|
||||
Required properties:
|
||||
|
||||
- compatible: must be exactly one of:
|
||||
"realtek,rtl8365mb" (4+1 ports)
|
||||
"realtek,rtl8366"
|
||||
"realtek,rtl8366rb" (4+1 ports)
|
||||
"realtek,rtl8366s" (4+1 ports)
|
||||
@@ -62,6 +63,8 @@ and subnodes of DSA switches.
|
||||
|
||||
Examples:
|
||||
|
||||
An example for the RTL8366RB:
|
||||
|
||||
switch {
|
||||
compatible = "realtek,rtl8366rb";
|
||||
/* 22 = MDIO (has input reads), 21 = MDC (clock, output only) */
|
||||
@@ -151,3 +154,87 @@ switch {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
An example for the RTL8365MB-VC:
|
||||
|
||||
switch {
|
||||
compatible = "realtek,rtl8365mb";
|
||||
mdc-gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
|
||||
mdio-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
|
||||
|
||||
switch_intc: interrupt-controller {
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "swp0";
|
||||
phy-handle = <ðphy0>;
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "swp1";
|
||||
phy-handle = <ðphy1>;
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "swp2";
|
||||
phy-handle = <ðphy2>;
|
||||
};
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "swp3";
|
||||
phy-handle = <ðphy3>;
|
||||
};
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&fec1>;
|
||||
phy-mode = "rgmii";
|
||||
tx-internal-delay-ps = <2000>;
|
||||
rx-internal-delay-ps = <2000>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mdio {
|
||||
compatible = "realtek,smi-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethphy0: phy@0 {
|
||||
reg = <0>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
ethphy1: phy@1 {
|
||||
reg = <1>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <1>;
|
||||
};
|
||||
ethphy2: phy@2 {
|
||||
reg = <2>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <2>;
|
||||
};
|
||||
ethphy3: phy@3 {
|
||||
reg = <3>;
|
||||
interrupt-parent = <&switch_intc>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -51,6 +51,9 @@ examples:
|
||||
switch@10 {
|
||||
compatible = "qca,qca8337";
|
||||
reg = <0x10>;
|
||||
/* ... */
|
||||
|
||||
ports {
|
||||
/* ... */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@ properties:
|
||||
- socionext,uniphier-ld11-ave4
|
||||
- socionext,uniphier-ld20-ave4
|
||||
- socionext,uniphier-pxs3-ave4
|
||||
- socionext,uniphier-nx1-ave4
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -131,6 +131,8 @@ patternProperties:
|
||||
description: Asahi Kasei Corp.
|
||||
"^asc,.*":
|
||||
description: All Sensors Corporation
|
||||
"^asix,.*":
|
||||
description: ASIX Electronics Corporation
|
||||
"^aspeed,.*":
|
||||
description: ASPEED Technology Inc.
|
||||
"^asus,.*":
|
||||
|
||||
@@ -300,3 +300,14 @@ sync_version - INTEGER
|
||||
|
||||
Kernels with this sync_version entry are able to receive messages
|
||||
of both version 1 and version 2 of the synchronisation protocol.
|
||||
|
||||
run_estimation - BOOLEAN
|
||||
0 - disabled
|
||||
not 0 - enabled (default)
|
||||
|
||||
If disabled, the estimation will be stop, and you can't see
|
||||
any update on speed estimation data.
|
||||
|
||||
You can always re-enable estimation by setting this value to 1.
|
||||
But be careful, the first estimation after re-enable is not
|
||||
accurate.
|
||||
|
||||
@@ -2908,6 +2908,12 @@ S: Maintained
|
||||
F: Documentation/hwmon/asc7621.rst
|
||||
F: drivers/hwmon/asc7621.c
|
||||
|
||||
ASIX AX88796C SPI ETHERNET ADAPTER
|
||||
M: Łukasz Stelmach <l.stelmach@samsung.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/asix,ax88796c.yaml
|
||||
F: drivers/net/ethernet/asix/ax88796c_*
|
||||
|
||||
ASPEED PINCTRL DRIVERS
|
||||
M: Andrew Jeffery <andrew@aj.id.au>
|
||||
L: linux-aspeed@lists.ozlabs.org (moderated for non-subscribers)
|
||||
@@ -7034,7 +7040,6 @@ F: drivers/net/mdio/fwnode_mdio.c
|
||||
F: drivers/net/mdio/of_mdio.c
|
||||
F: drivers/net/pcs/
|
||||
F: drivers/net/phy/
|
||||
F: drivers/of/of_net.c
|
||||
F: include/dt-bindings/net/qca-ar803x.h
|
||||
F: include/linux/*mdio*.h
|
||||
F: include/linux/mdio/*.h
|
||||
@@ -7046,6 +7051,7 @@ F: include/linux/platform_data/mdio-gpio.h
|
||||
F: include/trace/events/mdio.h
|
||||
F: include/uapi/linux/mdio.h
|
||||
F: include/uapi/linux/mii.h
|
||||
F: net/core/of_net.c
|
||||
|
||||
EXFAT FILE SYSTEM
|
||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||
|
||||
@@ -1055,14 +1055,16 @@ static const struct net_device_ops ssip_pn_ops = {
|
||||
|
||||
static void ssip_pn_setup(struct net_device *dev)
|
||||
{
|
||||
static const u8 addr = PN_MEDIA_SOS;
|
||||
|
||||
dev->features = 0;
|
||||
dev->netdev_ops = &ssip_pn_ops;
|
||||
dev->type = ARPHRD_PHONET;
|
||||
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
|
||||
dev->mtu = SSIP_DEFAULT_MTU;
|
||||
dev->hard_header_len = 1;
|
||||
dev->dev_addr[0] = PN_MEDIA_SOS;
|
||||
dev->addr_len = 1;
|
||||
dev_addr_set(dev, &addr);
|
||||
dev->tx_queue_len = SSIP_TXQUEUE_LEN;
|
||||
|
||||
dev->needs_free_netdev = true;
|
||||
|
||||
@@ -945,8 +945,8 @@ static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
dev->broadcast[0] = 0xFF;
|
||||
|
||||
/* Set hardware address. */
|
||||
dev->dev_addr[0] = aa->s_node;
|
||||
dev->addr_len = 1;
|
||||
dev_addr_set(dev, &aa->s_node);
|
||||
return 0;
|
||||
|
||||
case SIOCGIFADDR:
|
||||
|
||||
@@ -846,9 +846,8 @@ static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
set_30 (dev,ltflags);
|
||||
|
||||
dev->broadcast[0] = 0xFF;
|
||||
dev->dev_addr[0] = aa->s_node;
|
||||
|
||||
dev->addr_len=1;
|
||||
dev_addr_set(dev, &aa->s_node);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -207,7 +207,8 @@ static int __init arcrimi_found(struct net_device *dev)
|
||||
}
|
||||
|
||||
/* get and check the station ID from offset 1 in shmem */
|
||||
dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION);
|
||||
arcnet_set_addr(dev, arcnet_readb(lp->mem_start,
|
||||
COM9026_REG_R_STATION));
|
||||
|
||||
arc_printk(D_NORMAL, dev, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n",
|
||||
dev->dev_addr[0],
|
||||
@@ -324,7 +325,7 @@ static int __init arc_rimi_init(void)
|
||||
return -ENOMEM;
|
||||
|
||||
if (node && node != 0xff)
|
||||
dev->dev_addr[0] = node;
|
||||
arcnet_set_addr(dev, node);
|
||||
|
||||
dev->mem_start = io;
|
||||
dev->irq = irq;
|
||||
|
||||
@@ -364,6 +364,11 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
|
||||
struct net_device *dev);
|
||||
void arcnet_timeout(struct net_device *dev, unsigned int txqueue);
|
||||
|
||||
static inline void arcnet_set_addr(struct net_device *dev, u8 addr)
|
||||
{
|
||||
dev_addr_set(dev, &addr);
|
||||
}
|
||||
|
||||
/* I/O equivalents */
|
||||
|
||||
#ifdef CONFIG_SA1100_CT6001
|
||||
|
||||
@@ -151,7 +151,7 @@ static int __init com20020_init(void)
|
||||
return -ENOMEM;
|
||||
|
||||
if (node && node != 0xff)
|
||||
dev->dev_addr[0] = node;
|
||||
arcnet_set_addr(dev, node);
|
||||
|
||||
dev->netdev_ops = &com20020_netdev_ops;
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
||||
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
dev->base_addr = ioaddr;
|
||||
dev->dev_addr[0] = node;
|
||||
arcnet_set_addr(dev, node);
|
||||
dev->sysfs_groups[0] = &com20020_state_group;
|
||||
dev->irq = pdev->irq;
|
||||
lp->card_name = "PCI COM20020";
|
||||
|
||||
@@ -157,7 +157,7 @@ static int com20020_set_hwaddr(struct net_device *dev, void *addr)
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
struct sockaddr *hwaddr = addr;
|
||||
|
||||
memcpy(dev->dev_addr, hwaddr->sa_data, 1);
|
||||
dev_addr_set(dev, hwaddr->sa_data);
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_NODE);
|
||||
arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG);
|
||||
|
||||
@@ -220,7 +220,7 @@ int com20020_found(struct net_device *dev, int shared)
|
||||
|
||||
/* FIXME: do this some other way! */
|
||||
if (!dev->dev_addr[0])
|
||||
dev->dev_addr[0] = arcnet_inb(ioaddr, 8);
|
||||
arcnet_set_addr(dev, arcnet_inb(ioaddr, 8));
|
||||
|
||||
com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
|
||||
arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG);
|
||||
|
||||
@@ -133,7 +133,7 @@ static int com20020_probe(struct pcmcia_device *p_dev)
|
||||
lp->hw.owner = THIS_MODULE;
|
||||
|
||||
/* fill in our module parameters as defaults */
|
||||
dev->dev_addr[0] = node;
|
||||
arcnet_set_addr(dev, node);
|
||||
|
||||
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
p_dev->resource[0]->end = 16;
|
||||
|
||||
@@ -252,7 +252,7 @@ static int __init com90io_found(struct net_device *dev)
|
||||
|
||||
/* get and check the station ID from offset 1 in shmem */
|
||||
|
||||
dev->dev_addr[0] = get_buffer_byte(dev, 1);
|
||||
arcnet_set_addr(dev, get_buffer_byte(dev, 1));
|
||||
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
|
||||
@@ -531,7 +531,8 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem,
|
||||
}
|
||||
|
||||
/* get and check the station ID from offset 1 in shmem */
|
||||
dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION);
|
||||
arcnet_set_addr(dev, arcnet_readb(lp->mem_start,
|
||||
COM9026_REG_R_STATION));
|
||||
|
||||
dev->base_addr = ioaddr;
|
||||
|
||||
|
||||
@@ -4414,7 +4414,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
|
||||
}
|
||||
|
||||
/* success */
|
||||
memcpy(bond_dev->dev_addr, ss->__data, bond_dev->addr_len);
|
||||
dev_addr_set(bond_dev, ss->__data);
|
||||
return 0;
|
||||
|
||||
unwind:
|
||||
|
||||
@@ -811,8 +811,8 @@ int bond_create_sysfs(struct bond_net *bn)
|
||||
*/
|
||||
if (ret == -EEXIST) {
|
||||
/* Is someone being kinky and naming a device bonding_master? */
|
||||
if (__dev_get_by_name(bn->net,
|
||||
class_attr_bonding_masters.attr.name))
|
||||
if (netdev_name_in_use(bn->net,
|
||||
class_attr_bonding_masters.attr.name))
|
||||
pr_err("network device named %s already exists in sysfs\n",
|
||||
class_attr_bonding_masters.attr.name);
|
||||
ret = 0;
|
||||
|
||||
@@ -70,6 +70,7 @@ config NET_DSA_QCA8K
|
||||
config NET_DSA_REALTEK_SMI
|
||||
tristate "Realtek SMI Ethernet switch family support"
|
||||
select NET_DSA_TAG_RTL4_A
|
||||
select NET_DSA_TAG_RTL8_4
|
||||
select FIXED_PHY
|
||||
select IRQ_DOMAIN
|
||||
select REALTEK_PHY
|
||||
|
||||
@@ -10,7 +10,7 @@ obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
|
||||
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
|
||||
obj-$(CONFIG_NET_DSA_QCA8K) += qca8k.o
|
||||
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
|
||||
realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o
|
||||
realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o rtl8365mb.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303) += lan9303-core.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_I2C) += lan9303_i2c.o
|
||||
obj-$(CONFIG_NET_DSA_SMSC_LAN9303_MDIO) += lan9303_mdio.o
|
||||
|
||||
@@ -889,62 +889,183 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
|
||||
}
|
||||
|
||||
static int
|
||||
qca8k_setup_of_rgmii_delay(struct qca8k_priv *priv)
|
||||
qca8k_setup_mac_pwr_sel(struct qca8k_priv *priv)
|
||||
{
|
||||
u32 mask = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* SoC specific settings for ipq8064.
|
||||
* If more device require this consider adding
|
||||
* a dedicated binding.
|
||||
*/
|
||||
if (of_machine_is_compatible("qcom,ipq8064"))
|
||||
mask |= QCA8K_MAC_PWR_RGMII0_1_8V;
|
||||
|
||||
/* SoC specific settings for ipq8065 */
|
||||
if (of_machine_is_compatible("qcom,ipq8065"))
|
||||
mask |= QCA8K_MAC_PWR_RGMII1_1_8V;
|
||||
|
||||
if (mask) {
|
||||
ret = qca8k_rmw(priv, QCA8K_REG_MAC_PWR_SEL,
|
||||
QCA8K_MAC_PWR_RGMII0_1_8V |
|
||||
QCA8K_MAC_PWR_RGMII1_1_8V,
|
||||
mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qca8k_find_cpu_port(struct dsa_switch *ds)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
|
||||
/* Find the connected cpu port. Valid port are 0 or 6 */
|
||||
if (dsa_is_cpu_port(ds, 0))
|
||||
return 0;
|
||||
|
||||
dev_dbg(priv->dev, "port 0 is not the CPU port. Checking port 6");
|
||||
|
||||
if (dsa_is_cpu_port(ds, 6))
|
||||
return 6;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int
|
||||
qca8k_setup_of_pws_reg(struct qca8k_priv *priv)
|
||||
{
|
||||
struct device_node *node = priv->dev->of_node;
|
||||
const struct qca8k_match_data *data;
|
||||
u32 val = 0;
|
||||
int ret;
|
||||
|
||||
/* QCA8327 require to set to the correct mode.
|
||||
* His bigger brother QCA8328 have the 172 pin layout.
|
||||
* Should be applied by default but we set this just to make sure.
|
||||
*/
|
||||
if (priv->switch_id == QCA8K_ID_QCA8327) {
|
||||
data = of_device_get_match_data(priv->dev);
|
||||
|
||||
/* Set the correct package of 148 pin for QCA8327 */
|
||||
if (data->reduced_package)
|
||||
val |= QCA8327_PWS_PACKAGE148_EN;
|
||||
|
||||
ret = qca8k_rmw(priv, QCA8K_REG_PWS, QCA8327_PWS_PACKAGE148_EN,
|
||||
val);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(node, "qca,ignore-power-on-sel"))
|
||||
val |= QCA8K_PWS_POWER_ON_SEL;
|
||||
|
||||
if (of_property_read_bool(node, "qca,led-open-drain")) {
|
||||
if (!(val & QCA8K_PWS_POWER_ON_SEL)) {
|
||||
dev_err(priv->dev, "qca,led-open-drain require qca,ignore-power-on-sel to be set.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val |= QCA8K_PWS_LED_OPEN_EN_CSR;
|
||||
}
|
||||
|
||||
return qca8k_rmw(priv, QCA8K_REG_PWS,
|
||||
QCA8K_PWS_LED_OPEN_EN_CSR | QCA8K_PWS_POWER_ON_SEL,
|
||||
val);
|
||||
}
|
||||
|
||||
static int
|
||||
qca8k_parse_port_config(struct qca8k_priv *priv)
|
||||
{
|
||||
int port, cpu_port_index = -1, ret;
|
||||
struct device_node *port_dn;
|
||||
phy_interface_t mode;
|
||||
struct dsa_port *dp;
|
||||
u32 val;
|
||||
u32 delay;
|
||||
|
||||
/* CPU port is already checked */
|
||||
dp = dsa_to_port(priv->ds, 0);
|
||||
/* We have 2 CPU port. Check them */
|
||||
for (port = 0; port < QCA8K_NUM_PORTS && cpu_port_index < QCA8K_NUM_CPU_PORTS; port++) {
|
||||
/* Skip every other port */
|
||||
if (port != 0 && port != 6)
|
||||
continue;
|
||||
|
||||
port_dn = dp->dn;
|
||||
dp = dsa_to_port(priv->ds, port);
|
||||
port_dn = dp->dn;
|
||||
cpu_port_index++;
|
||||
|
||||
/* Check if port 0 is set to the correct type */
|
||||
of_get_phy_mode(port_dn, &mode);
|
||||
if (mode != PHY_INTERFACE_MODE_RGMII_ID &&
|
||||
mode != PHY_INTERFACE_MODE_RGMII_RXID &&
|
||||
mode != PHY_INTERFACE_MODE_RGMII_TXID) {
|
||||
return 0;
|
||||
}
|
||||
if (!of_device_is_available(port_dn))
|
||||
continue;
|
||||
|
||||
switch (mode) {
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
if (of_property_read_u32(port_dn, "rx-internal-delay-ps", &val))
|
||||
val = 2;
|
||||
else
|
||||
/* Switch regs accept value in ns, convert ps to ns */
|
||||
val = val / 1000;
|
||||
ret = of_get_phy_mode(port_dn, &mode);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
if (val > QCA8K_MAX_DELAY) {
|
||||
dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
|
||||
val = 3;
|
||||
}
|
||||
switch (mode) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
delay = 0;
|
||||
|
||||
if (!of_property_read_u32(port_dn, "tx-internal-delay-ps", &delay))
|
||||
/* Switch regs accept value in ns, convert ps to ns */
|
||||
delay = delay / 1000;
|
||||
else if (mode == PHY_INTERFACE_MODE_RGMII_ID ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_TXID)
|
||||
delay = 1;
|
||||
|
||||
if (delay > QCA8K_MAX_DELAY) {
|
||||
dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
|
||||
delay = 3;
|
||||
}
|
||||
|
||||
priv->ports_config.rgmii_tx_delay[cpu_port_index] = delay;
|
||||
|
||||
delay = 0;
|
||||
|
||||
if (!of_property_read_u32(port_dn, "rx-internal-delay-ps", &delay))
|
||||
/* Switch regs accept value in ns, convert ps to ns */
|
||||
delay = delay / 1000;
|
||||
else if (mode == PHY_INTERFACE_MODE_RGMII_ID ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_RXID)
|
||||
delay = 2;
|
||||
|
||||
if (delay > QCA8K_MAX_DELAY) {
|
||||
dev_err(priv->dev, "rgmii rx delay is limited to a max value of 3ns, setting to the max value");
|
||||
delay = 3;
|
||||
}
|
||||
|
||||
priv->ports_config.rgmii_rx_delay[cpu_port_index] = delay;
|
||||
|
||||
/* Skip sgmii parsing for rgmii* mode */
|
||||
if (mode == PHY_INTERFACE_MODE_RGMII ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_ID ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_TXID ||
|
||||
mode == PHY_INTERFACE_MODE_RGMII_RXID)
|
||||
break;
|
||||
|
||||
if (of_property_read_bool(port_dn, "qca,sgmii-txclk-falling-edge"))
|
||||
priv->ports_config.sgmii_tx_clk_falling_edge = true;
|
||||
|
||||
if (of_property_read_bool(port_dn, "qca,sgmii-rxclk-falling-edge"))
|
||||
priv->ports_config.sgmii_rx_clk_falling_edge = true;
|
||||
|
||||
if (of_property_read_bool(port_dn, "qca,sgmii-enable-pll")) {
|
||||
priv->ports_config.sgmii_enable_pll = true;
|
||||
|
||||
if (priv->switch_id == QCA8K_ID_QCA8327) {
|
||||
dev_err(priv->dev, "SGMII PLL should NOT be enabled for qca8327. Aborting enabling");
|
||||
priv->ports_config.sgmii_enable_pll = false;
|
||||
}
|
||||
|
||||
if (priv->switch_revision < 2)
|
||||
dev_warn(priv->dev, "SGMII PLL should NOT be enabled for qca8337 with revision 2 or more.");
|
||||
}
|
||||
|
||||
priv->rgmii_rx_delay = val;
|
||||
/* Stop here if we need to check only for rx delay */
|
||||
if (mode != PHY_INTERFACE_MODE_RGMII_ID)
|
||||
break;
|
||||
|
||||
fallthrough;
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
if (of_property_read_u32(port_dn, "tx-internal-delay-ps", &val))
|
||||
val = 1;
|
||||
else
|
||||
/* Switch regs accept value in ns, convert ps to ns */
|
||||
val = val / 1000;
|
||||
|
||||
if (val > QCA8K_MAX_DELAY) {
|
||||
dev_err(priv->dev, "rgmii tx delay is limited to a max value of 3ns, setting to the max value");
|
||||
val = 3;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
priv->rgmii_tx_delay = val;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -954,15 +1075,20 @@ static int
|
||||
qca8k_setup(struct dsa_switch *ds)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
int ret, i;
|
||||
int cpu_port, ret, i;
|
||||
u32 mask;
|
||||
|
||||
/* Make sure that port 0 is the cpu port */
|
||||
if (!dsa_is_cpu_port(ds, 0)) {
|
||||
dev_err(priv->dev, "port 0 is not the CPU port");
|
||||
return -EINVAL;
|
||||
cpu_port = qca8k_find_cpu_port(ds);
|
||||
if (cpu_port < 0) {
|
||||
dev_err(priv->dev, "No cpu port configured in both cpu port0 and port6");
|
||||
return cpu_port;
|
||||
}
|
||||
|
||||
/* Parse CPU port config to be later used in phy_link mac_config */
|
||||
ret = qca8k_parse_port_config(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_init(&priv->reg_mutex);
|
||||
|
||||
/* Start by setting up the register mapping */
|
||||
@@ -975,7 +1101,11 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qca8k_setup_of_rgmii_delay(priv);
|
||||
ret = qca8k_setup_of_pws_reg(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qca8k_setup_mac_pwr_sel(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -992,41 +1122,49 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
dev_warn(priv->dev, "mib init failed");
|
||||
|
||||
/* Enable QCA header mode on the cpu port */
|
||||
ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(QCA8K_CPU_PORT),
|
||||
QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
|
||||
QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed enabling QCA header mode");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
/* Initial setup of all ports */
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
/* Disable forwarding by default on all ports */
|
||||
ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
QCA8K_PORT_LOOKUP_MEMBER, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable QCA header mode on all cpu ports */
|
||||
if (dsa_is_cpu_port(ds, i)) {
|
||||
ret = qca8k_write(priv, QCA8K_REG_PORT_HDR_CTRL(i),
|
||||
QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_TX_S |
|
||||
QCA8K_PORT_HDR_CTRL_ALL << QCA8K_PORT_HDR_CTRL_RX_S);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed enabling QCA header mode");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable MAC by default on all user ports */
|
||||
if (dsa_is_user_port(ds, i))
|
||||
qca8k_port_set_status(priv, i, 0);
|
||||
}
|
||||
|
||||
/* Disable MAC by default on all ports */
|
||||
for (i = 1; i < QCA8K_NUM_PORTS; i++)
|
||||
qca8k_port_set_status(priv, i, 0);
|
||||
|
||||
/* Forward all unknown frames to CPU port for Linux processing */
|
||||
/* Forward all unknown frames to CPU port for Linux processing
|
||||
* Notice that in multi-cpu config only one port should be set
|
||||
* for igmp, unknown, multicast and broadcast packet
|
||||
*/
|
||||
ret = qca8k_write(priv, QCA8K_REG_GLOBAL_FW_CTRL1,
|
||||
BIT(0) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
|
||||
BIT(0) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
|
||||
BIT(0) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
|
||||
BIT(0) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
|
||||
BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_IGMP_DP_S |
|
||||
BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_BC_DP_S |
|
||||
BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_MC_DP_S |
|
||||
BIT(cpu_port) << QCA8K_GLOBAL_FW_CTRL1_UC_DP_S);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Setup connection between CPU port & user ports */
|
||||
/* Setup connection between CPU port & user ports
|
||||
* Configure specific switch configuration for ports
|
||||
*/
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
/* CPU port gets connected to all user ports of the switch */
|
||||
if (dsa_is_cpu_port(ds, i)) {
|
||||
ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(QCA8K_CPU_PORT),
|
||||
ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
QCA8K_PORT_LOOKUP_MEMBER, dsa_user_ports(ds));
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1038,7 +1176,7 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
|
||||
ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(i),
|
||||
QCA8K_PORT_LOOKUP_MEMBER,
|
||||
BIT(QCA8K_CPU_PORT));
|
||||
BIT(cpu_port));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1063,16 +1201,14 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* The port 5 of the qca8337 have some problem in flood condition. The
|
||||
* original legacy driver had some specific buffer and priority settings
|
||||
* for the different port suggested by the QCA switch team. Add this
|
||||
* missing settings to improve switch stability under load condition.
|
||||
* This problem is limited to qca8337 and other qca8k switch are not affected.
|
||||
*/
|
||||
if (priv->switch_id == QCA8K_ID_QCA8337) {
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
/* The port 5 of the qca8337 have some problem in flood condition. The
|
||||
* original legacy driver had some specific buffer and priority settings
|
||||
* for the different port suggested by the QCA switch team. Add this
|
||||
* missing settings to improve switch stability under load condition.
|
||||
* This problem is limited to qca8337 and other qca8k switch are not affected.
|
||||
*/
|
||||
if (priv->switch_id == QCA8K_ID_QCA8337) {
|
||||
switch (i) {
|
||||
/* The 2 CPU port and port 5 requires some different
|
||||
* priority than any other ports.
|
||||
@@ -1108,6 +1244,12 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
QCA8K_PORT_HOL_CTRL1_WRED_EN,
|
||||
mask);
|
||||
}
|
||||
|
||||
/* Set initial MTU for every port.
|
||||
* We have only have a general MTU setting. So track
|
||||
* every port and set the max across all port.
|
||||
*/
|
||||
priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
|
||||
}
|
||||
|
||||
/* Special GLOBAL_FC_THRESH value are needed for ar8327 switch */
|
||||
@@ -1121,8 +1263,6 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
}
|
||||
|
||||
/* Setup our port MTUs to match power on defaults */
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++)
|
||||
priv->port_mtu[i] = ETH_FRAME_LEN + ETH_FCS_LEN;
|
||||
ret = qca8k_write(priv, QCA8K_MAX_FRAME_SIZE, ETH_FRAME_LEN + ETH_FCS_LEN);
|
||||
if (ret)
|
||||
dev_warn(priv->dev, "failed setting MTU settings");
|
||||
@@ -1136,13 +1276,54 @@ qca8k_setup(struct dsa_switch *ds)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
qca8k_mac_config_setup_internal_delay(struct qca8k_priv *priv, int cpu_port_index,
|
||||
u32 reg)
|
||||
{
|
||||
u32 delay, val = 0;
|
||||
int ret;
|
||||
|
||||
/* Delay can be declared in 3 different way.
|
||||
* Mode to rgmii and internal-delay standard binding defined
|
||||
* rgmii-id or rgmii-tx/rx phy mode set.
|
||||
* The parse logic set a delay different than 0 only when one
|
||||
* of the 3 different way is used. In all other case delay is
|
||||
* not enabled. With ID or TX/RXID delay is enabled and set
|
||||
* to the default and recommended value.
|
||||
*/
|
||||
if (priv->ports_config.rgmii_tx_delay[cpu_port_index]) {
|
||||
delay = priv->ports_config.rgmii_tx_delay[cpu_port_index];
|
||||
|
||||
val |= QCA8K_PORT_PAD_RGMII_TX_DELAY(delay) |
|
||||
QCA8K_PORT_PAD_RGMII_TX_DELAY_EN;
|
||||
}
|
||||
|
||||
if (priv->ports_config.rgmii_rx_delay[cpu_port_index]) {
|
||||
delay = priv->ports_config.rgmii_rx_delay[cpu_port_index];
|
||||
|
||||
val |= QCA8K_PORT_PAD_RGMII_RX_DELAY(delay) |
|
||||
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN;
|
||||
}
|
||||
|
||||
/* Set RGMII delay based on the selected values */
|
||||
ret = qca8k_rmw(priv, reg,
|
||||
QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK |
|
||||
QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK |
|
||||
QCA8K_PORT_PAD_RGMII_TX_DELAY_EN |
|
||||
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN,
|
||||
val);
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to set internal delay for CPU port%d",
|
||||
cpu_port_index == QCA8K_CPU_PORT0 ? 0 : 6);
|
||||
}
|
||||
|
||||
static void
|
||||
qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
struct qca8k_priv *priv = ds->priv;
|
||||
int cpu_port_index, ret;
|
||||
u32 reg, val;
|
||||
int ret;
|
||||
|
||||
switch (port) {
|
||||
case 0: /* 1st CPU port */
|
||||
@@ -1154,6 +1335,7 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
return;
|
||||
|
||||
reg = QCA8K_REG_PORT0_PAD_CTRL;
|
||||
cpu_port_index = QCA8K_CPU_PORT0;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
@@ -1172,6 +1354,7 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
return;
|
||||
|
||||
reg = QCA8K_REG_PORT6_PAD_CTRL;
|
||||
cpu_port_index = QCA8K_CPU_PORT6;
|
||||
break;
|
||||
default:
|
||||
dev_err(ds->dev, "%s: unsupported port: %i\n", __func__, port);
|
||||
@@ -1186,23 +1369,18 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
|
||||
switch (state->interface) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
/* RGMII mode means no delay so don't enable the delay */
|
||||
qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
/* RGMII_ID needs internal delay. This is enabled through
|
||||
* PORT5_PAD_CTRL for all ports, rather than individual port
|
||||
* registers
|
||||
qca8k_write(priv, reg, QCA8K_PORT_PAD_RGMII_EN);
|
||||
|
||||
/* Configure rgmii delay */
|
||||
qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg);
|
||||
|
||||
/* QCA8337 requires to set rgmii rx delay for all ports.
|
||||
* This is enabled through PORT5_PAD_CTRL for all ports,
|
||||
* rather than individual port registers.
|
||||
*/
|
||||
qca8k_write(priv, reg,
|
||||
QCA8K_PORT_PAD_RGMII_EN |
|
||||
QCA8K_PORT_PAD_RGMII_TX_DELAY(priv->rgmii_tx_delay) |
|
||||
QCA8K_PORT_PAD_RGMII_RX_DELAY(priv->rgmii_rx_delay) |
|
||||
QCA8K_PORT_PAD_RGMII_TX_DELAY_EN |
|
||||
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
|
||||
/* QCA8337 requires to set rgmii rx delay */
|
||||
if (priv->switch_id == QCA8K_ID_QCA8337)
|
||||
qca8k_write(priv, QCA8K_REG_PORT5_PAD_CTRL,
|
||||
QCA8K_PORT_PAD_RGMII_RX_DELAY_EN);
|
||||
@@ -1227,8 +1405,11 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
|
||||
QCA8K_SGMII_EN_TX | QCA8K_SGMII_EN_SD;
|
||||
val |= QCA8K_SGMII_EN_SD;
|
||||
|
||||
if (priv->ports_config.sgmii_enable_pll)
|
||||
val |= QCA8K_SGMII_EN_PLL | QCA8K_SGMII_EN_RX |
|
||||
QCA8K_SGMII_EN_TX;
|
||||
|
||||
if (dsa_is_cpu_port(ds, port)) {
|
||||
/* CPU port, we're talking to the CPU MAC, be a PHY */
|
||||
@@ -1243,6 +1424,35 @@ qca8k_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
}
|
||||
|
||||
qca8k_write(priv, QCA8K_REG_SGMII_CTRL, val);
|
||||
|
||||
/* For qca8327/qca8328/qca8334/qca8338 sgmii is unique and
|
||||
* falling edge is set writing in the PORT0 PAD reg
|
||||
*/
|
||||
if (priv->switch_id == QCA8K_ID_QCA8327 ||
|
||||
priv->switch_id == QCA8K_ID_QCA8337)
|
||||
reg = QCA8K_REG_PORT0_PAD_CTRL;
|
||||
|
||||
val = 0;
|
||||
|
||||
/* SGMII Clock phase configuration */
|
||||
if (priv->ports_config.sgmii_rx_clk_falling_edge)
|
||||
val |= QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE;
|
||||
|
||||
if (priv->ports_config.sgmii_tx_clk_falling_edge)
|
||||
val |= QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE;
|
||||
|
||||
if (val)
|
||||
ret = qca8k_rmw(priv, reg,
|
||||
QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE |
|
||||
QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE,
|
||||
val);
|
||||
|
||||
/* From original code is reported port instability as SGMII also
|
||||
* require delay set. Apply advised values here or take them from DT.
|
||||
*/
|
||||
if (state->interface == PHY_INTERFACE_MODE_SGMII)
|
||||
qca8k_mac_config_setup_internal_delay(priv, cpu_port_index, reg);
|
||||
|
||||
break;
|
||||
default:
|
||||
dev_err(ds->dev, "xMII mode %s not supported for port %d\n",
|
||||
@@ -1522,10 +1732,15 @@ static int
|
||||
qca8k_port_bridge_join(struct dsa_switch *ds, int port, struct net_device *br)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
int port_mask = BIT(QCA8K_CPU_PORT);
|
||||
int port_mask, cpu_port;
|
||||
int i, ret;
|
||||
|
||||
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
|
||||
cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
|
||||
port_mask = BIT(cpu_port);
|
||||
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
if (dsa_is_cpu_port(ds, i))
|
||||
continue;
|
||||
if (dsa_to_port(ds, i)->bridge_dev != br)
|
||||
continue;
|
||||
/* Add this port to the portvlan mask of the other ports
|
||||
@@ -1551,9 +1766,13 @@ static void
|
||||
qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
|
||||
{
|
||||
struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
|
||||
int i;
|
||||
int cpu_port, i;
|
||||
|
||||
for (i = 1; i < QCA8K_NUM_PORTS; i++) {
|
||||
cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
|
||||
|
||||
for (i = 0; i < QCA8K_NUM_PORTS; i++) {
|
||||
if (dsa_is_cpu_port(ds, i))
|
||||
continue;
|
||||
if (dsa_to_port(ds, i)->bridge_dev != br)
|
||||
continue;
|
||||
/* Remove this port to the portvlan mask of the other ports
|
||||
@@ -1568,7 +1787,7 @@ qca8k_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br)
|
||||
* this port
|
||||
*/
|
||||
qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port),
|
||||
QCA8K_PORT_LOOKUP_MEMBER, BIT(QCA8K_CPU_PORT));
|
||||
QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port));
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1939,7 +2158,12 @@ static int qca8k_resume(struct device *dev)
|
||||
static SIMPLE_DEV_PM_OPS(qca8k_pm_ops,
|
||||
qca8k_suspend, qca8k_resume);
|
||||
|
||||
static const struct qca8k_match_data qca832x = {
|
||||
static const struct qca8k_match_data qca8327 = {
|
||||
.id = QCA8K_ID_QCA8327,
|
||||
.reduced_package = true,
|
||||
};
|
||||
|
||||
static const struct qca8k_match_data qca8328 = {
|
||||
.id = QCA8K_ID_QCA8327,
|
||||
};
|
||||
|
||||
@@ -1948,7 +2172,8 @@ static const struct qca8k_match_data qca833x = {
|
||||
};
|
||||
|
||||
static const struct of_device_id qca8k_of_match[] = {
|
||||
{ .compatible = "qca,qca8327", .data = &qca832x },
|
||||
{ .compatible = "qca,qca8327", .data = &qca8327 },
|
||||
{ .compatible = "qca,qca8328", .data = &qca8328 },
|
||||
{ .compatible = "qca,qca8334", .data = &qca833x },
|
||||
{ .compatible = "qca,qca8337", .data = &qca833x },
|
||||
{ /* sentinel */ },
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#define QCA8K_NUM_PORTS 7
|
||||
#define QCA8K_NUM_CPU_PORTS 2
|
||||
#define QCA8K_MAX_MTU 9000
|
||||
|
||||
#define PHY_ID_QCA8327 0x004dd034
|
||||
@@ -24,8 +25,6 @@
|
||||
|
||||
#define QCA8K_NUM_FDB_RECORDS 2048
|
||||
|
||||
#define QCA8K_CPU_PORT 0
|
||||
|
||||
#define QCA8K_PORT_VID_DEF 1
|
||||
|
||||
/* Global control registers */
|
||||
@@ -35,16 +34,26 @@
|
||||
#define QCA8K_MASK_CTRL_DEVICE_ID_MASK GENMASK(15, 8)
|
||||
#define QCA8K_MASK_CTRL_DEVICE_ID(x) ((x) >> 8)
|
||||
#define QCA8K_REG_PORT0_PAD_CTRL 0x004
|
||||
#define QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE BIT(19)
|
||||
#define QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE BIT(18)
|
||||
#define QCA8K_REG_PORT5_PAD_CTRL 0x008
|
||||
#define QCA8K_REG_PORT6_PAD_CTRL 0x00c
|
||||
#define QCA8K_PORT_PAD_RGMII_EN BIT(26)
|
||||
#define QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK GENMASK(23, 22)
|
||||
#define QCA8K_PORT_PAD_RGMII_TX_DELAY(x) ((x) << 22)
|
||||
#define QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK GENMASK(21, 20)
|
||||
#define QCA8K_PORT_PAD_RGMII_RX_DELAY(x) ((x) << 20)
|
||||
#define QCA8K_PORT_PAD_RGMII_TX_DELAY_EN BIT(25)
|
||||
#define QCA8K_PORT_PAD_RGMII_RX_DELAY_EN BIT(24)
|
||||
#define QCA8K_MAX_DELAY 3
|
||||
#define QCA8K_PORT_PAD_SGMII_EN BIT(7)
|
||||
#define QCA8K_REG_PWS 0x010
|
||||
#define QCA8K_PWS_POWER_ON_SEL BIT(31)
|
||||
/* This reg is only valid for QCA832x and toggle the package
|
||||
* type from 176 pin (by default) to 148 pin used on QCA8327
|
||||
*/
|
||||
#define QCA8327_PWS_PACKAGE148_EN BIT(30)
|
||||
#define QCA8K_PWS_LED_OPEN_EN_CSR BIT(24)
|
||||
#define QCA8K_PWS_SERDES_AEN_DIS BIT(7)
|
||||
#define QCA8K_REG_MODULE_EN 0x030
|
||||
#define QCA8K_MODULE_EN_MIB BIT(0)
|
||||
@@ -100,6 +109,11 @@
|
||||
#define QCA8K_SGMII_MODE_CTRL_PHY (1 << 22)
|
||||
#define QCA8K_SGMII_MODE_CTRL_MAC (2 << 22)
|
||||
|
||||
/* MAC_PWR_SEL registers */
|
||||
#define QCA8K_REG_MAC_PWR_SEL 0x0e4
|
||||
#define QCA8K_MAC_PWR_RGMII1_1_8V BIT(18)
|
||||
#define QCA8K_MAC_PWR_RGMII0_1_8V BIT(19)
|
||||
|
||||
/* EEE control registers */
|
||||
#define QCA8K_REG_EEE_CTRL 0x100
|
||||
#define QCA8K_REG_EEE_CTRL_LPI_EN(_i) ((_i + 1) * 2)
|
||||
@@ -248,14 +262,27 @@ struct ar8xxx_port_status {
|
||||
|
||||
struct qca8k_match_data {
|
||||
u8 id;
|
||||
bool reduced_package;
|
||||
};
|
||||
|
||||
enum {
|
||||
QCA8K_CPU_PORT0,
|
||||
QCA8K_CPU_PORT6,
|
||||
};
|
||||
|
||||
struct qca8k_ports_config {
|
||||
bool sgmii_rx_clk_falling_edge;
|
||||
bool sgmii_tx_clk_falling_edge;
|
||||
bool sgmii_enable_pll;
|
||||
u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
|
||||
u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
|
||||
};
|
||||
|
||||
struct qca8k_priv {
|
||||
u8 switch_id;
|
||||
u8 switch_revision;
|
||||
u8 rgmii_tx_delay;
|
||||
u8 rgmii_rx_delay;
|
||||
bool legacy_phy_port_mapping;
|
||||
struct qca8k_ports_config ports_config;
|
||||
struct regmap *regmap;
|
||||
struct mii_bus *bus;
|
||||
struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
|
||||
|
||||
@@ -501,6 +501,10 @@ static const struct of_device_id realtek_smi_of_match[] = {
|
||||
.compatible = "realtek,rtl8366s",
|
||||
.data = NULL,
|
||||
},
|
||||
{
|
||||
.compatible = "realtek,rtl8365mb",
|
||||
.data = &rtl8365mb_variant,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, realtek_smi_of_match);
|
||||
|
||||
@@ -140,5 +140,6 @@ int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset);
|
||||
void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
|
||||
|
||||
extern const struct realtek_smi_variant rtl8366rb_variant;
|
||||
extern const struct realtek_smi_variant rtl8365mb_variant;
|
||||
|
||||
#endif /* _REALTEK_SMI_H */
|
||||
|
||||
1982
drivers/net/dsa/rtl8365mb.c
Normal file
1982
drivers/net/dsa/rtl8365mb.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1345,7 +1345,7 @@ rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
|
||||
default:
|
||||
dev_err(smi->dev, "unknown bridge state requested\n");
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/* Set the same status for the port on all the FIDs */
|
||||
for (i = 0; i < RTL8366RB_NUM_FIDS; i++) {
|
||||
|
||||
@@ -20,6 +20,27 @@
|
||||
#define SJA1105_AGEING_TIME_MS(ms) ((ms) / 10)
|
||||
#define SJA1105_NUM_L2_POLICERS SJA1110_MAX_L2_POLICING_COUNT
|
||||
|
||||
/* Calculated assuming 1Gbps, where the clock has 125 MHz (8 ns period)
|
||||
* To avoid floating point operations, we'll multiply the degrees by 10
|
||||
* to get a "phase" and get 1 decimal point precision.
|
||||
*/
|
||||
#define SJA1105_RGMII_DELAY_PS_TO_PHASE(ps) \
|
||||
(((ps) * 360) / 800)
|
||||
#define SJA1105_RGMII_DELAY_PHASE_TO_PS(phase) \
|
||||
((800 * (phase)) / 360)
|
||||
#define SJA1105_RGMII_DELAY_PHASE_TO_HW(phase) \
|
||||
(((phase) - 738) / 9)
|
||||
#define SJA1105_RGMII_DELAY_PS_TO_HW(ps) \
|
||||
SJA1105_RGMII_DELAY_PHASE_TO_HW(SJA1105_RGMII_DELAY_PS_TO_PHASE(ps))
|
||||
|
||||
/* Valid range in degrees is a value between 73.8 and 101.7
|
||||
* in 0.9 degree increments
|
||||
*/
|
||||
#define SJA1105_RGMII_DELAY_MIN_PS \
|
||||
SJA1105_RGMII_DELAY_PHASE_TO_PS(738)
|
||||
#define SJA1105_RGMII_DELAY_MAX_PS \
|
||||
SJA1105_RGMII_DELAY_PHASE_TO_PS(1017)
|
||||
|
||||
typedef enum {
|
||||
SPI_READ = 0,
|
||||
SPI_WRITE = 1,
|
||||
@@ -222,8 +243,8 @@ struct sja1105_flow_block {
|
||||
|
||||
struct sja1105_private {
|
||||
struct sja1105_static_config static_config;
|
||||
bool rgmii_rx_delay[SJA1105_MAX_NUM_PORTS];
|
||||
bool rgmii_tx_delay[SJA1105_MAX_NUM_PORTS];
|
||||
int rgmii_rx_delay_ps[SJA1105_MAX_NUM_PORTS];
|
||||
int rgmii_tx_delay_ps[SJA1105_MAX_NUM_PORTS];
|
||||
phy_interface_t phy_mode[SJA1105_MAX_NUM_PORTS];
|
||||
bool fixed_link[SJA1105_MAX_NUM_PORTS];
|
||||
unsigned long ucast_egress_floods;
|
||||
|
||||
@@ -498,17 +498,6 @@ sja1110_cfg_pad_mii_id_packing(void *buf, struct sja1105_cfg_pad_mii_id *cmd,
|
||||
sja1105_packing(buf, &cmd->txc_pd, 0, 0, size, op);
|
||||
}
|
||||
|
||||
/* Valid range in degrees is an integer between 73.8 and 101.7 */
|
||||
static u64 sja1105_rgmii_delay(u64 phase)
|
||||
{
|
||||
/* UM11040.pdf: The delay in degree phase is 73.8 + delay_tune * 0.9.
|
||||
* To avoid floating point operations we'll multiply by 10
|
||||
* and get 1 decimal point precision.
|
||||
*/
|
||||
phase *= 10;
|
||||
return (phase - 738) / 9;
|
||||
}
|
||||
|
||||
/* The RGMII delay setup procedure is 2-step and gets called upon each
|
||||
* .phylink_mac_config. Both are strategic.
|
||||
* The reason is that the RX Tunable Delay Line of the SJA1105 MAC has issues
|
||||
@@ -521,13 +510,15 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port)
|
||||
const struct sja1105_private *priv = ctx;
|
||||
const struct sja1105_regs *regs = priv->info->regs;
|
||||
struct sja1105_cfg_pad_mii_id pad_mii_id = {0};
|
||||
int rx_delay = priv->rgmii_rx_delay_ps[port];
|
||||
int tx_delay = priv->rgmii_tx_delay_ps[port];
|
||||
u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
|
||||
int rc;
|
||||
|
||||
if (priv->rgmii_rx_delay[port])
|
||||
pad_mii_id.rxc_delay = sja1105_rgmii_delay(90);
|
||||
if (priv->rgmii_tx_delay[port])
|
||||
pad_mii_id.txc_delay = sja1105_rgmii_delay(90);
|
||||
if (rx_delay)
|
||||
pad_mii_id.rxc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(rx_delay);
|
||||
if (tx_delay)
|
||||
pad_mii_id.txc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(tx_delay);
|
||||
|
||||
/* Stage 1: Turn the RGMII delay lines off. */
|
||||
pad_mii_id.rxc_bypass = 1;
|
||||
@@ -542,11 +533,11 @@ int sja1105pqrs_setup_rgmii_delay(const void *ctx, int port)
|
||||
return rc;
|
||||
|
||||
/* Stage 2: Turn the RGMII delay lines on. */
|
||||
if (priv->rgmii_rx_delay[port]) {
|
||||
if (rx_delay) {
|
||||
pad_mii_id.rxc_bypass = 0;
|
||||
pad_mii_id.rxc_pd = 0;
|
||||
}
|
||||
if (priv->rgmii_tx_delay[port]) {
|
||||
if (tx_delay) {
|
||||
pad_mii_id.txc_bypass = 0;
|
||||
pad_mii_id.txc_pd = 0;
|
||||
}
|
||||
@@ -561,20 +552,22 @@ int sja1110_setup_rgmii_delay(const void *ctx, int port)
|
||||
const struct sja1105_private *priv = ctx;
|
||||
const struct sja1105_regs *regs = priv->info->regs;
|
||||
struct sja1105_cfg_pad_mii_id pad_mii_id = {0};
|
||||
int rx_delay = priv->rgmii_rx_delay_ps[port];
|
||||
int tx_delay = priv->rgmii_tx_delay_ps[port];
|
||||
u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0};
|
||||
|
||||
pad_mii_id.rxc_pd = 1;
|
||||
pad_mii_id.txc_pd = 1;
|
||||
|
||||
if (priv->rgmii_rx_delay[port]) {
|
||||
pad_mii_id.rxc_delay = sja1105_rgmii_delay(90);
|
||||
if (rx_delay) {
|
||||
pad_mii_id.rxc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(rx_delay);
|
||||
/* The "BYPASS" bit in SJA1110 is actually a "don't bypass" */
|
||||
pad_mii_id.rxc_bypass = 1;
|
||||
pad_mii_id.rxc_pd = 0;
|
||||
}
|
||||
|
||||
if (priv->rgmii_tx_delay[port]) {
|
||||
pad_mii_id.txc_delay = sja1105_rgmii_delay(90);
|
||||
if (tx_delay) {
|
||||
pad_mii_id.txc_delay = SJA1105_RGMII_DELAY_PS_TO_HW(tx_delay);
|
||||
pad_mii_id.txc_bypass = 1;
|
||||
pad_mii_id.txc_pd = 0;
|
||||
}
|
||||
|
||||
@@ -1109,27 +1109,78 @@ static int sja1105_static_config_load(struct sja1105_private *priv)
|
||||
return sja1105_static_config_upload(priv);
|
||||
}
|
||||
|
||||
static int sja1105_parse_rgmii_delays(struct sja1105_private *priv)
|
||||
/* This is the "new way" for a MAC driver to configure its RGMII delay lines,
|
||||
* based on the explicit "rx-internal-delay-ps" and "tx-internal-delay-ps"
|
||||
* properties. It has the advantage of working with fixed links and with PHYs
|
||||
* that apply RGMII delays too, and the MAC driver needs not perform any
|
||||
* special checks.
|
||||
*
|
||||
* Previously we were acting upon the "phy-mode" property when we were
|
||||
* operating in fixed-link, basically acting as a PHY, but with a reversed
|
||||
* interpretation: PHY_INTERFACE_MODE_RGMII_TXID means that the MAC should
|
||||
* behave as if it is connected to a PHY which has applied RGMII delays in the
|
||||
* TX direction. So if anything, RX delays should have been added by the MAC,
|
||||
* but we were adding TX delays.
|
||||
*
|
||||
* If the "{rx,tx}-internal-delay-ps" properties are not specified, we fall
|
||||
* back to the legacy behavior and apply delays on fixed-link ports based on
|
||||
* the reverse interpretation of the phy-mode. This is a deviation from the
|
||||
* expected default behavior which is to simply apply no delays. To achieve
|
||||
* that behavior with the new bindings, it is mandatory to specify
|
||||
* "{rx,tx}-internal-delay-ps" with a value of 0.
|
||||
*/
|
||||
static int sja1105_parse_rgmii_delays(struct sja1105_private *priv, int port,
|
||||
struct device_node *port_dn)
|
||||
{
|
||||
struct dsa_switch *ds = priv->ds;
|
||||
int port;
|
||||
phy_interface_t phy_mode = priv->phy_mode[port];
|
||||
struct device *dev = &priv->spidev->dev;
|
||||
int rx_delay = -1, tx_delay = -1;
|
||||
|
||||
for (port = 0; port < ds->num_ports; port++) {
|
||||
if (!priv->fixed_link[port])
|
||||
continue;
|
||||
if (!phy_interface_mode_is_rgmii(phy_mode))
|
||||
return 0;
|
||||
|
||||
if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_RXID ||
|
||||
priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID)
|
||||
priv->rgmii_rx_delay[port] = true;
|
||||
of_property_read_u32(port_dn, "rx-internal-delay-ps", &rx_delay);
|
||||
of_property_read_u32(port_dn, "tx-internal-delay-ps", &tx_delay);
|
||||
|
||||
if (priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_TXID ||
|
||||
priv->phy_mode[port] == PHY_INTERFACE_MODE_RGMII_ID)
|
||||
priv->rgmii_tx_delay[port] = true;
|
||||
if (rx_delay == -1 && tx_delay == -1 && priv->fixed_link[port]) {
|
||||
dev_warn(dev,
|
||||
"Port %d interpreting RGMII delay settings based on \"phy-mode\" property, "
|
||||
"please update device tree to specify \"rx-internal-delay-ps\" and "
|
||||
"\"tx-internal-delay-ps\"",
|
||||
port);
|
||||
|
||||
if ((priv->rgmii_rx_delay[port] || priv->rgmii_tx_delay[port]) &&
|
||||
!priv->info->setup_rgmii_delay)
|
||||
return -EINVAL;
|
||||
if (phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
|
||||
phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
|
||||
rx_delay = 2000;
|
||||
|
||||
if (phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
|
||||
phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
|
||||
tx_delay = 2000;
|
||||
}
|
||||
|
||||
if (rx_delay < 0)
|
||||
rx_delay = 0;
|
||||
if (tx_delay < 0)
|
||||
tx_delay = 0;
|
||||
|
||||
if ((rx_delay || tx_delay) && !priv->info->setup_rgmii_delay) {
|
||||
dev_err(dev, "Chip cannot apply RGMII delays\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((rx_delay && rx_delay < SJA1105_RGMII_DELAY_MIN_PS) ||
|
||||
(tx_delay && tx_delay < SJA1105_RGMII_DELAY_MIN_PS) ||
|
||||
(rx_delay > SJA1105_RGMII_DELAY_MAX_PS) ||
|
||||
(tx_delay > SJA1105_RGMII_DELAY_MAX_PS)) {
|
||||
dev_err(dev,
|
||||
"port %d RGMII delay values out of range, must be between %d and %d ps\n",
|
||||
port, SJA1105_RGMII_DELAY_MIN_PS, SJA1105_RGMII_DELAY_MAX_PS);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
priv->rgmii_rx_delay_ps[port] = rx_delay;
|
||||
priv->rgmii_tx_delay_ps[port] = tx_delay;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1180,6 +1231,10 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
|
||||
}
|
||||
|
||||
priv->phy_mode[index] = phy_mode;
|
||||
|
||||
err = sja1105_parse_rgmii_delays(priv, index, child);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3317,15 +3372,6 @@ static int sja1105_probe(struct spi_device *spi)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Error out early if internal delays are required through DT
|
||||
* and we can't apply them.
|
||||
*/
|
||||
rc = sja1105_parse_rgmii_delays(priv);
|
||||
if (rc < 0) {
|
||||
dev_err(ds->dev, "RGMII delay not supported\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_SCH_CBS)) {
|
||||
priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers,
|
||||
sizeof(struct sja1105_cbs_entry),
|
||||
|
||||
@@ -394,7 +394,8 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv,
|
||||
vl_lookup[k].vlanid = rule->key.vl.vid;
|
||||
vl_lookup[k].vlanprior = rule->key.vl.pcp;
|
||||
} else {
|
||||
u16 vid = dsa_8021q_rx_vid(priv->ds, port);
|
||||
struct dsa_port *dp = dsa_to_port(priv->ds, port);
|
||||
u16 vid = dsa_tag_8021q_rx_vid(dp);
|
||||
|
||||
vl_lookup[k].vlanid = vid;
|
||||
vl_lookup[k].vlanprior = 0;
|
||||
|
||||
@@ -567,6 +567,7 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
|
||||
{
|
||||
struct corkscrew_private *vp = netdev_priv(dev);
|
||||
unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
|
||||
__be16 addr[ETH_ALEN / 2];
|
||||
int i;
|
||||
int irq;
|
||||
|
||||
@@ -619,7 +620,6 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
|
||||
/* Read the station address from the EEPROM. */
|
||||
EL3WINDOW(0);
|
||||
for (i = 0; i < 0x18; i++) {
|
||||
__be16 *phys_addr = (__be16 *) dev->dev_addr;
|
||||
int timer;
|
||||
outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
|
||||
/* Pause for at least 162 us. for the read to take place. */
|
||||
@@ -631,8 +631,9 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
|
||||
eeprom[i] = inw(ioaddr + Wn0EepromData);
|
||||
checksum ^= eeprom[i];
|
||||
if (i < 3)
|
||||
phys_addr[i] = htons(eeprom[i]);
|
||||
addr[i] = htons(eeprom[i]);
|
||||
}
|
||||
eth_hw_addr_set(dev, (u8 *)addr);
|
||||
checksum = (checksum ^ (checksum >> 8)) & 0xff;
|
||||
if (checksum != 0x00)
|
||||
pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
|
||||
|
||||
@@ -305,15 +305,13 @@ static int tc574_config(struct pcmcia_device *link)
|
||||
struct net_device *dev = link->priv;
|
||||
struct el3_private *lp = netdev_priv(dev);
|
||||
int ret, i, j;
|
||||
__be16 addr[ETH_ALEN / 2];
|
||||
unsigned int ioaddr;
|
||||
__be16 *phys_addr;
|
||||
char *cardname;
|
||||
__u32 config;
|
||||
u8 *buf;
|
||||
size_t len;
|
||||
|
||||
phys_addr = (__be16 *)dev->dev_addr;
|
||||
|
||||
dev_dbg(&link->dev, "3c574_config()\n");
|
||||
|
||||
link->io_lines = 16;
|
||||
@@ -347,19 +345,20 @@ static int tc574_config(struct pcmcia_device *link)
|
||||
len = pcmcia_get_tuple(link, 0x88, &buf);
|
||||
if (buf && len >= 6) {
|
||||
for (i = 0; i < 3; i++)
|
||||
phys_addr[i] = htons(le16_to_cpu(buf[i * 2]));
|
||||
addr[i] = htons(le16_to_cpu(buf[i * 2]));
|
||||
kfree(buf);
|
||||
} else {
|
||||
kfree(buf); /* 0 < len < 6 */
|
||||
EL3WINDOW(0);
|
||||
for (i = 0; i < 3; i++)
|
||||
phys_addr[i] = htons(read_eeprom(ioaddr, i + 10));
|
||||
if (phys_addr[0] == htons(0x6060)) {
|
||||
addr[i] = htons(read_eeprom(ioaddr, i + 10));
|
||||
if (addr[0] == htons(0x6060)) {
|
||||
pr_notice("IO port conflict at 0x%03lx-0x%03lx\n",
|
||||
dev->base_addr, dev->base_addr+15);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
eth_hw_addr_set(dev, (u8 *)addr);
|
||||
if (link->prod_id[1])
|
||||
cardname = link->prod_id[1];
|
||||
else
|
||||
|
||||
@@ -237,8 +237,8 @@ static void tc589_detach(struct pcmcia_device *link)
|
||||
static int tc589_config(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
__be16 *phys_addr;
|
||||
int ret, i, j, multi = 0, fifo;
|
||||
__be16 addr[ETH_ALEN / 2];
|
||||
unsigned int ioaddr;
|
||||
static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
|
||||
u8 *buf;
|
||||
@@ -246,7 +246,6 @@ static int tc589_config(struct pcmcia_device *link)
|
||||
|
||||
dev_dbg(&link->dev, "3c589_config\n");
|
||||
|
||||
phys_addr = (__be16 *)dev->dev_addr;
|
||||
/* Is this a 3c562? */
|
||||
if (link->manf_id != MANFID_3COM)
|
||||
dev_info(&link->dev, "hmmm, is this really a 3Com card??\n");
|
||||
@@ -285,18 +284,19 @@ static int tc589_config(struct pcmcia_device *link)
|
||||
len = pcmcia_get_tuple(link, 0x88, &buf);
|
||||
if (buf && len >= 6) {
|
||||
for (i = 0; i < 3; i++)
|
||||
phys_addr[i] = htons(le16_to_cpu(buf[i*2]));
|
||||
addr[i] = htons(le16_to_cpu(buf[i*2]));
|
||||
kfree(buf);
|
||||
} else {
|
||||
kfree(buf); /* 0 < len < 6 */
|
||||
for (i = 0; i < 3; i++)
|
||||
phys_addr[i] = htons(read_eeprom(ioaddr, i));
|
||||
if (phys_addr[0] == htons(0x6060)) {
|
||||
addr[i] = htons(read_eeprom(ioaddr, i));
|
||||
if (addr[0] == htons(0x6060)) {
|
||||
dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n",
|
||||
dev->base_addr, dev->base_addr+15);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
eth_hw_addr_set(dev, (u8 *)addr);
|
||||
|
||||
/* The address and resource configuration register aren't loaded from
|
||||
* the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version.
|
||||
|
||||
@@ -1091,6 +1091,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
|
||||
struct vortex_private *vp;
|
||||
int option;
|
||||
unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
|
||||
__be16 addr[ETH_ALEN / 2];
|
||||
int i, step;
|
||||
struct net_device *dev;
|
||||
static int printed_version;
|
||||
@@ -1284,7 +1285,8 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
|
||||
if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO))
|
||||
pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
|
||||
for (i = 0; i < 3; i++)
|
||||
((__be16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
|
||||
addr[i] = htons(eeprom[i + 10]);
|
||||
eth_hw_addr_set(dev, (u8 *)addr);
|
||||
if (print_info)
|
||||
pr_cont(" %pM", dev->dev_addr);
|
||||
/* Unfortunately an all zero eeprom passes the checksum and this
|
||||
|
||||
@@ -320,8 +320,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
|
||||
i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
|
||||
if (i) return i;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
dev->dev_addr[i] = SA_prom[i];
|
||||
eth_hw_addr_set(dev, SA_prom);
|
||||
|
||||
pr_cont(" %pM\n", dev->dev_addr);
|
||||
|
||||
|
||||
@@ -748,11 +748,13 @@ static int ax_init_dev(struct net_device *dev)
|
||||
|
||||
/* load the mac-address from the device */
|
||||
if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
|
||||
ei_local->mem + E8390_CMD); /* 0x61 */
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
dev->dev_addr[i] =
|
||||
ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
|
||||
addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
|
||||
eth_hw_addr_set(dev, addr);
|
||||
}
|
||||
|
||||
if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
|
||||
|
||||
@@ -187,6 +187,7 @@ static int get_prom(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
unsigned int ioaddr = dev->base_addr;
|
||||
u8 addr[ETH_ALEN];
|
||||
int i, j;
|
||||
|
||||
/* This is based on drivers/net/ethernet/8390/ne.c */
|
||||
@@ -220,9 +221,11 @@ static int get_prom(struct pcmcia_device *link)
|
||||
|
||||
for (i = 0; i < 6; i += 2) {
|
||||
j = inw(ioaddr + AXNET_DATAPORT);
|
||||
dev->dev_addr[i] = j & 0xff;
|
||||
dev->dev_addr[i+1] = j >> 8;
|
||||
addr[i] = j & 0xff;
|
||||
addr[i+1] = j >> 8;
|
||||
}
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
return 1;
|
||||
} /* get_prom */
|
||||
|
||||
|
||||
@@ -374,8 +374,7 @@ static int mcf8390_init(struct net_device *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
dev->dev_addr[i] = SA_prom[i];
|
||||
eth_hw_addr_set(dev, SA_prom);
|
||||
|
||||
netdev_dbg(dev, "Found ethernet address: %pM\n", dev->dev_addr);
|
||||
|
||||
|
||||
@@ -500,9 +500,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
|
||||
|
||||
dev->base_addr = ioaddr;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++) {
|
||||
dev->dev_addr[i] = SA_prom[i];
|
||||
}
|
||||
eth_hw_addr_set(dev, SA_prom);
|
||||
|
||||
pr_cont("%pM\n", dev->dev_addr);
|
||||
|
||||
|
||||
@@ -278,6 +278,7 @@ static struct hw_info *get_hwinfo(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
u_char __iomem *base, *virt;
|
||||
u8 addr[ETH_ALEN];
|
||||
int i, j;
|
||||
|
||||
/* Allocate a small memory window */
|
||||
@@ -302,7 +303,8 @@ static struct hw_info *get_hwinfo(struct pcmcia_device *link)
|
||||
(readb(base+2) == hw_info[i].a1) &&
|
||||
(readb(base+4) == hw_info[i].a2)) {
|
||||
for (j = 0; j < 6; j++)
|
||||
dev->dev_addr[j] = readb(base + (j<<1));
|
||||
addr[j] = readb(base + (j<<1));
|
||||
eth_hw_addr_set(dev, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -324,6 +326,7 @@ static struct hw_info *get_prom(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
unsigned int ioaddr = dev->base_addr;
|
||||
u8 addr[ETH_ALEN];
|
||||
u_char prom[32];
|
||||
int i, j;
|
||||
|
||||
@@ -362,7 +365,8 @@ static struct hw_info *get_prom(struct pcmcia_device *link)
|
||||
}
|
||||
if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
|
||||
for (j = 0; j < 6; j++)
|
||||
dev->dev_addr[j] = prom[j<<1];
|
||||
addr[j] = prom[j<<1];
|
||||
eth_hw_addr_set(dev, addr);
|
||||
return (i < NR_INFO) ? hw_info+i : &default_info;
|
||||
}
|
||||
return NULL;
|
||||
@@ -377,6 +381,7 @@ static struct hw_info *get_prom(struct pcmcia_device *link)
|
||||
static struct hw_info *get_dl10019(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
u8 addr[ETH_ALEN];
|
||||
int i;
|
||||
u_char sum;
|
||||
|
||||
@@ -385,7 +390,8 @@ static struct hw_info *get_dl10019(struct pcmcia_device *link)
|
||||
if (sum != 0xff)
|
||||
return NULL;
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
|
||||
addr[i] = inb_p(dev->base_addr + 0x14 + i);
|
||||
eth_hw_addr_set(dev, addr);
|
||||
i = inb(dev->base_addr + 0x1f);
|
||||
return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info;
|
||||
}
|
||||
@@ -400,6 +406,7 @@ static struct hw_info *get_ax88190(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
unsigned int ioaddr = dev->base_addr;
|
||||
u8 addr[ETH_ALEN];
|
||||
int i, j;
|
||||
|
||||
/* Not much of a test, but the alternatives are messy */
|
||||
@@ -413,9 +420,10 @@ static struct hw_info *get_ax88190(struct pcmcia_device *link)
|
||||
|
||||
for (i = 0; i < 6; i += 2) {
|
||||
j = inw(ioaddr + PCNET_DATAPORT);
|
||||
dev->dev_addr[i] = j & 0xff;
|
||||
dev->dev_addr[i+1] = j >> 8;
|
||||
addr[i] = j & 0xff;
|
||||
addr[i+1] = j >> 8;
|
||||
}
|
||||
eth_hw_addr_set(dev, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -430,6 +438,7 @@ static struct hw_info *get_ax88190(struct pcmcia_device *link)
|
||||
static struct hw_info *get_hwired(struct pcmcia_device *link)
|
||||
{
|
||||
struct net_device *dev = link->priv;
|
||||
u8 addr[ETH_ALEN];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
@@ -438,7 +447,8 @@ static struct hw_info *get_hwired(struct pcmcia_device *link)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = hw_addr[i];
|
||||
addr[i] = hw_addr[i];
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
return &default_info;
|
||||
} /* get_hwired */
|
||||
|
||||
@@ -104,8 +104,8 @@ STNIC_WRITE (int reg, byte val)
|
||||
static int __init stnic_probe(void)
|
||||
{
|
||||
struct net_device *dev;
|
||||
int i, err;
|
||||
struct ei_device *ei_local;
|
||||
int err;
|
||||
|
||||
/* If we are not running on a SolutionEngine, give up now */
|
||||
if (! MACH_SE)
|
||||
@@ -119,8 +119,7 @@ static int __init stnic_probe(void)
|
||||
#ifdef CONFIG_SH_STANDARD_BIOS
|
||||
sh_bios_get_node_addr (stnic_eadr);
|
||||
#endif
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
dev->dev_addr[i] = stnic_eadr[i];
|
||||
eth_hw_addr_set(dev, stnic_eadr);
|
||||
|
||||
/* Set the base address to point to the NIC, not the "real" base! */
|
||||
dev->base_addr = 0x1000;
|
||||
|
||||
@@ -364,8 +364,7 @@ static int zorro8390_init(struct net_device *dev, unsigned long board,
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
dev->dev_addr[i] = SA_prom[i];
|
||||
eth_hw_addr_set(dev, SA_prom);
|
||||
|
||||
pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ source "drivers/net/ethernet/apm/Kconfig"
|
||||
source "drivers/net/ethernet/apple/Kconfig"
|
||||
source "drivers/net/ethernet/aquantia/Kconfig"
|
||||
source "drivers/net/ethernet/arc/Kconfig"
|
||||
source "drivers/net/ethernet/asix/Kconfig"
|
||||
source "drivers/net/ethernet/atheros/Kconfig"
|
||||
source "drivers/net/ethernet/broadcom/Kconfig"
|
||||
source "drivers/net/ethernet/brocade/Kconfig"
|
||||
|
||||
@@ -19,6 +19,7 @@ obj-$(CONFIG_NET_XGENE) += apm/
|
||||
obj-$(CONFIG_NET_VENDOR_APPLE) += apple/
|
||||
obj-$(CONFIG_NET_VENDOR_AQUANTIA) += aquantia/
|
||||
obj-$(CONFIG_NET_VENDOR_ARC) += arc/
|
||||
obj-$(CONFIG_NET_VENDOR_ASIX) += asix/
|
||||
obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/
|
||||
obj-$(CONFIG_NET_VENDOR_CADENCE) += cadence/
|
||||
obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/
|
||||
|
||||
@@ -342,7 +342,7 @@ static u32 owl_emac_dma_cmd_stop(struct owl_emac_priv *priv)
|
||||
static void owl_emac_set_hw_mac_addr(struct net_device *netdev)
|
||||
{
|
||||
struct owl_emac_priv *priv = netdev_priv(netdev);
|
||||
u8 *mac_addr = netdev->dev_addr;
|
||||
const u8 *mac_addr = netdev->dev_addr;
|
||||
u32 addr_high, addr_low;
|
||||
|
||||
addr_high = mac_addr[0] << 8 | mac_addr[1];
|
||||
@@ -1385,7 +1385,7 @@ static void owl_emac_get_mac_addr(struct net_device *netdev)
|
||||
struct device *dev = netdev->dev.parent;
|
||||
int ret;
|
||||
|
||||
ret = eth_platform_get_mac_address(dev, netdev->dev_addr);
|
||||
ret = platform_get_ethdev_address(dev, netdev);
|
||||
if (!ret && is_valid_ether_addr(netdev->dev_addr))
|
||||
return;
|
||||
|
||||
|
||||
@@ -641,6 +641,7 @@ static int starfire_init_one(struct pci_dev *pdev,
|
||||
struct netdev_private *np;
|
||||
int i, irq, chip_idx = ent->driver_data;
|
||||
struct net_device *dev;
|
||||
u8 addr[ETH_ALEN];
|
||||
long ioaddr;
|
||||
void __iomem *base;
|
||||
int drv_flags, io_size;
|
||||
@@ -696,7 +697,8 @@ static int starfire_init_one(struct pci_dev *pdev,
|
||||
|
||||
/* Serial EEPROM reads are hidden by the hardware. */
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = readb(base + EEPROMCtrl + 20 - i);
|
||||
addr[i] = readb(base + EEPROMCtrl + 20 - i);
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
#if ! defined(final_version) /* Dump the EEPROM contents during development. */
|
||||
if (debug > 4)
|
||||
@@ -955,7 +957,7 @@ static int netdev_open(struct net_device *dev)
|
||||
writew(0, ioaddr + PerfFilterTable + 4);
|
||||
writew(0, ioaddr + PerfFilterTable + 8);
|
||||
for (i = 1; i < 16; i++) {
|
||||
__be16 *eaddrs = (__be16 *)dev->dev_addr;
|
||||
const __be16 *eaddrs = (const __be16 *)dev->dev_addr;
|
||||
void __iomem *setup_frm = ioaddr + PerfFilterTable + i * 16;
|
||||
writew(be16_to_cpu(eaddrs[2]), setup_frm); setup_frm += 4;
|
||||
writew(be16_to_cpu(eaddrs[1]), setup_frm); setup_frm += 4;
|
||||
@@ -1787,14 +1789,14 @@ static void set_rx_mode(struct net_device *dev)
|
||||
} else if (netdev_mc_count(dev) <= 14) {
|
||||
/* Use the 16 element perfect filter, skip first two entries. */
|
||||
void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16;
|
||||
__be16 *eaddrs;
|
||||
const __be16 *eaddrs;
|
||||
netdev_for_each_mc_addr(ha, dev) {
|
||||
eaddrs = (__be16 *) ha->addr;
|
||||
writew(be16_to_cpu(eaddrs[2]), filter_addr); filter_addr += 4;
|
||||
writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
|
||||
writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 8;
|
||||
}
|
||||
eaddrs = (__be16 *)dev->dev_addr;
|
||||
eaddrs = (const __be16 *)dev->dev_addr;
|
||||
i = netdev_mc_count(dev) + 2;
|
||||
while (i++ < 16) {
|
||||
writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4;
|
||||
@@ -1805,7 +1807,7 @@ static void set_rx_mode(struct net_device *dev)
|
||||
} else {
|
||||
/* Must use a multicast hash table. */
|
||||
void __iomem *filter_addr;
|
||||
__be16 *eaddrs;
|
||||
const __be16 *eaddrs;
|
||||
__le16 mc_filter[32] __attribute__ ((aligned(sizeof(long)))); /* Multicast hash filter */
|
||||
|
||||
memset(mc_filter, 0, sizeof(mc_filter));
|
||||
@@ -1819,7 +1821,7 @@ static void set_rx_mode(struct net_device *dev)
|
||||
}
|
||||
/* Clear the perfect filter list, skip first two entries. */
|
||||
filter_addr = ioaddr + PerfFilterTable + 2 * 16;
|
||||
eaddrs = (__be16 *)dev->dev_addr;
|
||||
eaddrs = (const __be16 *)dev->dev_addr;
|
||||
for (i = 2; i < 16; i++) {
|
||||
writew(be16_to_cpu(eaddrs[0]), filter_addr); filter_addr += 4;
|
||||
writew(be16_to_cpu(eaddrs[1]), filter_addr); filter_addr += 4;
|
||||
|
||||
@@ -1346,6 +1346,7 @@ static int greth_of_probe(struct platform_device *ofdev)
|
||||
int i;
|
||||
int err;
|
||||
int tmp;
|
||||
u8 addr[ETH_ALEN];
|
||||
unsigned long timeout;
|
||||
|
||||
dev = alloc_etherdev(sizeof(struct greth_private));
|
||||
@@ -1449,8 +1450,6 @@ static int greth_of_probe(struct platform_device *ofdev)
|
||||
break;
|
||||
}
|
||||
if (i == 6) {
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
err = of_get_mac_address(ofdev->dev.of_node, addr);
|
||||
if (!err) {
|
||||
for (i = 0; i < 6; i++)
|
||||
@@ -1464,7 +1463,8 @@ static int greth_of_probe(struct platform_device *ofdev)
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = macaddr[i];
|
||||
addr[i] = macaddr[i];
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
macaddr[5]++;
|
||||
|
||||
|
||||
@@ -1008,7 +1008,7 @@ static void slic_set_link_autoneg(struct slic_device *sdev)
|
||||
|
||||
static void slic_set_mac_address(struct slic_device *sdev)
|
||||
{
|
||||
u8 *addr = sdev->netdev->dev_addr;
|
||||
const u8 *addr = sdev->netdev->dev_addr;
|
||||
u32 val;
|
||||
|
||||
val = addr[5] | addr[4] << 8 | addr[3] << 16 | addr[2] << 24;
|
||||
|
||||
@@ -869,6 +869,7 @@ static int ace_init(struct net_device *dev)
|
||||
int board_idx, ecode = 0;
|
||||
short i;
|
||||
unsigned char cache_size;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
ap = netdev_priv(dev);
|
||||
regs = ap->regs;
|
||||
@@ -988,12 +989,13 @@ static int ace_init(struct net_device *dev)
|
||||
writel(mac1, ®s->MacAddrHi);
|
||||
writel(mac2, ®s->MacAddrLo);
|
||||
|
||||
dev->dev_addr[0] = (mac1 >> 8) & 0xff;
|
||||
dev->dev_addr[1] = mac1 & 0xff;
|
||||
dev->dev_addr[2] = (mac2 >> 24) & 0xff;
|
||||
dev->dev_addr[3] = (mac2 >> 16) & 0xff;
|
||||
dev->dev_addr[4] = (mac2 >> 8) & 0xff;
|
||||
dev->dev_addr[5] = mac2 & 0xff;
|
||||
addr[0] = (mac1 >> 8) & 0xff;
|
||||
addr[1] = mac1 & 0xff;
|
||||
addr[2] = (mac2 >> 24) & 0xff;
|
||||
addr[3] = (mac2 >> 16) & 0xff;
|
||||
addr[4] = (mac2 >> 8) & 0xff;
|
||||
addr[5] = mac2 & 0xff;
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
printk("MAC: %pM\n", dev->dev_addr);
|
||||
|
||||
@@ -2712,7 +2714,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p)
|
||||
struct ace_private *ap = netdev_priv(dev);
|
||||
struct ace_regs __iomem *regs = ap->regs;
|
||||
struct sockaddr *addr=p;
|
||||
u8 *da;
|
||||
const u8 *da;
|
||||
struct cmd cmd;
|
||||
|
||||
if(netif_running(dev))
|
||||
@@ -2720,7 +2722,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p)
|
||||
|
||||
eth_hw_addr_set(dev, addr->sa_data);
|
||||
|
||||
da = (u8 *)dev->dev_addr;
|
||||
da = (const u8 *)dev->dev_addr;
|
||||
|
||||
writel(da[0] << 8 | da[1], ®s->MacAddrHi);
|
||||
writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5],
|
||||
|
||||
@@ -849,7 +849,7 @@ static int init_phy(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr)
|
||||
static void tse_update_mac_addr(struct altera_tse_private *priv, const u8 *addr)
|
||||
{
|
||||
u32 msb;
|
||||
u32 lsb;
|
||||
|
||||
@@ -1743,6 +1743,7 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
|
||||
unsigned long reg_addr, reg_len;
|
||||
struct amd8111e_priv *lp;
|
||||
struct net_device *dev;
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
@@ -1809,7 +1810,8 @@ static int amd8111e_probe_one(struct pci_dev *pdev,
|
||||
|
||||
/* Initializing MAC address */
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
dev->dev_addr[i] = readb(lp->mmio + PADR + i);
|
||||
addr[i] = readb(lp->mmio + PADR + i);
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
/* Setting user defined parametrs */
|
||||
lp->ext_phy_option = speed_duplex[card_idx];
|
||||
|
||||
@@ -529,7 +529,8 @@ static void mace_write(mace_private *lp, unsigned int ioaddr, int reg,
|
||||
mace_init
|
||||
Resets the MACE chip.
|
||||
---------------------------------------------------------------------------- */
|
||||
static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
|
||||
static int mace_init(mace_private *lp, unsigned int ioaddr,
|
||||
const char *enet_addr)
|
||||
{
|
||||
int i;
|
||||
int ct = 0;
|
||||
|
||||
@@ -1595,6 +1595,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
struct net_device *dev;
|
||||
const struct pcnet32_access *a = NULL;
|
||||
u8 promaddr[ETH_ALEN];
|
||||
u8 addr[ETH_ALEN];
|
||||
int ret = -ENODEV;
|
||||
|
||||
/* reset the chip */
|
||||
@@ -1760,9 +1761,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
unsigned int val;
|
||||
val = a->read_csr(ioaddr, i + 12) & 0x0ffff;
|
||||
/* There may be endianness issues here. */
|
||||
dev->dev_addr[2 * i] = val & 0x0ff;
|
||||
dev->dev_addr[2 * i + 1] = (val >> 8) & 0x0ff;
|
||||
addr[2 * i] = val & 0x0ff;
|
||||
addr[2 * i + 1] = (val >> 8) & 0x0ff;
|
||||
}
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
/* read PROM address and compare with CSR address */
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
@@ -1780,8 +1782,11 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
|
||||
}
|
||||
|
||||
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
|
||||
if (!is_valid_ether_addr(dev->dev_addr))
|
||||
eth_zero_addr(dev->dev_addr);
|
||||
if (!is_valid_ether_addr(dev->dev_addr)) {
|
||||
static const u8 zero_addr[ETH_ALEN] = {};
|
||||
|
||||
eth_hw_addr_set(dev, zero_addr);
|
||||
}
|
||||
|
||||
if (pcnet32_debug & NETIF_MSG_PROBE) {
|
||||
pr_cont(" %pM", dev->dev_addr);
|
||||
|
||||
@@ -305,7 +305,6 @@ static int __init lance_probe( struct net_device *dev)
|
||||
unsigned long ioaddr;
|
||||
|
||||
struct lance_private *lp;
|
||||
int i;
|
||||
static int did_version;
|
||||
volatile unsigned short *ioaddr_probe;
|
||||
unsigned short tmp1, tmp2;
|
||||
@@ -373,8 +372,7 @@ static int __init lance_probe( struct net_device *dev)
|
||||
dev->irq);
|
||||
|
||||
/* copy in the ethernet address from the prom */
|
||||
for(i = 0; i < 6 ; i++)
|
||||
dev->dev_addr[i] = idprom->id_ethaddr[i];
|
||||
eth_hw_addr_set(dev, idprom->id_ethaddr);
|
||||
|
||||
/* tell the card it's ether address, bytes swapped */
|
||||
MEM->init.hwaddr[0] = dev->dev_addr[1];
|
||||
|
||||
@@ -1301,7 +1301,6 @@ static int sparc_lance_probe_one(struct platform_device *op,
|
||||
struct device_node *dp = op->dev.of_node;
|
||||
struct lance_private *lp;
|
||||
struct net_device *dev;
|
||||
int i;
|
||||
|
||||
dev = alloc_etherdev(sizeof(struct lance_private) + 8);
|
||||
if (!dev)
|
||||
@@ -1315,8 +1314,7 @@ static int sparc_lance_probe_one(struct platform_device *op,
|
||||
* will copy the address in the device structure to the lance
|
||||
* initialization block.
|
||||
*/
|
||||
for (i = 0; i < 6; i++)
|
||||
dev->dev_addr[i] = idprom->id_ethaddr[i];
|
||||
eth_hw_addr_set(dev, idprom->id_ethaddr);
|
||||
|
||||
/* Get the IO region */
|
||||
lp->lregs = of_ioremap(&op->resource[0], 0,
|
||||
|
||||
@@ -1080,7 +1080,7 @@ static int xgbe_add_mac_addresses(struct xgbe_prv_data *pdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xgbe_set_mac_address(struct xgbe_prv_data *pdata, u8 *addr)
|
||||
static int xgbe_set_mac_address(struct xgbe_prv_data *pdata, const u8 *addr)
|
||||
{
|
||||
unsigned int mac_addr_hi, mac_addr_lo;
|
||||
|
||||
|
||||
@@ -1912,10 +1912,8 @@ static int xgbe_close(struct net_device *netdev)
|
||||
clk_disable_unprepare(pdata->ptpclk);
|
||||
clk_disable_unprepare(pdata->sysclk);
|
||||
|
||||
flush_workqueue(pdata->an_workqueue);
|
||||
destroy_workqueue(pdata->an_workqueue);
|
||||
|
||||
flush_workqueue(pdata->dev_workqueue);
|
||||
destroy_workqueue(pdata->dev_workqueue);
|
||||
|
||||
set_bit(XGBE_DOWN, &pdata->dev_state);
|
||||
|
||||
@@ -729,7 +729,7 @@ struct xgbe_ext_stats {
|
||||
struct xgbe_hw_if {
|
||||
int (*tx_complete)(struct xgbe_ring_desc *);
|
||||
|
||||
int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr);
|
||||
int (*set_mac_address)(struct xgbe_prv_data *, const u8 *addr);
|
||||
int (*config_rx_mode)(struct xgbe_prv_data *);
|
||||
|
||||
int (*enable_rx_csum)(struct xgbe_prv_data *);
|
||||
|
||||
@@ -65,7 +65,7 @@ void xge_mac_set_speed(struct xge_pdata *pdata)
|
||||
|
||||
void xge_mac_set_station_addr(struct xge_pdata *pdata)
|
||||
{
|
||||
u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
const u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
u32 addr0, addr1;
|
||||
|
||||
addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
|
||||
|
||||
@@ -378,8 +378,8 @@ u32 xgene_enet_rd_stat(struct xgene_enet_pdata *pdata, u32 rd_addr)
|
||||
|
||||
static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
const u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
u32 addr0, addr1;
|
||||
u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
|
||||
addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
|
||||
(dev_addr[1] << 8) | dev_addr[0];
|
||||
|
||||
@@ -165,8 +165,8 @@ static void xgene_sgmac_reset(struct xgene_enet_pdata *p)
|
||||
|
||||
static void xgene_sgmac_set_mac_addr(struct xgene_enet_pdata *p)
|
||||
{
|
||||
const u8 *dev_addr = p->ndev->dev_addr;
|
||||
u32 addr0, addr1;
|
||||
u8 *dev_addr = p->ndev->dev_addr;
|
||||
|
||||
addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
|
||||
(dev_addr[1] << 8) | dev_addr[0];
|
||||
|
||||
@@ -207,8 +207,8 @@ static void xgene_pcs_reset(struct xgene_enet_pdata *pdata)
|
||||
|
||||
static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
|
||||
{
|
||||
const u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
u32 addr0, addr1;
|
||||
u8 *dev_addr = pdata->ndev->dev_addr;
|
||||
|
||||
addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
|
||||
(dev_addr[1] << 8) | dev_addr[0];
|
||||
|
||||
@@ -308,7 +308,7 @@ bmac_init_registers(struct net_device *dev)
|
||||
{
|
||||
struct bmac_data *bp = netdev_priv(dev);
|
||||
volatile unsigned short regValue;
|
||||
unsigned short *pWord16;
|
||||
const unsigned short *pWord16;
|
||||
int i;
|
||||
|
||||
/* XXDEBUG(("bmac: enter init_registers\n")); */
|
||||
@@ -371,7 +371,7 @@ bmac_init_registers(struct net_device *dev)
|
||||
bmwrite(dev, BHASH1, bp->hash_table_mask[2]); /* bits 47 - 32 */
|
||||
bmwrite(dev, BHASH0, bp->hash_table_mask[3]); /* bits 63 - 48 */
|
||||
|
||||
pWord16 = (unsigned short *)dev->dev_addr;
|
||||
pWord16 = (const unsigned short *)dev->dev_addr;
|
||||
bmwrite(dev, MADD0, *pWord16++);
|
||||
bmwrite(dev, MADD1, *pWord16++);
|
||||
bmwrite(dev, MADD2, *pWord16);
|
||||
@@ -521,19 +521,16 @@ static int bmac_resume(struct macio_dev *mdev)
|
||||
static int bmac_set_address(struct net_device *dev, void *addr)
|
||||
{
|
||||
struct bmac_data *bp = netdev_priv(dev);
|
||||
unsigned char *p = addr;
|
||||
unsigned short *pWord16;
|
||||
const unsigned short *pWord16;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
XXDEBUG(("bmac: enter set_address\n"));
|
||||
spin_lock_irqsave(&bp->lock, flags);
|
||||
|
||||
for (i = 0; i < 6; ++i) {
|
||||
dev->dev_addr[i] = p[i];
|
||||
}
|
||||
eth_hw_addr_set(dev, addr);
|
||||
|
||||
/* load up the hardware address */
|
||||
pWord16 = (unsigned short *)dev->dev_addr;
|
||||
pWord16 = (const unsigned short *)dev->dev_addr;
|
||||
bmwrite(dev, MADD0, *pWord16++);
|
||||
bmwrite(dev, MADD1, *pWord16++);
|
||||
bmwrite(dev, MADD2, *pWord16);
|
||||
|
||||
@@ -217,7 +217,7 @@ struct aq_hw_ops {
|
||||
int (*hw_ring_tx_head_update)(struct aq_hw_s *self,
|
||||
struct aq_ring_s *aq_ring);
|
||||
|
||||
int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr);
|
||||
int (*hw_set_mac_address)(struct aq_hw_s *self, const u8 *mac_addr);
|
||||
|
||||
int (*hw_soft_reset)(struct aq_hw_s *self);
|
||||
|
||||
@@ -226,7 +226,7 @@ struct aq_hw_ops {
|
||||
|
||||
int (*hw_reset)(struct aq_hw_s *self);
|
||||
|
||||
int (*hw_init)(struct aq_hw_s *self, u8 *mac_addr);
|
||||
int (*hw_init)(struct aq_hw_s *self, const u8 *mac_addr);
|
||||
|
||||
int (*hw_start)(struct aq_hw_s *self);
|
||||
|
||||
@@ -373,7 +373,7 @@ struct aq_fw_ops {
|
||||
int (*set_phyloopback)(struct aq_hw_s *self, u32 mode, bool enable);
|
||||
|
||||
int (*set_power)(struct aq_hw_s *self, unsigned int power_state,
|
||||
u8 *mac);
|
||||
const u8 *mac);
|
||||
|
||||
int (*send_fw_request)(struct aq_hw_s *self,
|
||||
const struct hw_fw_request_iface *fw_req,
|
||||
|
||||
@@ -35,7 +35,7 @@ static int aq_apply_macsec_cfg(struct aq_nic_s *nic);
|
||||
static int aq_apply_secy_cfg(struct aq_nic_s *nic,
|
||||
const struct macsec_secy *secy);
|
||||
|
||||
static void aq_ether_addr_to_mac(u32 mac[2], unsigned char *emac)
|
||||
static void aq_ether_addr_to_mac(u32 mac[2], const unsigned char *emac)
|
||||
{
|
||||
u32 tmp[2] = { 0 };
|
||||
|
||||
|
||||
@@ -300,6 +300,7 @@ static bool aq_nic_is_valid_ether_addr(const u8 *addr)
|
||||
|
||||
int aq_nic_ndev_register(struct aq_nic_s *self)
|
||||
{
|
||||
u8 addr[ETH_ALEN];
|
||||
int err = 0;
|
||||
|
||||
if (!self->ndev) {
|
||||
@@ -316,12 +317,13 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
|
||||
#endif
|
||||
|
||||
mutex_lock(&self->fwreq_mutex);
|
||||
err = self->aq_fw_ops->get_mac_permanent(self->aq_hw,
|
||||
self->ndev->dev_addr);
|
||||
err = self->aq_fw_ops->get_mac_permanent(self->aq_hw, addr);
|
||||
mutex_unlock(&self->fwreq_mutex);
|
||||
if (err)
|
||||
goto err_exit;
|
||||
|
||||
eth_hw_addr_set(self->ndev, addr);
|
||||
|
||||
if (!is_valid_ether_addr(self->ndev->dev_addr) ||
|
||||
!aq_nic_is_valid_ether_addr(self->ndev->dev_addr)) {
|
||||
netdev_warn(self->ndev, "MAC is invalid, will use random.");
|
||||
|
||||
@@ -322,7 +322,7 @@ static int hw_atl_a0_hw_init_rx_path(struct aq_hw_s *self)
|
||||
return aq_hw_err_from_flags(self);
|
||||
}
|
||||
|
||||
static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
|
||||
static int hw_atl_a0_hw_mac_addr_set(struct aq_hw_s *self, const u8 *mac_addr)
|
||||
{
|
||||
unsigned int h = 0U;
|
||||
unsigned int l = 0U;
|
||||
@@ -348,7 +348,7 @@ err_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
|
||||
static int hw_atl_a0_hw_init(struct aq_hw_s *self, const u8 *mac_addr)
|
||||
{
|
||||
static u32 aq_hw_atl_igcr_table_[4][2] = {
|
||||
[AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U },
|
||||
|
||||
@@ -533,7 +533,7 @@ static int hw_atl_b0_hw_init_rx_path(struct aq_hw_s *self)
|
||||
return aq_hw_err_from_flags(self);
|
||||
}
|
||||
|
||||
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr)
|
||||
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, const u8 *mac_addr)
|
||||
{
|
||||
unsigned int h = 0U;
|
||||
unsigned int l = 0U;
|
||||
@@ -558,7 +558,7 @@ err_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr)
|
||||
static int hw_atl_b0_hw_init(struct aq_hw_s *self, const u8 *mac_addr)
|
||||
{
|
||||
static u32 aq_hw_atl_igcr_table_[4][2] = {
|
||||
[AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U },
|
||||
|
||||
@@ -58,7 +58,7 @@ int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, struct aq_ring_s *ring);
|
||||
|
||||
void hw_atl_b0_hw_init_rx_rss_ctrl1(struct aq_hw_s *self);
|
||||
|
||||
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, u8 *mac_addr);
|
||||
int hw_atl_b0_hw_mac_addr_set(struct aq_hw_s *self, const u8 *mac_addr);
|
||||
|
||||
int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc);
|
||||
int hw_atl_b0_set_loopback(struct aq_hw_s *self, u32 mode, bool enable);
|
||||
|
||||
@@ -944,7 +944,7 @@ u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self)
|
||||
}
|
||||
|
||||
static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled,
|
||||
u8 *mac)
|
||||
const u8 *mac)
|
||||
{
|
||||
struct hw_atl_utils_fw_rpc *prpc = NULL;
|
||||
unsigned int rpc_size = 0U;
|
||||
@@ -987,7 +987,7 @@ err_exit:
|
||||
}
|
||||
|
||||
static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state,
|
||||
u8 *mac)
|
||||
const u8 *mac)
|
||||
{
|
||||
struct hw_atl_utils_fw_rpc *prpc = NULL;
|
||||
unsigned int rpc_size = 0U;
|
||||
|
||||
@@ -358,7 +358,7 @@ static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aq_fw2x_set_wol(struct aq_hw_s *self, u8 *mac)
|
||||
static int aq_fw2x_set_wol(struct aq_hw_s *self, const u8 *mac)
|
||||
{
|
||||
struct hw_atl_utils_fw_rpc *rpc = NULL;
|
||||
struct offload_info *info = NULL;
|
||||
@@ -404,7 +404,7 @@ err_exit:
|
||||
}
|
||||
|
||||
static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state,
|
||||
u8 *mac)
|
||||
const u8 *mac)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
|
||||
@@ -516,7 +516,7 @@ static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self)
|
||||
return aq_hw_err_from_flags(self);
|
||||
}
|
||||
|
||||
static int hw_atl2_hw_init(struct aq_hw_s *self, u8 *mac_addr)
|
||||
static int hw_atl2_hw_init(struct aq_hw_s *self, const u8 *mac_addr)
|
||||
{
|
||||
static u32 aq_hw_atl2_igcr_table_[4][2] = {
|
||||
[AQ_HW_IRQ_INVALID] = { 0x20000000U, 0x20000000U },
|
||||
|
||||
35
drivers/net/ethernet/asix/Kconfig
Normal file
35
drivers/net/ethernet/asix/Kconfig
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# Asix network device configuration
|
||||
#
|
||||
|
||||
config NET_VENDOR_ASIX
|
||||
bool "Asix devices"
|
||||
default y
|
||||
help
|
||||
If you have a network (Ethernet, non-USB, not NE2000 compatible)
|
||||
interface based on a chip from ASIX, say Y.
|
||||
|
||||
if NET_VENDOR_ASIX
|
||||
|
||||
config SPI_AX88796C
|
||||
tristate "Asix AX88796C-SPI support"
|
||||
select PHYLIB
|
||||
depends on SPI
|
||||
depends on GPIOLIB
|
||||
help
|
||||
Say Y here if you intend to use ASIX AX88796C attached in SPI mode.
|
||||
|
||||
config SPI_AX88796C_COMPRESSION
|
||||
bool "SPI transfer compression"
|
||||
default n
|
||||
depends on SPI_AX88796C
|
||||
help
|
||||
Say Y here to enable SPI transfer compression. It saves up
|
||||
to 24 dummy cycles during each transfer which may noticeably
|
||||
speed up short transfers. This sets the default value that is
|
||||
inherited by network interfaces during probe. It can be
|
||||
changed at run time via spi-compression ethtool tunable.
|
||||
|
||||
If unsure say N.
|
||||
|
||||
endif # NET_VENDOR_ASIX
|
||||
6
drivers/net/ethernet/asix/Makefile
Normal file
6
drivers/net/ethernet/asix/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Makefile for the Asix network device drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SPI_AX88796C) += ax88796c.o
|
||||
ax88796c-y := ax88796c_main.o ax88796c_ioctl.o ax88796c_spi.o
|
||||
239
drivers/net/ethernet/asix/ax88796c_ioctl.c
Normal file
239
drivers/net/ethernet/asix/ax88796c_ioctl.c
Normal file
@@ -0,0 +1,239 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2010 ASIX Electronics Corporation
|
||||
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* ASIX AX88796C SPI Fast Ethernet Linux driver
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ax88796c: " fmt
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "ax88796c_main.h"
|
||||
#include "ax88796c_ioctl.h"
|
||||
|
||||
static const char ax88796c_priv_flag_names[][ETH_GSTRING_LEN] = {
|
||||
"SPICompression",
|
||||
};
|
||||
|
||||
static void
|
||||
ax88796c_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
|
||||
{
|
||||
/* Inherit standard device info */
|
||||
strncpy(info->driver, DRV_NAME, sizeof(info->driver));
|
||||
}
|
||||
|
||||
static u32 ax88796c_get_msglevel(struct net_device *ndev)
|
||||
{
|
||||
struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
|
||||
|
||||
return ax_local->msg_enable;
|
||||
}
|
||||
|
||||
static void ax88796c_set_msglevel(struct net_device *ndev, u32 level)
|
||||
{
|
||||
struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
|
||||
|
||||
ax_local->msg_enable = level;
|
||||
}
|
||||
|
||||
static void
|
||||
ax88796c_get_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
|
||||
|
||||
pause->tx_pause = !!(ax_local->flowctrl & AX_FC_TX);
|
||||
pause->rx_pause = !!(ax_local->flowctrl & AX_FC_RX);
|
||||
pause->autoneg = (ax_local->flowctrl & AX_FC_ANEG) ?
|
||||
AUTONEG_ENABLE :
|
||||
AUTONEG_DISABLE;
|
||||
}
|
||||
|
||||
static int
|
||||
ax88796c_set_pauseparam(struct net_device *ndev, struct ethtool_pauseparam *pause)
|
||||
{
|
||||
struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
|
||||
int fc;
|
||||
|
||||
/* The following logic comes from phylink_ethtool_set_pauseparam() */
|
||||
fc = pause->tx_pause ? AX_FC_TX : 0;
|
||||
fc |= pause->rx_pause ? AX_FC_RX : 0;
|
||||
fc |= pause->autoneg ? AX_FC_ANEG : 0;
|
||||
|
||||
ax_local->flowctrl = fc;
|
||||
|
||||
if (pause->autoneg) {
|
||||
phy_set_asym_pause(ax_local->phydev, pause->tx_pause,
|
||||
pause->rx_pause);
|
||||
} else {
|
||||
int maccr = 0;
|
||||
|
||||
phy_set_asym_pause(ax_local->phydev, 0, 0);
|
||||
maccr |= (ax_local->flowctrl & AX_FC_RX) ? MACCR_RXFC_ENABLE : 0;
|
||||
maccr |= (ax_local->flowctrl & AX_FC_TX) ? MACCR_TXFC_ENABLE : 0;
|
||||
|
||||
mutex_lock(&ax_local->spi_lock);
|
||||
|
||||
maccr |= AX_READ(&ax_local->ax_spi, P0_MACCR) &
|
||||
~(MACCR_TXFC_ENABLE | MACCR_RXFC_ENABLE);
|
||||
AX_WRITE(&ax_local->ax_spi, maccr, P0_MACCR);
|
||||
|
||||
mutex_unlock(&ax_local->spi_lock);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ax88796c_get_regs_len(struct net_device *ndev)
|
||||
{
|
||||
return AX88796C_REGDUMP_LEN + AX88796C_PHY_REGDUMP_LEN;
|
||||
}
|
||||
|
||||
static void
|
||||
ax88796c_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *_p)
|
||||
{
|
||||
struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
|
||||
int offset, i;
|
||||
u16 *p = _p;
|
||||
|
||||
memset(p, 0, ax88796c_get_regs_len(ndev));
|
||||
|
||||
mutex_lock(&ax_local->spi_lock);
|
||||
|
||||
for (offset = 0; offset < AX88796C_REGDUMP_LEN; offset += 2) {
|
||||
if (!test_bit(offset / 2, ax88796c_no_regs_mask))
|
||||
*p = AX_READ(&ax_local->ax_spi, offset);
|
||||
p++;
|
||||
}
|
||||
|
||||
mutex_unlock(&ax_local->spi_lock);
|
||||
|
||||
for (i = 0; i < AX88796C_PHY_REGDUMP_LEN / 2; i++) {
|
||||
*p = phy_read(ax_local->phydev, i);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ax88796c_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
|
||||
{
|
||||
switch (stringset) {
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
memcpy(data, ax88796c_priv_flag_names,
|
||||
sizeof(ax88796c_priv_flag_names));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ax88796c_get_sset_count(struct net_device *ndev, int stringset)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
ret = ARRAY_SIZE(ax88796c_priv_flag_names);
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ax88796c_set_priv_flags(struct net_device *ndev, u32 flags)
|
||||
{
|
||||
struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
|
||||
|
||||
if (flags & ~AX_PRIV_FLAGS_MASK)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if ((ax_local->priv_flags ^ flags) & AX_CAP_COMP)
|
||||
if (netif_running(ndev))
|
||||
return -EBUSY;
|
||||
|
||||
ax_local->priv_flags = flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 ax88796c_get_priv_flags(struct net_device *ndev)
|
||||
{
|
||||
struct ax88796c_device *ax_local = to_ax88796c_device(ndev);
|
||||
|
||||
return ax_local->priv_flags;
|
||||
}
|
||||
|
||||
int ax88796c_mdio_read(struct mii_bus *mdiobus, int phy_id, int loc)
|
||||
{
|
||||
struct ax88796c_device *ax_local = mdiobus->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ax_local->spi_lock);
|
||||
AX_WRITE(&ax_local->ax_spi, MDIOCR_RADDR(loc)
|
||||
| MDIOCR_FADDR(phy_id) | MDIOCR_READ, P2_MDIOCR);
|
||||
|
||||
ret = read_poll_timeout(AX_READ, ret,
|
||||
(ret != 0),
|
||||
0, jiffies_to_usecs(HZ / 100), false,
|
||||
&ax_local->ax_spi, P2_MDIOCR);
|
||||
if (!ret)
|
||||
ret = AX_READ(&ax_local->ax_spi, P2_MDIODR);
|
||||
|
||||
mutex_unlock(&ax_local->spi_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ax88796c_mdio_write(struct mii_bus *mdiobus, int phy_id, int loc, u16 val)
|
||||
{
|
||||
struct ax88796c_device *ax_local = mdiobus->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ax_local->spi_lock);
|
||||
AX_WRITE(&ax_local->ax_spi, val, P2_MDIODR);
|
||||
|
||||
AX_WRITE(&ax_local->ax_spi,
|
||||
MDIOCR_RADDR(loc) | MDIOCR_FADDR(phy_id)
|
||||
| MDIOCR_WRITE, P2_MDIOCR);
|
||||
|
||||
ret = read_poll_timeout(AX_READ, ret,
|
||||
((ret & MDIOCR_VALID) != 0), 0,
|
||||
jiffies_to_usecs(HZ / 100), false,
|
||||
&ax_local->ax_spi, P2_MDIOCR);
|
||||
mutex_unlock(&ax_local->spi_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct ethtool_ops ax88796c_ethtool_ops = {
|
||||
.get_drvinfo = ax88796c_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_msglevel = ax88796c_get_msglevel,
|
||||
.set_msglevel = ax88796c_set_msglevel,
|
||||
.get_link_ksettings = phy_ethtool_get_link_ksettings,
|
||||
.set_link_ksettings = phy_ethtool_set_link_ksettings,
|
||||
.nway_reset = phy_ethtool_nway_reset,
|
||||
.get_pauseparam = ax88796c_get_pauseparam,
|
||||
.set_pauseparam = ax88796c_set_pauseparam,
|
||||
.get_regs_len = ax88796c_get_regs_len,
|
||||
.get_regs = ax88796c_get_regs,
|
||||
.get_strings = ax88796c_get_strings,
|
||||
.get_sset_count = ax88796c_get_sset_count,
|
||||
.get_priv_flags = ax88796c_get_priv_flags,
|
||||
.set_priv_flags = ax88796c_set_priv_flags,
|
||||
};
|
||||
|
||||
int ax88796c_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = phy_mii_ioctl(ndev->phydev, ifr, cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
26
drivers/net/ethernet/asix/ax88796c_ioctl.h
Normal file
26
drivers/net/ethernet/asix/ax88796c_ioctl.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2010 ASIX Electronics Corporation
|
||||
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* ASIX AX88796C SPI Fast Ethernet Linux driver
|
||||
*/
|
||||
|
||||
#ifndef _AX88796C_IOCTL_H
|
||||
#define _AX88796C_IOCTL_H
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "ax88796c_main.h"
|
||||
|
||||
extern const struct ethtool_ops ax88796c_ethtool_ops;
|
||||
|
||||
bool ax88796c_check_power(const struct ax88796c_device *ax_local);
|
||||
bool ax88796c_check_power_and_wake(struct ax88796c_device *ax_local);
|
||||
void ax88796c_set_power_saving(struct ax88796c_device *ax_local, u8 ps_level);
|
||||
int ax88796c_mdio_read(struct mii_bus *mdiobus, int phy_id, int loc);
|
||||
int ax88796c_mdio_write(struct mii_bus *mdiobus, int phy_id, int loc, u16 val);
|
||||
int ax88796c_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
|
||||
|
||||
#endif
|
||||
1163
drivers/net/ethernet/asix/ax88796c_main.c
Normal file
1163
drivers/net/ethernet/asix/ax88796c_main.c
Normal file
File diff suppressed because it is too large
Load Diff
568
drivers/net/ethernet/asix/ax88796c_main.h
Normal file
568
drivers/net/ethernet/asix/ax88796c_main.h
Normal file
@@ -0,0 +1,568 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2010 ASIX Electronics Corporation
|
||||
* Copyright (c) 2020 Samsung Electronics
|
||||
*
|
||||
* ASIX AX88796C SPI Fast Ethernet Linux driver
|
||||
*/
|
||||
|
||||
#ifndef _AX88796C_MAIN_H
|
||||
#define _AX88796C_MAIN_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/mii.h>
|
||||
|
||||
#include "ax88796c_spi.h"
|
||||
|
||||
/* These identify the driver base version and may not be removed. */
|
||||
#define DRV_NAME "ax88796c"
|
||||
#define ADP_NAME "ASIX AX88796C SPI Ethernet Adapter"
|
||||
|
||||
#define TX_QUEUE_HIGH_WATER 45 /* Tx queue high water mark */
|
||||
#define TX_QUEUE_LOW_WATER 20 /* Tx queue low water mark */
|
||||
|
||||
#define AX88796C_REGDUMP_LEN 256
|
||||
#define AX88796C_PHY_REGDUMP_LEN 14
|
||||
#define AX88796C_PHY_ID 0x10
|
||||
|
||||
#define TX_OVERHEAD 8
|
||||
#define TX_EOP_SIZE 4
|
||||
|
||||
#define AX_MCAST_FILTER_SIZE 8
|
||||
#define AX_MAX_MCAST 64
|
||||
#define AX_MAX_CLK 80000000
|
||||
#define TX_HDR_SOP_DICF 0x8000
|
||||
#define TX_HDR_SOP_CPHI 0x4000
|
||||
#define TX_HDR_SOP_INT 0x2000
|
||||
#define TX_HDR_SOP_MDEQ 0x1000
|
||||
#define TX_HDR_SOP_PKTLEN 0x07FF
|
||||
#define TX_HDR_SOP_SEQNUM 0xF800
|
||||
#define TX_HDR_SOP_PKTLENBAR 0x07FF
|
||||
|
||||
#define TX_HDR_SEG_FS 0x8000
|
||||
#define TX_HDR_SEG_LS 0x4000
|
||||
#define TX_HDR_SEG_SEGNUM 0x3800
|
||||
#define TX_HDR_SEG_SEGLEN 0x0700
|
||||
#define TX_HDR_SEG_EOFST 0xC000
|
||||
#define TX_HDR_SEG_SOFST 0x3800
|
||||
#define TX_HDR_SEG_SEGLENBAR 0x07FF
|
||||
|
||||
#define TX_HDR_EOP_SEQNUM 0xF800
|
||||
#define TX_HDR_EOP_PKTLEN 0x07FF
|
||||
#define TX_HDR_EOP_SEQNUMBAR 0xF800
|
||||
#define TX_HDR_EOP_PKTLENBAR 0x07FF
|
||||
|
||||
/* Rx header fields mask */
|
||||
#define RX_HDR1_MCBC 0x8000
|
||||
#define RX_HDR1_STUFF_PKT 0x4000
|
||||
#define RX_HDR1_MII_ERR 0x2000
|
||||
#define RX_HDR1_CRC_ERR 0x1000
|
||||
#define RX_HDR1_PKT_LEN 0x07FF
|
||||
|
||||
#define RX_HDR2_SEQ_NUM 0xF800
|
||||
#define RX_HDR2_PKT_LEN_BAR 0x7FFF
|
||||
|
||||
#define RX_HDR3_PE 0x8000
|
||||
#define RX_HDR3_L3_TYPE_IPV4V6 0x6000
|
||||
#define RX_HDR3_L3_TYPE_IP 0x4000
|
||||
#define RX_HDR3_L3_TYPE_IPV6 0x2000
|
||||
#define RX_HDR3_L4_TYPE_ICMPV6 0x1400
|
||||
#define RX_HDR3_L4_TYPE_TCP 0x1000
|
||||
#define RX_HDR3_L4_TYPE_IGMP 0x0c00
|
||||
#define RX_HDR3_L4_TYPE_ICMP 0x0800
|
||||
#define RX_HDR3_L4_TYPE_UDP 0x0400
|
||||
#define RX_HDR3_L3_ERR 0x0200
|
||||
#define RX_HDR3_L4_ERR 0x0100
|
||||
#define RX_HDR3_PRIORITY(x) ((x) << 4)
|
||||
#define RX_HDR3_STRIP 0x0008
|
||||
#define RX_HDR3_VLAN_ID 0x0007
|
||||
|
||||
struct ax88796c_pcpu_stats {
|
||||
u64_stats_t rx_packets;
|
||||
u64_stats_t rx_bytes;
|
||||
u64_stats_t tx_packets;
|
||||
u64_stats_t tx_bytes;
|
||||
struct u64_stats_sync syncp;
|
||||
u32 rx_dropped;
|
||||
u32 tx_dropped;
|
||||
u32 rx_frame_errors;
|
||||
u32 rx_crc_errors;
|
||||
};
|
||||
|
||||
struct ax88796c_device {
|
||||
struct spi_device *spi;
|
||||
struct net_device *ndev;
|
||||
struct ax88796c_pcpu_stats __percpu *stats;
|
||||
|
||||
struct work_struct ax_work;
|
||||
|
||||
struct mutex spi_lock; /* device access */
|
||||
|
||||
struct sk_buff_head tx_wait_q;
|
||||
|
||||
struct axspi_data ax_spi;
|
||||
|
||||
struct mii_bus *mdiobus;
|
||||
struct phy_device *phydev;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
u16 seq_num;
|
||||
|
||||
u8 multi_filter[AX_MCAST_FILTER_SIZE];
|
||||
|
||||
int link;
|
||||
int speed;
|
||||
int duplex;
|
||||
int pause;
|
||||
int asym_pause;
|
||||
int flowctrl;
|
||||
#define AX_FC_NONE 0
|
||||
#define AX_FC_RX BIT(0)
|
||||
#define AX_FC_TX BIT(1)
|
||||
#define AX_FC_ANEG BIT(2)
|
||||
|
||||
u32 priv_flags;
|
||||
#define AX_CAP_COMP BIT(0)
|
||||
#define AX_PRIV_FLAGS_MASK (AX_CAP_COMP)
|
||||
|
||||
unsigned long flags;
|
||||
#define EVENT_INTR BIT(0)
|
||||
#define EVENT_TX BIT(1)
|
||||
#define EVENT_SET_MULTI BIT(2)
|
||||
|
||||
};
|
||||
|
||||
#define to_ax88796c_device(ndev) ((struct ax88796c_device *)netdev_priv(ndev))
|
||||
|
||||
enum skb_state {
|
||||
illegal = 0,
|
||||
tx_done,
|
||||
rx_done,
|
||||
rx_err,
|
||||
};
|
||||
|
||||
struct skb_data {
|
||||
enum skb_state state;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/* A88796C register definition */
|
||||
/* Definition of PAGE0 */
|
||||
#define P0_PSR (0x00)
|
||||
#define PSR_DEV_READY BIT(7)
|
||||
#define PSR_RESET (0 << 15)
|
||||
#define PSR_RESET_CLR BIT(15)
|
||||
#define P0_BOR (0x02)
|
||||
#define P0_FER (0x04)
|
||||
#define FER_IPALM BIT(0)
|
||||
#define FER_DCRC BIT(1)
|
||||
#define FER_RH3M BIT(2)
|
||||
#define FER_HEADERSWAP BIT(7)
|
||||
#define FER_WSWAP BIT(8)
|
||||
#define FER_BSWAP BIT(9)
|
||||
#define FER_INTHI BIT(10)
|
||||
#define FER_INTLO (0 << 10)
|
||||
#define FER_IRQ_PULL BIT(11)
|
||||
#define FER_RXEN BIT(14)
|
||||
#define FER_TXEN BIT(15)
|
||||
#define P0_ISR (0x06)
|
||||
#define ISR_RXPKT BIT(0)
|
||||
#define ISR_MDQ BIT(4)
|
||||
#define ISR_TXT BIT(5)
|
||||
#define ISR_TXPAGES BIT(6)
|
||||
#define ISR_TXERR BIT(8)
|
||||
#define ISR_LINK BIT(9)
|
||||
#define P0_IMR (0x08)
|
||||
#define IMR_RXPKT BIT(0)
|
||||
#define IMR_MDQ BIT(4)
|
||||
#define IMR_TXT BIT(5)
|
||||
#define IMR_TXPAGES BIT(6)
|
||||
#define IMR_TXERR BIT(8)
|
||||
#define IMR_LINK BIT(9)
|
||||
#define IMR_MASKALL (0xFFFF)
|
||||
#define IMR_DEFAULT (IMR_TXERR)
|
||||
#define P0_WFCR (0x0A)
|
||||
#define WFCR_PMEIND BIT(0) /* PME indication */
|
||||
#define WFCR_PMETYPE BIT(1) /* PME I/O type */
|
||||
#define WFCR_PMEPOL BIT(2) /* PME polarity */
|
||||
#define WFCR_PMERST BIT(3) /* Reset PME */
|
||||
#define WFCR_SLEEP BIT(4) /* Enable sleep mode */
|
||||
#define WFCR_WAKEUP BIT(5) /* Enable wakeup mode */
|
||||
#define WFCR_WAITEVENT BIT(6) /* Reserved */
|
||||
#define WFCR_CLRWAKE BIT(7) /* Clear wakeup */
|
||||
#define WFCR_LINKCH BIT(8) /* Enable link change */
|
||||
#define WFCR_MAGICP BIT(9) /* Enable magic packet */
|
||||
#define WFCR_WAKEF BIT(10) /* Enable wakeup frame */
|
||||
#define WFCR_PMEEN BIT(11) /* Enable PME pin */
|
||||
#define WFCR_LINKCHS BIT(12) /* Link change status */
|
||||
#define WFCR_MAGICPS BIT(13) /* Magic packet status */
|
||||
#define WFCR_WAKEFS BIT(14) /* Wakeup frame status */
|
||||
#define WFCR_PMES BIT(15) /* PME pin status */
|
||||
#define P0_PSCR (0x0C)
|
||||
#define PSCR_PS_MASK (0xFFF0)
|
||||
#define PSCR_PS_D0 (0)
|
||||
#define PSCR_PS_D1 BIT(0)
|
||||
#define PSCR_PS_D2 BIT(1)
|
||||
#define PSCR_FPS BIT(3) /* Enable fiber mode PS */
|
||||
#define PSCR_SWPS BIT(4) /* Enable software */
|
||||
/* PS control */
|
||||
#define PSCR_WOLPS BIT(5) /* Enable WOL PS */
|
||||
#define PSCR_SWWOL BIT(6) /* Enable software select */
|
||||
/* WOL PS */
|
||||
#define PSCR_PHYOSC BIT(7) /* Internal PHY OSC control */
|
||||
#define PSCR_FOFEF BIT(8) /* Force PHY generate FEF */
|
||||
#define PSCR_FOF BIT(9) /* Force PHY in fiber mode */
|
||||
#define PSCR_PHYPD BIT(10) /* PHY power down. */
|
||||
/* Active high */
|
||||
#define PSCR_PHYRST BIT(11) /* PHY reset signal. */
|
||||
/* Active low */
|
||||
#define PSCR_PHYCSIL BIT(12) /* PHY cable energy detect */
|
||||
#define PSCR_PHYCOFF BIT(13) /* PHY cable off */
|
||||
#define PSCR_PHYLINK BIT(14) /* PHY link status */
|
||||
#define PSCR_EEPOK BIT(15) /* EEPROM load complete */
|
||||
#define P0_MACCR (0x0E)
|
||||
#define MACCR_RXEN BIT(0) /* Enable RX */
|
||||
#define MACCR_DUPLEX_FULL BIT(1) /* 1: Full, 0: Half */
|
||||
#define MACCR_SPEED_100 BIT(2) /* 1: 100Mbps, 0: 10Mbps */
|
||||
#define MACCR_RXFC_ENABLE BIT(3)
|
||||
#define MACCR_RXFC_MASK 0xFFF7
|
||||
#define MACCR_TXFC_ENABLE BIT(4)
|
||||
#define MACCR_TXFC_MASK 0xFFEF
|
||||
#define MACCR_PSI BIT(6) /* Software Cable-Off */
|
||||
/* Power Saving Interrupt */
|
||||
#define MACCR_PF BIT(7)
|
||||
#define MACCR_PMM_BITS 8
|
||||
#define MACCR_PMM_MASK (0x1F00)
|
||||
#define MACCR_PMM_RESET BIT(8)
|
||||
#define MACCR_PMM_WAIT (2 << 8)
|
||||
#define MACCR_PMM_READY (3 << 8)
|
||||
#define MACCR_PMM_D1 (4 << 8)
|
||||
#define MACCR_PMM_D2 (5 << 8)
|
||||
#define MACCR_PMM_WAKE (7 << 8)
|
||||
#define MACCR_PMM_D1_WAKE (8 << 8)
|
||||
#define MACCR_PMM_D2_WAKE (9 << 8)
|
||||
#define MACCR_PMM_SLEEP (10 << 8)
|
||||
#define MACCR_PMM_PHY_RESET (11 << 8)
|
||||
#define MACCR_PMM_SOFT_D1 (16 << 8)
|
||||
#define MACCR_PMM_SOFT_D2 (17 << 8)
|
||||
#define P0_TFBFCR (0x10)
|
||||
#define TFBFCR_SCHE_FREE_PAGE 0xE07F
|
||||
#define TFBFCR_FREE_PAGE_BITS 0x07
|
||||
#define TFBFCR_FREE_PAGE_LATCH BIT(6)
|
||||
#define TFBFCR_SET_FREE_PAGE(x) (((x) & 0x3F) << TFBFCR_FREE_PAGE_BITS)
|
||||
#define TFBFCR_TX_PAGE_SET BIT(13)
|
||||
#define TFBFCR_MANU_ENTX BIT(15)
|
||||
#define TX_FREEBUF_MASK 0x003F
|
||||
#define TX_DPTSTART 0x4000
|
||||
|
||||
#define P0_TSNR (0x12)
|
||||
#define TXNR_TXB_ERR BIT(5)
|
||||
#define TXNR_TXB_IDLE BIT(6)
|
||||
#define TSNR_PKT_CNT(x) (((x) & 0x3F) << 8)
|
||||
#define TXNR_TXB_REINIT BIT(14)
|
||||
#define TSNR_TXB_START BIT(15)
|
||||
#define P0_RTDPR (0x14)
|
||||
#define P0_RXBCR1 (0x16)
|
||||
#define RXBCR1_RXB_DISCARD BIT(14)
|
||||
#define RXBCR1_RXB_START BIT(15)
|
||||
#define P0_RXBCR2 (0x18)
|
||||
#define RXBCR2_PKT_MASK (0xFF)
|
||||
#define RXBCR2_RXPC_MASK (0x7F)
|
||||
#define RXBCR2_RXB_READY BIT(13)
|
||||
#define RXBCR2_RXB_IDLE BIT(14)
|
||||
#define RXBCR2_RXB_REINIT BIT(15)
|
||||
#define P0_RTWCR (0x1A)
|
||||
#define RTWCR_RXWC_MASK (0x3FFF)
|
||||
#define RTWCR_RX_LATCH BIT(15)
|
||||
#define P0_RCPHR (0x1C)
|
||||
|
||||
/* Definition of PAGE1 */
|
||||
#define P1_RPPER (0x22)
|
||||
#define RPPER_RXEN BIT(0)
|
||||
#define P1_MRCR (0x28)
|
||||
#define P1_MDR (0x2A)
|
||||
#define P1_RMPR (0x2C)
|
||||
#define P1_TMPR (0x2E)
|
||||
#define P1_RXBSPCR (0x30)
|
||||
#define RXBSPCR_STUF_WORD_CNT(x) (((x) & 0x7000) >> 12)
|
||||
#define RXBSPCR_STUF_ENABLE BIT(15)
|
||||
#define P1_MCR (0x32)
|
||||
#define MCR_SBP BIT(8)
|
||||
#define MCR_SM BIT(9)
|
||||
#define MCR_CRCENLAN BIT(11)
|
||||
#define MCR_STP BIT(12)
|
||||
/* Definition of PAGE2 */
|
||||
#define P2_CIR (0x42)
|
||||
#define P2_PCR (0x44)
|
||||
#define PCR_POLL_EN BIT(0)
|
||||
#define PCR_POLL_FLOWCTRL BIT(1)
|
||||
#define PCR_POLL_BMCR BIT(2)
|
||||
#define PCR_PHYID(x) ((x) << 8)
|
||||
#define P2_PHYSR (0x46)
|
||||
#define P2_MDIODR (0x48)
|
||||
#define P2_MDIOCR (0x4A)
|
||||
#define MDIOCR_RADDR(x) ((x) & 0x1F)
|
||||
#define MDIOCR_FADDR(x) (((x) & 0x1F) << 8)
|
||||
#define MDIOCR_VALID BIT(13)
|
||||
#define MDIOCR_READ BIT(14)
|
||||
#define MDIOCR_WRITE BIT(15)
|
||||
#define P2_LCR0 (0x4C)
|
||||
#define LCR_LED0_EN BIT(0)
|
||||
#define LCR_LED0_100MODE BIT(1)
|
||||
#define LCR_LED0_DUPLEX BIT(2)
|
||||
#define LCR_LED0_LINK BIT(3)
|
||||
#define LCR_LED0_ACT BIT(4)
|
||||
#define LCR_LED0_COL BIT(5)
|
||||
#define LCR_LED0_10MODE BIT(6)
|
||||
#define LCR_LED0_DUPCOL BIT(7)
|
||||
#define LCR_LED1_EN BIT(8)
|
||||
#define LCR_LED1_100MODE BIT(9)
|
||||
#define LCR_LED1_DUPLEX BIT(10)
|
||||
#define LCR_LED1_LINK BIT(11)
|
||||
#define LCR_LED1_ACT BIT(12)
|
||||
#define LCR_LED1_COL BIT(13)
|
||||
#define LCR_LED1_10MODE BIT(14)
|
||||
#define LCR_LED1_DUPCOL BIT(15)
|
||||
#define P2_LCR1 (0x4E)
|
||||
#define LCR_LED2_MASK (0xFF00)
|
||||
#define LCR_LED2_EN BIT(0)
|
||||
#define LCR_LED2_100MODE BIT(1)
|
||||
#define LCR_LED2_DUPLEX BIT(2)
|
||||
#define LCR_LED2_LINK BIT(3)
|
||||
#define LCR_LED2_ACT BIT(4)
|
||||
#define LCR_LED2_COL BIT(5)
|
||||
#define LCR_LED2_10MODE BIT(6)
|
||||
#define LCR_LED2_DUPCOL BIT(7)
|
||||
#define P2_IPGCR (0x50)
|
||||
#define P2_CRIR (0x52)
|
||||
#define P2_FLHWCR (0x54)
|
||||
#define P2_RXCR (0x56)
|
||||
#define RXCR_PRO BIT(0)
|
||||
#define RXCR_AMALL BIT(1)
|
||||
#define RXCR_SEP BIT(2)
|
||||
#define RXCR_AB BIT(3)
|
||||
#define RXCR_AM BIT(4)
|
||||
#define RXCR_AP BIT(5)
|
||||
#define RXCR_ARP BIT(6)
|
||||
#define P2_JLCR (0x58)
|
||||
#define P2_MPLR (0x5C)
|
||||
|
||||
/* Definition of PAGE3 */
|
||||
#define P3_MACASR0 (0x62)
|
||||
#define P3_MACASR(x) (P3_MACASR0 + 2 * (x))
|
||||
#define MACASR_LOWBYTE_MASK 0x00FF
|
||||
#define MACASR_HIGH_BITS 0x08
|
||||
#define P3_MACASR1 (0x64)
|
||||
#define P3_MACASR2 (0x66)
|
||||
#define P3_MFAR01 (0x68)
|
||||
#define P3_MFAR_BASE (0x68)
|
||||
#define P3_MFAR(x) (P3_MFAR_BASE + 2 * (x))
|
||||
|
||||
#define P3_MFAR23 (0x6A)
|
||||
#define P3_MFAR45 (0x6C)
|
||||
#define P3_MFAR67 (0x6E)
|
||||
#define P3_VID0FR (0x70)
|
||||
#define P3_VID1FR (0x72)
|
||||
#define P3_EECSR (0x74)
|
||||
#define P3_EEDR (0x76)
|
||||
#define P3_EECR (0x78)
|
||||
#define EECR_ADDR_MASK (0x00FF)
|
||||
#define EECR_READ_ACT BIT(8)
|
||||
#define EECR_WRITE_ACT BIT(9)
|
||||
#define EECR_WRITE_DISABLE BIT(10)
|
||||
#define EECR_WRITE_ENABLE BIT(11)
|
||||
#define EECR_EE_READY BIT(13)
|
||||
#define EECR_RELOAD BIT(14)
|
||||
#define EECR_RESET BIT(15)
|
||||
#define P3_TPCR (0x7A)
|
||||
#define TPCR_PATT_MASK (0xFF)
|
||||
#define TPCR_RAND_PKT_EN BIT(14)
|
||||
#define TPCR_FIXED_PKT_EN BIT(15)
|
||||
#define P3_TPLR (0x7C)
|
||||
/* Definition of PAGE4 */
|
||||
#define P4_SPICR (0x8A)
|
||||
#define SPICR_RCEN BIT(0)
|
||||
#define SPICR_QCEN BIT(1)
|
||||
#define SPICR_RBRE BIT(3)
|
||||
#define SPICR_PMM BIT(4)
|
||||
#define SPICR_LOOPBACK BIT(8)
|
||||
#define SPICR_CORE_RES_CLR BIT(10)
|
||||
#define SPICR_SPI_RES_CLR BIT(11)
|
||||
#define P4_SPIISMR (0x8C)
|
||||
|
||||
#define P4_COERCR0 (0x92)
|
||||
#define COERCR0_RXIPCE BIT(0)
|
||||
#define COERCR0_RXIPVE BIT(1)
|
||||
#define COERCR0_RXV6PE BIT(2)
|
||||
#define COERCR0_RXTCPE BIT(3)
|
||||
#define COERCR0_RXUDPE BIT(4)
|
||||
#define COERCR0_RXICMP BIT(5)
|
||||
#define COERCR0_RXIGMP BIT(6)
|
||||
#define COERCR0_RXICV6 BIT(7)
|
||||
|
||||
#define COERCR0_RXTCPV6 BIT(8)
|
||||
#define COERCR0_RXUDPV6 BIT(9)
|
||||
#define COERCR0_RXICMV6 BIT(10)
|
||||
#define COERCR0_RXIGMV6 BIT(11)
|
||||
#define COERCR0_RXICV6V6 BIT(12)
|
||||
|
||||
#define COERCR0_DEFAULT (COERCR0_RXIPCE | COERCR0_RXV6PE | \
|
||||
COERCR0_RXTCPE | COERCR0_RXUDPE | \
|
||||
COERCR0_RXTCPV6 | COERCR0_RXUDPV6)
|
||||
#define P4_COERCR1 (0x94)
|
||||
#define COERCR1_IPCEDP BIT(0)
|
||||
#define COERCR1_IPVEDP BIT(1)
|
||||
#define COERCR1_V6VEDP BIT(2)
|
||||
#define COERCR1_TCPEDP BIT(3)
|
||||
#define COERCR1_UDPEDP BIT(4)
|
||||
#define COERCR1_ICMPDP BIT(5)
|
||||
#define COERCR1_IGMPDP BIT(6)
|
||||
#define COERCR1_ICV6DP BIT(7)
|
||||
#define COERCR1_RX64TE BIT(8)
|
||||
#define COERCR1_RXPPPE BIT(9)
|
||||
#define COERCR1_TCP6DP BIT(10)
|
||||
#define COERCR1_UDP6DP BIT(11)
|
||||
#define COERCR1_IC6DP BIT(12)
|
||||
#define COERCR1_IG6DP BIT(13)
|
||||
#define COERCR1_ICV66DP BIT(14)
|
||||
#define COERCR1_RPCE BIT(15)
|
||||
|
||||
#define COERCR1_DEFAULT (COERCR1_RXPPPE)
|
||||
|
||||
#define P4_COETCR0 (0x96)
|
||||
#define COETCR0_TXIP BIT(0)
|
||||
#define COETCR0_TXTCP BIT(1)
|
||||
#define COETCR0_TXUDP BIT(2)
|
||||
#define COETCR0_TXICMP BIT(3)
|
||||
#define COETCR0_TXIGMP BIT(4)
|
||||
#define COETCR0_TXICV6 BIT(5)
|
||||
#define COETCR0_TXTCPV6 BIT(8)
|
||||
#define COETCR0_TXUDPV6 BIT(9)
|
||||
#define COETCR0_TXICMV6 BIT(10)
|
||||
#define COETCR0_TXIGMV6 BIT(11)
|
||||
#define COETCR0_TXICV6V6 BIT(12)
|
||||
|
||||
#define COETCR0_DEFAULT (COETCR0_TXIP | COETCR0_TXTCP | \
|
||||
COETCR0_TXUDP | COETCR0_TXTCPV6 | \
|
||||
COETCR0_TXUDPV6)
|
||||
#define P4_COETCR1 (0x98)
|
||||
#define COETCR1_TX64TE BIT(0)
|
||||
#define COETCR1_TXPPPE BIT(1)
|
||||
|
||||
#define P4_COECEDR (0x9A)
|
||||
#define P4_L2CECR (0x9C)
|
||||
|
||||
/* Definition of PAGE5 */
|
||||
#define P5_WFTR (0xA2)
|
||||
#define WFTR_2MS (0x01)
|
||||
#define WFTR_4MS (0x02)
|
||||
#define WFTR_8MS (0x03)
|
||||
#define WFTR_16MS (0x04)
|
||||
#define WFTR_32MS (0x05)
|
||||
#define WFTR_64MS (0x06)
|
||||
#define WFTR_128MS (0x07)
|
||||
#define WFTR_256MS (0x08)
|
||||
#define WFTR_512MS (0x09)
|
||||
#define WFTR_1024MS (0x0A)
|
||||
#define WFTR_2048MS (0x0B)
|
||||
#define WFTR_4096MS (0x0C)
|
||||
#define WFTR_8192MS (0x0D)
|
||||
#define WFTR_16384MS (0x0E)
|
||||
#define WFTR_32768MS (0x0F)
|
||||
#define P5_WFCCR (0xA4)
|
||||
#define P5_WFCR03 (0xA6)
|
||||
#define WFCR03_F0_EN BIT(0)
|
||||
#define WFCR03_F1_EN BIT(4)
|
||||
#define WFCR03_F2_EN BIT(8)
|
||||
#define WFCR03_F3_EN BIT(12)
|
||||
#define P5_WFCR47 (0xA8)
|
||||
#define WFCR47_F4_EN BIT(0)
|
||||
#define WFCR47_F5_EN BIT(4)
|
||||
#define WFCR47_F6_EN BIT(8)
|
||||
#define WFCR47_F7_EN BIT(12)
|
||||
#define P5_WF0BMR0 (0xAA)
|
||||
#define P5_WF0BMR1 (0xAC)
|
||||
#define P5_WF0CR (0xAE)
|
||||
#define P5_WF0OBR (0xB0)
|
||||
#define P5_WF1BMR0 (0xB2)
|
||||
#define P5_WF1BMR1 (0xB4)
|
||||
#define P5_WF1CR (0xB6)
|
||||
#define P5_WF1OBR (0xB8)
|
||||
#define P5_WF2BMR0 (0xBA)
|
||||
#define P5_WF2BMR1 (0xBC)
|
||||
|
||||
/* Definition of PAGE6 */
|
||||
#define P6_WF2CR (0xC2)
|
||||
#define P6_WF2OBR (0xC4)
|
||||
#define P6_WF3BMR0 (0xC6)
|
||||
#define P6_WF3BMR1 (0xC8)
|
||||
#define P6_WF3CR (0xCA)
|
||||
#define P6_WF3OBR (0xCC)
|
||||
#define P6_WF4BMR0 (0xCE)
|
||||
#define P6_WF4BMR1 (0xD0)
|
||||
#define P6_WF4CR (0xD2)
|
||||
#define P6_WF4OBR (0xD4)
|
||||
#define P6_WF5BMR0 (0xD6)
|
||||
#define P6_WF5BMR1 (0xD8)
|
||||
#define P6_WF5CR (0xDA)
|
||||
#define P6_WF5OBR (0xDC)
|
||||
|
||||
/* Definition of PAGE7 */
|
||||
#define P7_WF6BMR0 (0xE2)
|
||||
#define P7_WF6BMR1 (0xE4)
|
||||
#define P7_WF6CR (0xE6)
|
||||
#define P7_WF6OBR (0xE8)
|
||||
#define P7_WF7BMR0 (0xEA)
|
||||
#define P7_WF7BMR1 (0xEC)
|
||||
#define P7_WF7CR (0xEE)
|
||||
#define P7_WF7OBR (0xF0)
|
||||
#define P7_WFR01 (0xF2)
|
||||
#define P7_WFR23 (0xF4)
|
||||
#define P7_WFR45 (0xF6)
|
||||
#define P7_WFR67 (0xF8)
|
||||
#define P7_WFPC0 (0xFA)
|
||||
#define P7_WFPC1 (0xFC)
|
||||
|
||||
/* Tx headers structure */
|
||||
struct tx_sop_header {
|
||||
/* bit 15-11: flags, bit 10-0: packet length */
|
||||
u16 flags_len;
|
||||
/* bit 15-11: sequence number, bit 11-0: packet length bar */
|
||||
u16 seq_lenbar;
|
||||
};
|
||||
|
||||
struct tx_segment_header {
|
||||
/* bit 15-14: flags, bit 13-11: segment number */
|
||||
/* bit 10-0: segment length */
|
||||
u16 flags_seqnum_seglen;
|
||||
/* bit 15-14: end offset, bit 13-11: start offset */
|
||||
/* bit 10-0: segment length bar */
|
||||
u16 eo_so_seglenbar;
|
||||
};
|
||||
|
||||
struct tx_eop_header {
|
||||
/* bit 15-11: sequence number, bit 10-0: packet length */
|
||||
u16 seq_len;
|
||||
/* bit 15-11: sequence number bar, bit 10-0: packet length bar */
|
||||
u16 seqbar_lenbar;
|
||||
};
|
||||
|
||||
struct tx_pkt_info {
|
||||
struct tx_sop_header sop;
|
||||
struct tx_segment_header seg;
|
||||
struct tx_eop_header eop;
|
||||
u16 pkt_len;
|
||||
u16 seq_num;
|
||||
};
|
||||
|
||||
/* Rx headers structure */
|
||||
struct rx_header {
|
||||
u16 flags_len;
|
||||
u16 seq_lenbar;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
extern unsigned long ax88796c_no_regs_mask[];
|
||||
|
||||
#endif /* #ifndef _AX88796C_MAIN_H */
|
||||
115
drivers/net/ethernet/asix/ax88796c_spi.c
Normal file
115
drivers/net/ethernet/asix/ax88796c_spi.c
Normal file
@@ -0,0 +1,115 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2010 ASIX Electronics Corporation
|
||||
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* ASIX AX88796C SPI Fast Ethernet Linux driver
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ax88796c: " fmt
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include "ax88796c_spi.h"
|
||||
|
||||
const u8 ax88796c_rx_cmd_buf[5] = {AX_SPICMD_READ_RXQ, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
const u8 ax88796c_tx_cmd_buf[4] = {AX_SPICMD_WRITE_TXQ, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
/* driver bus management functions */
|
||||
int axspi_wakeup(struct axspi_data *ax_spi)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ax_spi->cmd_buf[0] = AX_SPICMD_EXIT_PWD; /* OP */
|
||||
ret = spi_write(ax_spi->spi, ax_spi->cmd_buf, 1);
|
||||
if (ret)
|
||||
dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int axspi_read_status(struct axspi_data *ax_spi, struct spi_status *status)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* OP */
|
||||
ax_spi->cmd_buf[0] = AX_SPICMD_READ_STATUS;
|
||||
ret = spi_write_then_read(ax_spi->spi, ax_spi->cmd_buf, 1, (u8 *)&status, 3);
|
||||
if (ret)
|
||||
dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
|
||||
else
|
||||
le16_to_cpus(&status->isr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len)
|
||||
{
|
||||
struct spi_transfer *xfer = ax_spi->spi_rx_xfer;
|
||||
int ret;
|
||||
|
||||
memcpy(ax_spi->cmd_buf, ax88796c_rx_cmd_buf, 5);
|
||||
|
||||
xfer->tx_buf = ax_spi->cmd_buf;
|
||||
xfer->rx_buf = NULL;
|
||||
xfer->len = ax_spi->comp ? 2 : 5;
|
||||
xfer->bits_per_word = 8;
|
||||
spi_message_add_tail(xfer, &ax_spi->rx_msg);
|
||||
|
||||
xfer++;
|
||||
xfer->rx_buf = data;
|
||||
xfer->tx_buf = NULL;
|
||||
xfer->len = len;
|
||||
xfer->bits_per_word = 8;
|
||||
spi_message_add_tail(xfer, &ax_spi->rx_msg);
|
||||
ret = spi_sync(ax_spi->spi, &ax_spi->rx_msg);
|
||||
if (ret)
|
||||
dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len)
|
||||
{
|
||||
return spi_write(ax_spi->spi, data, len);
|
||||
}
|
||||
|
||||
u16 axspi_read_reg(struct axspi_data *ax_spi, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
int len = ax_spi->comp ? 3 : 4;
|
||||
|
||||
ax_spi->cmd_buf[0] = 0x03; /* OP code read register */
|
||||
ax_spi->cmd_buf[1] = reg; /* register address */
|
||||
ax_spi->cmd_buf[2] = 0xFF; /* dumy cycle */
|
||||
ax_spi->cmd_buf[3] = 0xFF; /* dumy cycle */
|
||||
ret = spi_write_then_read(ax_spi->spi,
|
||||
ax_spi->cmd_buf, len,
|
||||
ax_spi->rx_buf, 2);
|
||||
if (ret) {
|
||||
dev_err(&ax_spi->spi->dev,
|
||||
"%s() failed: ret = %d\n", __func__, ret);
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
le16_to_cpus((u16 *)ax_spi->rx_buf);
|
||||
|
||||
return *(u16 *)ax_spi->rx_buf;
|
||||
}
|
||||
|
||||
int axspi_write_reg(struct axspi_data *ax_spi, u8 reg, u16 value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(ax_spi->cmd_buf, 0, sizeof(ax_spi->cmd_buf));
|
||||
ax_spi->cmd_buf[0] = AX_SPICMD_WRITE_REG; /* OP code read register */
|
||||
ax_spi->cmd_buf[1] = reg; /* register address */
|
||||
ax_spi->cmd_buf[2] = value;
|
||||
ax_spi->cmd_buf[3] = value >> 8;
|
||||
|
||||
ret = spi_write(ax_spi->spi, ax_spi->cmd_buf, 4);
|
||||
if (ret)
|
||||
dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
69
drivers/net/ethernet/asix/ax88796c_spi.h
Normal file
69
drivers/net/ethernet/asix/ax88796c_spi.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2010 ASIX Electronics Corporation
|
||||
* Copyright (c) 2020 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* ASIX AX88796C SPI Fast Ethernet Linux driver
|
||||
*/
|
||||
|
||||
#ifndef _AX88796C_SPI_H
|
||||
#define _AX88796C_SPI_H
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Definition of SPI command */
|
||||
#define AX_SPICMD_WRITE_TXQ 0x02
|
||||
#define AX_SPICMD_READ_REG 0x03
|
||||
#define AX_SPICMD_READ_STATUS 0x05
|
||||
#define AX_SPICMD_READ_RXQ 0x0B
|
||||
#define AX_SPICMD_BIDIR_WRQ 0xB2
|
||||
#define AX_SPICMD_WRITE_REG 0xD8
|
||||
#define AX_SPICMD_EXIT_PWD 0xAB
|
||||
|
||||
extern const u8 ax88796c_rx_cmd_buf[];
|
||||
extern const u8 ax88796c_tx_cmd_buf[];
|
||||
|
||||
struct axspi_data {
|
||||
struct spi_device *spi;
|
||||
struct spi_message rx_msg;
|
||||
struct spi_transfer spi_rx_xfer[2];
|
||||
u8 cmd_buf[6];
|
||||
u8 rx_buf[6];
|
||||
u8 comp;
|
||||
};
|
||||
|
||||
struct spi_status {
|
||||
u16 isr;
|
||||
u8 status;
|
||||
# define AX_STATUS_READY 0x80
|
||||
};
|
||||
|
||||
int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len);
|
||||
int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len);
|
||||
u16 axspi_read_reg(struct axspi_data *ax_spi, u8 reg);
|
||||
int axspi_write_reg(struct axspi_data *ax_spi, u8 reg, u16 value);
|
||||
int axspi_read_status(struct axspi_data *ax_spi, struct spi_status *status);
|
||||
int axspi_wakeup(struct axspi_data *ax_spi);
|
||||
|
||||
static inline u16 AX_READ(struct axspi_data *ax_spi, u8 offset)
|
||||
{
|
||||
return axspi_read_reg(ax_spi, offset);
|
||||
}
|
||||
|
||||
static inline int AX_WRITE(struct axspi_data *ax_spi, u16 value, u8 offset)
|
||||
{
|
||||
return axspi_write_reg(ax_spi, offset, value);
|
||||
}
|
||||
|
||||
static inline int AX_READ_STATUS(struct axspi_data *ax_spi,
|
||||
struct spi_status *status)
|
||||
{
|
||||
return axspi_read_status(ax_spi, status);
|
||||
}
|
||||
|
||||
static inline int AX_WAKEUP(struct axspi_data *ax_spi)
|
||||
{
|
||||
return axspi_wakeup(ax_spi);
|
||||
}
|
||||
#endif
|
||||
@@ -1971,7 +1971,7 @@ static int ag71xx_probe(struct platform_device *pdev)
|
||||
err = of_get_ethdev_address(np, ndev);
|
||||
if (err) {
|
||||
netif_err(ag, probe, ndev, "invalid MAC address, using random address\n");
|
||||
eth_random_addr(ndev->dev_addr);
|
||||
eth_hw_addr_random(ndev);
|
||||
}
|
||||
|
||||
err = of_get_phy_mode(np, &ag->phy_if_mode);
|
||||
|
||||
@@ -218,7 +218,8 @@ static inline void __b44_cam_read(struct b44 *bp, unsigned char *data, int index
|
||||
data[1] = (val >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
static inline void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
|
||||
static inline void __b44_cam_write(struct b44 *bp,
|
||||
const unsigned char *data, int index)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -1507,7 +1508,8 @@ static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset)
|
||||
}
|
||||
}
|
||||
|
||||
static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
|
||||
static int b44_magic_pattern(const u8 *macaddr, u8 *ppattern, u8 *pmask,
|
||||
int offset)
|
||||
{
|
||||
int magicsync = 6;
|
||||
int k, j, len = offset;
|
||||
|
||||
@@ -1818,7 +1818,7 @@ static inline void umac_reset(struct bcm_sysport_priv *priv)
|
||||
}
|
||||
|
||||
static void umac_set_hw_addr(struct bcm_sysport_priv *priv,
|
||||
unsigned char *addr)
|
||||
const unsigned char *addr)
|
||||
{
|
||||
u32 mac0 = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) |
|
||||
addr[3];
|
||||
|
||||
@@ -768,7 +768,7 @@ static void bgmac_umac_cmd_maskset(struct bgmac *bgmac, u32 mask, u32 set,
|
||||
udelay(2);
|
||||
}
|
||||
|
||||
static void bgmac_write_mac_address(struct bgmac *bgmac, u8 *addr)
|
||||
static void bgmac_write_mac_address(struct bgmac *bgmac, const u8 *addr)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
|
||||
@@ -2704,7 +2704,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
|
||||
}
|
||||
|
||||
static void
|
||||
bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos)
|
||||
bnx2_set_mac_addr(struct bnx2 *bp, const u8 *mac_addr, u32 pos)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
|
||||
@@ -1994,7 +1994,7 @@ int bnx2x_idle_chk(struct bnx2x *bp);
|
||||
* operation has been successfully scheduled and a negative - if a requested
|
||||
* operations has failed.
|
||||
*/
|
||||
int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
|
||||
int bnx2x_set_mac_one(struct bnx2x *bp, const u8 *mac,
|
||||
struct bnx2x_vlan_mac_obj *obj, bool set,
|
||||
int mac_type, unsigned long *ramrod_flags);
|
||||
|
||||
|
||||
@@ -8417,7 +8417,7 @@ alloc_mem_err:
|
||||
* Init service functions
|
||||
*/
|
||||
|
||||
int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
|
||||
int bnx2x_set_mac_one(struct bnx2x *bp, const u8 *mac,
|
||||
struct bnx2x_vlan_mac_obj *obj, bool set,
|
||||
int mac_type, unsigned long *ramrod_flags)
|
||||
{
|
||||
@@ -9146,7 +9146,7 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode)
|
||||
|
||||
else if (bp->wol) {
|
||||
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
|
||||
u8 *mac_addr = bp->dev->dev_addr;
|
||||
const u8 *mac_addr = bp->dev->dev_addr;
|
||||
struct pci_dev *pdev = bp->pdev;
|
||||
u32 val;
|
||||
u16 pmc;
|
||||
@@ -11823,9 +11823,10 @@ static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
|
||||
u32 val, val2;
|
||||
int func = BP_ABS_FUNC(bp);
|
||||
int port = BP_PORT(bp);
|
||||
u8 addr[ETH_ALEN] = {};
|
||||
|
||||
/* Zero primary MAC configuration */
|
||||
eth_zero_addr(bp->dev->dev_addr);
|
||||
eth_hw_addr_set(bp->dev, addr);
|
||||
|
||||
if (BP_NOMCP(bp)) {
|
||||
BNX2X_ERROR("warning: random MAC workaround active\n");
|
||||
@@ -11834,8 +11835,10 @@ static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
|
||||
val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
|
||||
val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
|
||||
if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
|
||||
(val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
|
||||
bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
|
||||
(val != FUNC_MF_CFG_LOWERMAC_DEFAULT)) {
|
||||
bnx2x_set_mac_buf(addr, val, val2);
|
||||
eth_hw_addr_set(bp->dev, addr);
|
||||
}
|
||||
|
||||
if (CNIC_SUPPORT(bp))
|
||||
bnx2x_get_cnic_mac_hwinfo(bp);
|
||||
@@ -11843,7 +11846,8 @@ static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
|
||||
/* in SF read MACs from port configuration */
|
||||
val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
|
||||
val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
|
||||
bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
|
||||
bnx2x_set_mac_buf(addr, val, val2);
|
||||
eth_hw_addr_set(bp->dev, addr);
|
||||
|
||||
if (CNIC_SUPPORT(bp))
|
||||
bnx2x_get_cnic_mac_hwinfo(bp);
|
||||
@@ -12291,7 +12295,9 @@ static int bnx2x_init_bp(struct bnx2x *bp)
|
||||
if (rc)
|
||||
return rc;
|
||||
} else {
|
||||
eth_zero_addr(bp->dev->dev_addr);
|
||||
static const u8 zero_addr[ETH_ALEN] = {};
|
||||
|
||||
eth_hw_addr_set(bp->dev, zero_addr);
|
||||
}
|
||||
|
||||
bnx2x_set_modes_bitmap(bp);
|
||||
|
||||
@@ -508,7 +508,8 @@ int bnx2x_vfpf_init(struct bnx2x *bp);
|
||||
void bnx2x_vfpf_close_vf(struct bnx2x *bp);
|
||||
int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
|
||||
bool is_leading);
|
||||
int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set);
|
||||
int bnx2x_vfpf_config_mac(struct bnx2x *bp, const u8 *addr, u8 vf_qid,
|
||||
bool set);
|
||||
int bnx2x_vfpf_config_rss(struct bnx2x *bp,
|
||||
struct bnx2x_config_rss_params *params);
|
||||
int bnx2x_vfpf_set_mcast(struct net_device *dev);
|
||||
|
||||
@@ -721,7 +721,7 @@ out:
|
||||
}
|
||||
|
||||
/* request pf to add a mac for the vf */
|
||||
int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr, u8 vf_qid, bool set)
|
||||
int bnx2x_vfpf_config_mac(struct bnx2x *bp, const u8 *addr, u8 vf_qid, bool set)
|
||||
{
|
||||
struct vfpf_set_q_filters_tlv *req = &bp->vf2pf_mbox->req.set_q_filters;
|
||||
struct pfvf_general_resp_tlv *resp = &bp->vf2pf_mbox->resp.general_resp;
|
||||
|
||||
@@ -4869,7 +4869,7 @@ static int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp,
|
||||
#endif
|
||||
|
||||
static int bnxt_hwrm_set_vnic_filter(struct bnxt *bp, u16 vnic_id, u16 idx,
|
||||
u8 *mac_addr)
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct hwrm_cfa_l2_filter_alloc_output *resp;
|
||||
struct hwrm_cfa_l2_filter_alloc_input *req;
|
||||
@@ -6366,7 +6366,7 @@ static int __bnxt_reserve_rings(struct bnxt *bp)
|
||||
if (rx_rings != bp->rx_nr_rings) {
|
||||
netdev_warn(bp->dev, "Able to reserve only %d out of %d requested RX rings\n",
|
||||
rx_rings, bp->rx_nr_rings);
|
||||
if ((bp->dev->priv_flags & IFF_RXFH_CONFIGURED) &&
|
||||
if (netif_is_rxfh_configured(bp->dev) &&
|
||||
(bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) !=
|
||||
bnxt_get_nr_rss_ctxs(bp, rx_rings) ||
|
||||
bnxt_get_max_rss_ring(bp) >= rx_rings)) {
|
||||
|
||||
@@ -909,7 +909,7 @@ static int bnxt_set_channels(struct net_device *dev,
|
||||
|
||||
if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) !=
|
||||
bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) &&
|
||||
(dev->priv_flags & IFF_RXFH_CONFIGURED)) {
|
||||
netif_is_rxfh_configured(dev)) {
|
||||
netdev_warn(dev, "RSS table size change required, RSS table entries must be default to proceed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1151,7 +1151,7 @@ void bnxt_hwrm_exec_fwd_req(struct bnxt *bp)
|
||||
}
|
||||
}
|
||||
|
||||
int bnxt_approve_mac(struct bnxt *bp, u8 *mac, bool strict)
|
||||
int bnxt_approve_mac(struct bnxt *bp, const u8 *mac, bool strict)
|
||||
{
|
||||
struct hwrm_func_vf_cfg_input *req;
|
||||
int rc = 0;
|
||||
@@ -1246,7 +1246,7 @@ void bnxt_update_vf_mac(struct bnxt *bp)
|
||||
{
|
||||
}
|
||||
|
||||
int bnxt_approve_mac(struct bnxt *bp, u8 *mac, bool strict)
|
||||
int bnxt_approve_mac(struct bnxt *bp, const u8 *mac, bool strict)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -41,5 +41,5 @@ int bnxt_cfg_hw_sriov(struct bnxt *bp, int *num_vfs, bool reset);
|
||||
void bnxt_sriov_disable(struct bnxt *);
|
||||
void bnxt_hwrm_exec_fwd_req(struct bnxt *);
|
||||
void bnxt_update_vf_mac(struct bnxt *);
|
||||
int bnxt_approve_mac(struct bnxt *, u8 *, bool);
|
||||
int bnxt_approve_mac(struct bnxt *, const u8 *, bool);
|
||||
#endif
|
||||
|
||||
@@ -3266,7 +3266,7 @@ static void bcmgenet_umac_reset(struct bcmgenet_priv *priv)
|
||||
}
|
||||
|
||||
static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv,
|
||||
unsigned char *addr)
|
||||
const unsigned char *addr)
|
||||
{
|
||||
bcmgenet_umac_writel(priv, get_unaligned_be32(&addr[0]), UMAC_MAC0);
|
||||
bcmgenet_umac_writel(priv, get_unaligned_be16(&addr[4]), UMAC_MAC1);
|
||||
@@ -3560,7 +3560,7 @@ static void bcmgenet_timeout(struct net_device *dev, unsigned int txqueue)
|
||||
#define MAX_MDF_FILTER 17
|
||||
|
||||
static inline void bcmgenet_set_mdf_addr(struct bcmgenet_priv *priv,
|
||||
unsigned char *addr,
|
||||
const unsigned char *addr,
|
||||
int *i)
|
||||
{
|
||||
bcmgenet_umac_writel(priv, addr[0] << 8 | addr[1],
|
||||
@@ -4085,8 +4085,12 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
||||
eth_hw_addr_set(dev, pd->mac_address);
|
||||
else
|
||||
if (device_get_ethdev_address(&pdev->dev, dev))
|
||||
if (has_acpi_companion(&pdev->dev))
|
||||
bcmgenet_get_hw_addr(priv, dev->dev_addr);
|
||||
if (has_acpi_companion(&pdev->dev)) {
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
bcmgenet_get_hw_addr(priv, addr);
|
||||
eth_hw_addr_set(dev, addr);
|
||||
}
|
||||
|
||||
if (!is_valid_ether_addr(dev->dev_addr)) {
|
||||
dev_warn(&pdev->dev, "using random Ethernet MAC\n");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user