mirror of
https://github.com/torvalds/linux.git
synced 2024-09-20 06:53:04 +00:00
Merge branch 'add-support-for-open-alliance-10base-t1x-macphy-serial-interface'
Parthiban Veerasooran says: ==================== Add support for OPEN Alliance 10BASE-T1x MACPHY Serial Interface This patch series contain the below updates, - Adds support for OPEN Alliance 10BASE-T1x MACPHY Serial Interface in the net/ethernet/oa_tc6.c. Link to the spec: ----------------- https://opensig.org/download/document/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf - Adds driver support for Microchip LAN8650/1 Rev.B1 10BASE-T1S MACPHY Ethernet driver in the net/ethernet/microchip/lan865x/lan865x.c. Link to the product: -------------------- https://www.microchip.com/en-us/product/lan8650 Testing Details: ---------------- The driver performance was tested using iperf3 in the below two setups separately. Setup 1: -------- Node 0 - Raspberry Pi 4 with LAN8650 MAC-PHY Node 1 - Raspberry Pi 4 with EVB-LAN8670-USB USB Stick Setup 2: -------- Node 0 - SAMA7G54-EK with LAN8650 MAC-PHY Node 1 - Raspberry Pi 4 with EVB-LAN8670-USB USB Stick Achieved maximum of 9.4 Mbps. Some systems like Raspberry Pi 4 need performance mode enabled to get the proper clock speed for SPI. Refer below link for more details. https://github.com/raspberrypi/linux/issues/3381#issuecomment-1144723750 ==================== Link: https://patch.msgid.link/20240909082514.262942-1-Parthiban.Veerasooran@microchip.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
3cfb5aa10c
74
Documentation/devicetree/bindings/net/microchip,lan8650.yaml
Normal file
74
Documentation/devicetree/bindings/net/microchip,lan8650.yaml
Normal file
|
@ -0,0 +1,74 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/net/microchip,lan8650.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip LAN8650/1 10BASE-T1S MACPHY Ethernet Controllers
|
||||
|
||||
maintainers:
|
||||
- Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
|
||||
|
||||
description:
|
||||
The LAN8650/1 combines a Media Access Controller (MAC) and an Ethernet
|
||||
PHY to enable 10BASE‑T1S networks. The Ethernet Media Access Controller
|
||||
(MAC) module implements a 10 Mbps half duplex Ethernet MAC, compatible
|
||||
with the IEEE 802.3 standard and a 10BASE-T1S physical layer transceiver
|
||||
integrated into the LAN8650/1. The communication between the Host and
|
||||
the MAC-PHY is specified in the OPEN Alliance 10BASE-T1x MACPHY Serial
|
||||
Interface (TC6).
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/net/ethernet-controller.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: microchip,lan8650
|
||||
- items:
|
||||
- const: microchip,lan8651
|
||||
- const: microchip,lan8650
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
Interrupt from MAC-PHY asserted in the event of Receive Chunks
|
||||
Available, Transmit Chunk Credits Available and Extended Status
|
||||
Event.
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
minimum: 15000000
|
||||
maximum: 25000000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- spi-max-frequency
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ethernet@0 {
|
||||
compatible = "microchip,lan8651", "microchip,lan8650";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <ð0_pins>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
|
||||
local-mac-address = [04 05 06 01 02 03];
|
||||
spi-max-frequency = <15000000>;
|
||||
};
|
||||
};
|
|
@ -88,6 +88,7 @@ Contents:
|
|||
nexthop-group-resilient
|
||||
nf_conntrack-sysctl
|
||||
nf_flowtable
|
||||
oa-tc6-framework
|
||||
openvswitch
|
||||
operstates
|
||||
packet_mmap
|
||||
|
|
497
Documentation/networking/oa-tc6-framework.rst
Normal file
497
Documentation/networking/oa-tc6-framework.rst
Normal file
|
@ -0,0 +1,497 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
=========================================================================
|
||||
OPEN Alliance 10BASE-T1x MAC-PHY Serial Interface (TC6) Framework Support
|
||||
=========================================================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The IEEE 802.3cg project defines two 10 Mbit/s PHYs operating over a
|
||||
single pair of conductors. The 10BASE-T1L (Clause 146) is a long reach
|
||||
PHY supporting full duplex point-to-point operation over 1 km of single
|
||||
balanced pair of conductors. The 10BASE-T1S (Clause 147) is a short reach
|
||||
PHY supporting full / half duplex point-to-point operation over 15 m of
|
||||
single balanced pair of conductors, or half duplex multidrop bus
|
||||
operation over 25 m of single balanced pair of conductors.
|
||||
|
||||
Furthermore, the IEEE 802.3cg project defines the new Physical Layer
|
||||
Collision Avoidance (PLCA) Reconciliation Sublayer (Clause 148) meant to
|
||||
provide improved determinism to the CSMA/CD media access method. PLCA
|
||||
works in conjunction with the 10BASE-T1S PHY operating in multidrop mode.
|
||||
|
||||
The aforementioned PHYs are intended to cover the low-speed / low-cost
|
||||
applications in industrial and automotive environment. The large number
|
||||
of pins (16) required by the MII interface, which is specified by the
|
||||
IEEE 802.3 in Clause 22, is one of the major cost factors that need to be
|
||||
addressed to fulfil this objective.
|
||||
|
||||
The MAC-PHY solution integrates an IEEE Clause 4 MAC and a 10BASE-T1x PHY
|
||||
exposing a low pin count Serial Peripheral Interface (SPI) to the host
|
||||
microcontroller. This also enables the addition of Ethernet functionality
|
||||
to existing low-end microcontrollers which do not integrate a MAC
|
||||
controller.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The MAC-PHY is specified to carry both data (Ethernet frames) and control
|
||||
(register access) transactions over a single full-duplex serial peripheral
|
||||
interface.
|
||||
|
||||
Protocol Overview
|
||||
-----------------
|
||||
|
||||
Two types of transactions are defined in the protocol: data transactions
|
||||
for Ethernet frame transfers and control transactions for register
|
||||
read/write transfers. A chunk is the basic element of data transactions
|
||||
and is composed of 4 bytes of overhead plus 64 bytes of payload size for
|
||||
each chunk. Ethernet frames are transferred over one or more data chunks.
|
||||
Control transactions consist of one or more register read/write control
|
||||
commands.
|
||||
|
||||
SPI transactions are initiated by the SPI host with the assertion of CSn
|
||||
low to the MAC-PHY and ends with the deassertion of CSn high. In between
|
||||
each SPI transaction, the SPI host may need time for additional
|
||||
processing and to setup the next SPI data or control transaction.
|
||||
|
||||
SPI data transactions consist of an equal number of transmit (TX) and
|
||||
receive (RX) chunks. Chunks in both transmit and receive directions may
|
||||
or may not contain valid frame data independent from each other, allowing
|
||||
for the simultaneous transmission and reception of different length
|
||||
frames.
|
||||
|
||||
Each transmit data chunk begins with a 32-bit data header followed by a
|
||||
data chunk payload on MOSI. The data header indicates whether transmit
|
||||
frame data is present and provides the information to determine which
|
||||
bytes of the payload contain valid frame data.
|
||||
|
||||
In parallel, receive data chunks are received on MISO. Each receive data
|
||||
chunk consists of a data chunk payload ending with a 32-bit data footer.
|
||||
The data footer indicates if there is receive frame data present within
|
||||
the payload or not and provides the information to determine which bytes
|
||||
of the payload contain valid frame data.
|
||||
|
||||
Reference
|
||||
---------
|
||||
|
||||
10BASE-T1x MAC-PHY Serial Interface Specification,
|
||||
|
||||
Link: https://opensig.org/download/document/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf
|
||||
|
||||
Hardware Architecture
|
||||
---------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
+----------+ +-------------------------------------+
|
||||
| | | MAC-PHY |
|
||||
| |<---->| +-----------+ +-------+ +-------+ |
|
||||
| SPI Host | | | SPI Slave | | MAC | | PHY | |
|
||||
| | | +-----------+ +-------+ +-------+ |
|
||||
+----------+ +-------------------------------------+
|
||||
|
||||
Software Architecture
|
||||
---------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
+----------------------------------------------------------+
|
||||
| Networking Subsystem |
|
||||
+----------------------------------------------------------+
|
||||
/ \ / \
|
||||
| |
|
||||
| |
|
||||
\ / |
|
||||
+----------------------+ +-----------------------------+
|
||||
| MAC Driver |<--->| OPEN Alliance TC6 Framework |
|
||||
+----------------------+ +-----------------------------+
|
||||
/ \ / \
|
||||
| |
|
||||
| |
|
||||
| \ /
|
||||
+----------------------------------------------------------+
|
||||
| SPI Subsystem |
|
||||
+----------------------------------------------------------+
|
||||
/ \
|
||||
|
|
||||
|
|
||||
\ /
|
||||
+----------------------------------------------------------+
|
||||
| 10BASE-T1x MAC-PHY Device |
|
||||
+----------------------------------------------------------+
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
MAC Driver
|
||||
~~~~~~~~~~
|
||||
|
||||
- Probed by SPI subsystem.
|
||||
|
||||
- Initializes OA TC6 framework for the MAC-PHY.
|
||||
|
||||
- Registers and configures the network device.
|
||||
|
||||
- Sends the tx ethernet frames from n/w subsystem to OA TC6 framework.
|
||||
|
||||
OPEN Alliance TC6 Framework
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Initializes PHYLIB interface.
|
||||
|
||||
- Registers mac-phy interrupt.
|
||||
|
||||
- Performs mac-phy register read/write operation using the control
|
||||
transaction protocol specified in the OPEN Alliance 10BASE-T1x MAC-PHY
|
||||
Serial Interface specification.
|
||||
|
||||
- Performs Ethernet frames transaction using the data transaction protocol
|
||||
for Ethernet frames specified in the OPEN Alliance 10BASE-T1x MAC-PHY
|
||||
Serial Interface specification.
|
||||
|
||||
- Forwards the received Ethernet frame from 10Base-T1x MAC-PHY to n/w
|
||||
subsystem.
|
||||
|
||||
Data Transaction
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The Ethernet frames that are typically transferred from the SPI host to
|
||||
the MAC-PHY will be converted into multiple transmit data chunks. Each
|
||||
transmit data chunk will have a 4 bytes header which contains the
|
||||
information needed to determine the validity and the location of the
|
||||
transmit frame data within the 64 bytes data chunk payload.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
+---------------------------------------------------+
|
||||
| Tx Chunk |
|
||||
| +---------------------------+ +----------------+ | MOSI
|
||||
| | 64 bytes chunk payload | | 4 bytes header | |------------>
|
||||
| +---------------------------+ +----------------+ |
|
||||
+---------------------------------------------------+
|
||||
|
||||
4 bytes header contains the below fields,
|
||||
|
||||
DNC (Bit 31) - Data-Not-Control flag. This flag specifies the type of SPI
|
||||
transaction. For TX data chunks, this bit shall be ’1’.
|
||||
0 - Control command
|
||||
1 - Data chunk
|
||||
|
||||
SEQ (Bit 30) - Data Chunk Sequence. This bit is used to indicate an
|
||||
even/odd transmit data chunk sequence to the MAC-PHY.
|
||||
|
||||
NORX (Bit 29) - No Receive flag. The SPI host may set this bit to prevent
|
||||
the MAC-PHY from conveying RX data on the MISO for the
|
||||
current chunk (DV = 0 in the footer), indicating that the
|
||||
host would not process it. Typically, the SPI host should
|
||||
set NORX = 0 indicating that it will accept and process
|
||||
any receive frame data within the current chunk.
|
||||
|
||||
RSVD (Bit 28..24) - Reserved: All reserved bits shall be ‘0’.
|
||||
|
||||
VS (Bit 23..22) - Vendor Specific. These bits are implementation specific.
|
||||
If the MAC-PHY does not implement these bits, the host
|
||||
shall set them to ‘0’.
|
||||
|
||||
DV (Bit 21) - Data Valid flag. The SPI host uses this bit to indicate
|
||||
whether the current chunk contains valid transmit frame data
|
||||
(DV = 1) or not (DV = 0). When ‘0’, the MAC-PHY ignores the
|
||||
chunk payload. Note that the receive path is unaffected by
|
||||
the setting of the DV bit in the data header.
|
||||
|
||||
SV (Bit 20) - Start Valid flag. The SPI host shall set this bit when the
|
||||
beginning of an Ethernet frame is present in the current
|
||||
transmit data chunk payload. Otherwise, this bit shall be
|
||||
zero. This bit is not to be confused with the Start-of-Frame
|
||||
Delimiter (SFD) byte described in IEEE 802.3 [2].
|
||||
|
||||
SWO (Bit 19..16) - Start Word Offset. When SV = 1, this field shall
|
||||
contain the 32-bit word offset into the transmit data
|
||||
chunk payload that points to the start of a new
|
||||
Ethernet frame to be transmitted. The host shall write
|
||||
this field as zero when SV = 0.
|
||||
|
||||
RSVD (Bit 15) - Reserved: All reserved bits shall be ‘0’.
|
||||
|
||||
EV (Bit 14) - End Valid flag. The SPI host shall set this bit when the end
|
||||
of an Ethernet frame is present in the current transmit data
|
||||
chunk payload. Otherwise, this bit shall be zero.
|
||||
|
||||
EBO (Bit 13..8) - End Byte Offset. When EV = 1, this field shall contain
|
||||
the byte offset into the transmit data chunk payload
|
||||
that points to the last byte of the Ethernet frame to
|
||||
transmit. This field shall be zero when EV = 0.
|
||||
|
||||
TSC (Bit 7..6) - Timestamp Capture. Request a timestamp capture when the
|
||||
frame is transmitted onto the network.
|
||||
00 - Do not capture a timestamp
|
||||
01 - Capture timestamp into timestamp capture register A
|
||||
10 - Capture timestamp into timestamp capture register B
|
||||
11 - Capture timestamp into timestamp capture register C
|
||||
|
||||
RSVD (Bit 5..1) - Reserved: All reserved bits shall be ‘0’.
|
||||
|
||||
P (Bit 0) - Parity. Parity bit calculated over the transmit data header.
|
||||
Method used is odd parity.
|
||||
|
||||
The number of buffers available in the MAC-PHY to store the incoming
|
||||
transmit data chunk payloads is represented as transmit credits. The
|
||||
available transmit credits in the MAC-PHY can be read either from the
|
||||
Buffer Status Register or footer (Refer below for the footer info)
|
||||
received from the MAC-PHY. The SPI host should not write more data chunks
|
||||
than the available transmit credits as this will lead to transmit buffer
|
||||
overflow error.
|
||||
|
||||
In case the previous data footer had no transmit credits available and
|
||||
once the transmit credits become available for transmitting transmit data
|
||||
chunks, the MAC-PHY interrupt is asserted to SPI host. On reception of the
|
||||
first data header this interrupt will be deasserted and the received
|
||||
footer for the first data chunk will have the transmit credits available
|
||||
information.
|
||||
|
||||
The Ethernet frames that are typically transferred from MAC-PHY to SPI
|
||||
host will be sent as multiple receive data chunks. Each receive data
|
||||
chunk will have 64 bytes of data chunk payload followed by 4 bytes footer
|
||||
which contains the information needed to determine the validity and the
|
||||
location of the receive frame data within the 64 bytes data chunk payload.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
+---------------------------------------------------+
|
||||
| Rx Chunk |
|
||||
| +----------------+ +---------------------------+ | MISO
|
||||
| | 4 bytes footer | | 64 bytes chunk payload | |------------>
|
||||
| +----------------+ +---------------------------+ |
|
||||
+---------------------------------------------------+
|
||||
|
||||
4 bytes footer contains the below fields,
|
||||
|
||||
EXST (Bit 31) - Extended Status. This bit is set when any bit in the
|
||||
STATUS0 or STATUS1 registers are set and not masked.
|
||||
|
||||
HDRB (Bit 30) - Received Header Bad. When set, indicates that the MAC-PHY
|
||||
received a control or data header with a parity error.
|
||||
|
||||
SYNC (Bit 29) - Configuration Synchronized flag. This bit reflects the
|
||||
state of the SYNC bit in the CONFIG0 configuration
|
||||
register (see Table 12). A zero indicates that the MAC-PHY
|
||||
configuration may not be as expected by the SPI host.
|
||||
Following configuration, the SPI host sets the
|
||||
corresponding bitin the configuration register which is
|
||||
reflected in this field.
|
||||
|
||||
RCA (Bit 28..24) - Receive Chunks Available. The RCA field indicates to
|
||||
the SPI host the minimum number of additional receive
|
||||
data chunks of frame data that are available for
|
||||
reading beyond the current receive data chunk. This
|
||||
field is zero when there is no receive frame data
|
||||
pending in the MAC-PHY’s buffer for reading.
|
||||
|
||||
VS (Bit 23..22) - Vendor Specific. These bits are implementation specific.
|
||||
If not implemented, the MAC-PHY shall set these bits to
|
||||
‘0’.
|
||||
|
||||
DV (Bit 21) - Data Valid flag. The MAC-PHY uses this bit to indicate
|
||||
whether the current receive data chunk contains valid
|
||||
receive frame data (DV = 1) or not (DV = 0). When ‘0’, the
|
||||
SPI host shall ignore the chunk payload.
|
||||
|
||||
SV (Bit 20) - Start Valid flag. The MAC-PHY sets this bit when the current
|
||||
chunk payload contains the start of an Ethernet frame.
|
||||
Otherwise, this bit is zero. The SV bit is not to be
|
||||
confused with the Start-of-Frame Delimiter (SFD) byte
|
||||
described in IEEE 802.3 [2].
|
||||
|
||||
SWO (Bit 19..16) - Start Word Offset. When SV = 1, this field contains the
|
||||
32-bit word offset into the receive data chunk payload
|
||||
containing the first byte of a new received Ethernet
|
||||
frame. When a receive timestamp has been added to the
|
||||
beginning of the received Ethernet frame (RTSA = 1)
|
||||
then SWO points to the most significant byte of the
|
||||
timestamp. This field will be zero when SV = 0.
|
||||
|
||||
FD (Bit 15) - Frame Drop. When set, this bit indicates that the MAC has
|
||||
detected a condition for which the SPI host should drop the
|
||||
received Ethernet frame. This bit is only valid at the end
|
||||
of a received Ethernet frame (EV = 1) and shall be zero at
|
||||
all other times.
|
||||
|
||||
EV (Bit 14) - End Valid flag. The MAC-PHY sets this bit when the end of a
|
||||
received Ethernet frame is present in this receive data
|
||||
chunk payload.
|
||||
|
||||
EBO (Bit 13..8) - End Byte Offset: When EV = 1, this field contains the
|
||||
byte offset into the receive data chunk payload that
|
||||
locates the last byte of the received Ethernet frame.
|
||||
This field is zero when EV = 0.
|
||||
|
||||
RTSA (Bit 7) - Receive Timestamp Added. This bit is set when a 32-bit or
|
||||
64-bit timestamp has been added to the beginning of the
|
||||
received Ethernet frame. The MAC-PHY shall set this bit to
|
||||
zero when SV = 0.
|
||||
|
||||
RTSP (Bit 6) - Receive Timestamp Parity. Parity bit calculated over the
|
||||
32-bit/64-bit timestamp added to the beginning of the
|
||||
received Ethernet frame. Method used is odd parity. The
|
||||
MAC-PHY shall set this bit to zero when RTSA = 0.
|
||||
|
||||
TXC (Bit 5..1) - Transmit Credits. This field contains the minimum number
|
||||
of transmit data chunks of frame data that the SPI host
|
||||
can write in a single transaction without incurring a
|
||||
transmit buffer overflow error.
|
||||
|
||||
P (Bit 0) - Parity. Parity bit calculated over the receive data footer.
|
||||
Method used is odd parity.
|
||||
|
||||
SPI host will initiate the data receive transaction based on the receive
|
||||
chunks available in the MAC-PHY which is provided in the receive chunk
|
||||
footer (RCA - Receive Chunks Available). SPI host will create data invalid
|
||||
transmit data chunks (empty chunks) or data valid transmit data chunks in
|
||||
case there are valid Ethernet frames to transmit to the MAC-PHY. The
|
||||
receive chunks available in MAC-PHY can be read either from the Buffer
|
||||
Status Register or footer.
|
||||
|
||||
In case the previous data footer had no receive data chunks available and
|
||||
once the receive data chunks become available again for reading, the
|
||||
MAC-PHY interrupt is asserted to SPI host. On reception of the first data
|
||||
header this interrupt will be deasserted and the received footer for the
|
||||
first data chunk will have the receive chunks available information.
|
||||
|
||||
MAC-PHY Interrupt
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The MAC-PHY interrupt is asserted when the following conditions are met.
|
||||
|
||||
Receive chunks available - This interrupt is asserted when the previous
|
||||
data footer had no receive data chunks available and once the receive
|
||||
data chunks become available for reading. On reception of the first data
|
||||
header this interrupt will be deasserted.
|
||||
|
||||
Transmit chunk credits available - This interrupt is asserted when the
|
||||
previous data footer indicated no transmit credits available and once the
|
||||
transmit credits become available for transmitting transmit data chunks.
|
||||
On reception of the first data header this interrupt will be deasserted.
|
||||
|
||||
Extended status event - This interrupt is asserted when the previous data
|
||||
footer indicated no extended status and once the extended event become
|
||||
available. In this case the host should read status #0 register to know
|
||||
the corresponding error/event. On reception of the first data header this
|
||||
interrupt will be deasserted.
|
||||
|
||||
Control Transaction
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
4 bytes control header contains the below fields,
|
||||
|
||||
DNC (Bit 31) - Data-Not-Control flag. This flag specifies the type of SPI
|
||||
transaction. For control commands, this bit shall be ‘0’.
|
||||
0 - Control command
|
||||
1 - Data chunk
|
||||
|
||||
HDRB (Bit 30) - Received Header Bad. When set by the MAC-PHY, indicates
|
||||
that a header was received with a parity error. The SPI
|
||||
host should always clear this bit. The MAC-PHY ignores the
|
||||
HDRB value sent by the SPI host on MOSI.
|
||||
|
||||
WNR (Bit 29) - Write-Not-Read. This bit indicates if data is to be written
|
||||
to registers (when set) or read from registers
|
||||
(when clear).
|
||||
|
||||
AID (Bit 28) - Address Increment Disable. When clear, the address will be
|
||||
automatically post-incremented by one following each
|
||||
register read or write. When set, address auto increment is
|
||||
disabled allowing successive reads and writes to occur at
|
||||
the same register address.
|
||||
|
||||
MMS (Bit 27..24) - Memory Map Selector. This field selects the specific
|
||||
register memory map to access.
|
||||
|
||||
ADDR (Bit 23..8) - Address. Address of the first register within the
|
||||
selected memory map to access.
|
||||
|
||||
LEN (Bit 7..1) - Length. Specifies the number of registers to read/write.
|
||||
This field is interpreted as the number of registers
|
||||
minus 1 allowing for up to 128 consecutive registers read
|
||||
or written starting at the address specified in ADDR. A
|
||||
length of zero shall read or write a single register.
|
||||
|
||||
P (Bit 0) - Parity. Parity bit calculated over the control command header.
|
||||
Method used is odd parity.
|
||||
|
||||
Control transactions consist of one or more control commands. Control
|
||||
commands are used by the SPI host to read and write registers within the
|
||||
MAC-PHY. Each control commands are composed of a 4 bytes control command
|
||||
header followed by register write data in case of control write command.
|
||||
|
||||
The MAC-PHY ignores the final 4 bytes of data from the SPI host at the end
|
||||
of the control write command. The control write command is also echoed
|
||||
from the MAC-PHY back to the SPI host to identify which register write
|
||||
failed in case of any bus errors. The echoed Control write command will
|
||||
have the first 4 bytes unused value to be ignored by the SPI host
|
||||
followed by 4 bytes echoed control header followed by echoed register
|
||||
write data. Control write commands can write either a single register or
|
||||
multiple consecutive registers. When multiple consecutive registers are
|
||||
written, the address is automatically post-incremented by the MAC-PHY.
|
||||
Writing to any unimplemented or undefined registers shall be ignored and
|
||||
yield no effect.
|
||||
|
||||
The MAC-PHY ignores all data from the SPI host following the control
|
||||
header for the remainder of the control read command. The control read
|
||||
command is also echoed from the MAC-PHY back to the SPI host to identify
|
||||
which register read is failed in case of any bus errors. The echoed
|
||||
Control read command will have the first 4 bytes of unused value to be
|
||||
ignored by the SPI host followed by 4 bytes echoed control header followed
|
||||
by register read data. Control read commands can read either a single
|
||||
register or multiple consecutive registers. When multiple consecutive
|
||||
registers are read, the address is automatically post-incremented by the
|
||||
MAC-PHY. Reading any unimplemented or undefined registers shall return
|
||||
zero.
|
||||
|
||||
Device drivers API
|
||||
==================
|
||||
|
||||
The include/linux/oa_tc6.h defines the following functions:
|
||||
|
||||
.. c:function:: struct oa_tc6 *oa_tc6_init(struct spi_device *spi, \
|
||||
struct net_device *netdev)
|
||||
|
||||
Initialize OA TC6 lib.
|
||||
|
||||
.. c:function:: void oa_tc6_exit(struct oa_tc6 *tc6)
|
||||
|
||||
Free allocated OA TC6 lib.
|
||||
|
||||
.. c:function:: int oa_tc6_write_register(struct oa_tc6 *tc6, u32 address, \
|
||||
u32 value)
|
||||
|
||||
Write a single register in the MAC-PHY.
|
||||
|
||||
.. c:function:: int oa_tc6_write_registers(struct oa_tc6 *tc6, u32 address, \
|
||||
u32 value[], u8 length)
|
||||
|
||||
Writing multiple consecutive registers starting from @address in the MAC-PHY.
|
||||
Maximum of 128 consecutive registers can be written starting at @address.
|
||||
|
||||
.. c:function:: int oa_tc6_read_register(struct oa_tc6 *tc6, u32 address, \
|
||||
u32 *value)
|
||||
|
||||
Read a single register in the MAC-PHY.
|
||||
|
||||
.. c:function:: int oa_tc6_read_registers(struct oa_tc6 *tc6, u32 address, \
|
||||
u32 value[], u8 length)
|
||||
|
||||
Reading multiple consecutive registers starting from @address in the MAC-PHY.
|
||||
Maximum of 128 consecutive registers can be read starting at @address.
|
||||
|
||||
.. c:function:: netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, \
|
||||
struct sk_buff *skb);
|
||||
|
||||
The transmit Ethernet frame in the skb is or going to be transmitted through
|
||||
the MAC-PHY.
|
||||
|
||||
.. c:function:: int oa_tc6_zero_align_receive_frame_enable(struct oa_tc6 *tc6);
|
||||
|
||||
Zero align receive frame feature can be enabled to align all receive ethernet
|
||||
frames data to start at the beginning of any receive data chunk payload with a
|
||||
start word offset (SWO) of zero.
|
15
MAINTAINERS
15
MAINTAINERS
|
@ -14980,6 +14980,13 @@ L: netdev@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/net/ethernet/microchip/lan743x_*
|
||||
|
||||
MICROCHIP LAN8650/1 10BASE-T1S MACPHY ETHERNET DRIVER
|
||||
M: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/net/microchip,lan8650.yaml
|
||||
F: drivers/net/ethernet/microchip/lan865x/lan865x.c
|
||||
|
||||
MICROCHIP LAN87xx/LAN937x T1 PHY DRIVER
|
||||
M: Arun Ramadoss <arun.ramadoss@microchip.com>
|
||||
R: UNGLinuxDriver@microchip.com
|
||||
|
@ -17113,6 +17120,14 @@ L: linux-rdma@vger.kernel.org
|
|||
S: Supported
|
||||
F: drivers/infiniband/ulp/opa_vnic
|
||||
|
||||
OPEN ALLIANCE 10BASE-T1S MACPHY SERIAL INTERFACE FRAMEWORK
|
||||
M: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/networking/oa-tc6-framework.rst
|
||||
F: drivers/include/linux/oa_tc6.h
|
||||
F: drivers/net/ethernet/oa_tc6.c
|
||||
|
||||
OPEN FIRMWARE AND FLATTENED DEVICE TREE
|
||||
M: Rob Herring <robh@kernel.org>
|
||||
M: Saravana Kannan <saravanak@google.com>
|
||||
|
|
|
@ -158,6 +158,17 @@ config ETHOC
|
|||
help
|
||||
Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
|
||||
|
||||
config OA_TC6
|
||||
tristate "OPEN Alliance TC6 10BASE-T1x MAC-PHY support"
|
||||
depends on SPI
|
||||
select PHYLIB
|
||||
help
|
||||
This library implements OPEN Alliance TC6 10BASE-T1x MAC-PHY
|
||||
Serial Interface protocol for supporting 10BASE-T1x MAC-PHYs.
|
||||
|
||||
To know the implementation details, refer documentation in
|
||||
<file:Documentation/networking/oa-tc6-framework.rst>.
|
||||
|
||||
source "drivers/net/ethernet/packetengines/Kconfig"
|
||||
source "drivers/net/ethernet/pasemi/Kconfig"
|
||||
source "drivers/net/ethernet/pensando/Kconfig"
|
||||
|
|
|
@ -105,3 +105,4 @@ obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
|
|||
obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
|
||||
obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/
|
||||
obj-$(CONFIG_NET_VENDOR_PENSANDO) += pensando/
|
||||
obj-$(CONFIG_OA_TC6) += oa_tc6.o
|
||||
|
|
|
@ -57,6 +57,7 @@ config LAN743X
|
|||
To compile this driver as a module, choose M here. The module will be
|
||||
called lan743x.
|
||||
|
||||
source "drivers/net/ethernet/microchip/lan865x/Kconfig"
|
||||
source "drivers/net/ethernet/microchip/lan966x/Kconfig"
|
||||
source "drivers/net/ethernet/microchip/sparx5/Kconfig"
|
||||
source "drivers/net/ethernet/microchip/vcap/Kconfig"
|
||||
|
|
|
@ -9,6 +9,7 @@ obj-$(CONFIG_LAN743X) += lan743x.o
|
|||
|
||||
lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
|
||||
|
||||
obj-$(CONFIG_LAN865X) += lan865x/
|
||||
obj-$(CONFIG_LAN966X_SWITCH) += lan966x/
|
||||
obj-$(CONFIG_SPARX5_SWITCH) += sparx5/
|
||||
obj-$(CONFIG_VCAP) += vcap/
|
||||
|
|
19
drivers/net/ethernet/microchip/lan865x/Kconfig
Normal file
19
drivers/net/ethernet/microchip/lan865x/Kconfig
Normal file
|
@ -0,0 +1,19 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Microchip LAN865x Driver Support
|
||||
#
|
||||
|
||||
if NET_VENDOR_MICROCHIP
|
||||
|
||||
config LAN865X
|
||||
tristate "LAN865x support"
|
||||
depends on SPI
|
||||
select OA_TC6
|
||||
help
|
||||
Support for the Microchip LAN8650/1 Rev.B0/B1 MACPHY Ethernet chip. It
|
||||
uses OPEN Alliance 10BASE-T1x Serial Interface specification.
|
||||
|
||||
To compile this driver as a module, choose M here. The module will be
|
||||
called lan865x.
|
||||
|
||||
endif # NET_VENDOR_MICROCHIP
|
6
drivers/net/ethernet/microchip/lan865x/Makefile
Normal file
6
drivers/net/ethernet/microchip/lan865x/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Makefile for the Microchip LAN865x Driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_LAN865X) += lan865x.o
|
429
drivers/net/ethernet/microchip/lan865x/lan865x.c
Normal file
429
drivers/net/ethernet/microchip/lan865x/lan865x.c
Normal file
|
@ -0,0 +1,429 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Microchip's LAN865x 10BASE-T1S MAC-PHY driver
|
||||
*
|
||||
* Author: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/oa_tc6.h>
|
||||
|
||||
#define DRV_NAME "lan8650"
|
||||
|
||||
/* MAC Network Control Register */
|
||||
#define LAN865X_REG_MAC_NET_CTL 0x00010000
|
||||
#define MAC_NET_CTL_TXEN BIT(3) /* Transmit Enable */
|
||||
#define MAC_NET_CTL_RXEN BIT(2) /* Receive Enable */
|
||||
|
||||
/* MAC Network Configuration Reg */
|
||||
#define LAN865X_REG_MAC_NET_CFG 0x00010001
|
||||
#define MAC_NET_CFG_PROMISCUOUS_MODE BIT(4)
|
||||
#define MAC_NET_CFG_MULTICAST_MODE BIT(6)
|
||||
#define MAC_NET_CFG_UNICAST_MODE BIT(7)
|
||||
|
||||
/* MAC Hash Register Bottom */
|
||||
#define LAN865X_REG_MAC_L_HASH 0x00010020
|
||||
/* MAC Hash Register Top */
|
||||
#define LAN865X_REG_MAC_H_HASH 0x00010021
|
||||
/* MAC Specific Addr 1 Bottom Reg */
|
||||
#define LAN865X_REG_MAC_L_SADDR1 0x00010022
|
||||
/* MAC Specific Addr 1 Top Reg */
|
||||
#define LAN865X_REG_MAC_H_SADDR1 0x00010023
|
||||
|
||||
struct lan865x_priv {
|
||||
struct work_struct multicast_work;
|
||||
struct net_device *netdev;
|
||||
struct spi_device *spi;
|
||||
struct oa_tc6 *tc6;
|
||||
};
|
||||
|
||||
static int lan865x_set_hw_macaddr_low_bytes(struct oa_tc6 *tc6, const u8 *mac)
|
||||
{
|
||||
u32 regval;
|
||||
|
||||
regval = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
|
||||
|
||||
return oa_tc6_write_register(tc6, LAN865X_REG_MAC_L_SADDR1, regval);
|
||||
}
|
||||
|
||||
static int lan865x_set_hw_macaddr(struct lan865x_priv *priv, const u8 *mac)
|
||||
{
|
||||
int restore_ret;
|
||||
u32 regval;
|
||||
int ret;
|
||||
|
||||
/* Configure MAC address low bytes */
|
||||
ret = lan865x_set_hw_macaddr_low_bytes(priv->tc6, mac);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Prepare and configure MAC address high bytes */
|
||||
regval = (mac[5] << 8) | mac[4];
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_SADDR1,
|
||||
regval);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
/* Restore the old MAC address low bytes from netdev if the new MAC
|
||||
* address high bytes setting failed.
|
||||
*/
|
||||
restore_ret = lan865x_set_hw_macaddr_low_bytes(priv->tc6,
|
||||
priv->netdev->dev_addr);
|
||||
if (restore_ret)
|
||||
return restore_ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops lan865x_ethtool_ops = {
|
||||
.get_link_ksettings = phy_ethtool_get_link_ksettings,
|
||||
.set_link_ksettings = phy_ethtool_set_link_ksettings,
|
||||
};
|
||||
|
||||
static int lan865x_set_mac_address(struct net_device *netdev, void *addr)
|
||||
{
|
||||
struct lan865x_priv *priv = netdev_priv(netdev);
|
||||
struct sockaddr *address = addr;
|
||||
int ret;
|
||||
|
||||
ret = eth_prepare_mac_addr_change(netdev, addr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ether_addr_equal(address->sa_data, netdev->dev_addr))
|
||||
return 0;
|
||||
|
||||
ret = lan865x_set_hw_macaddr(priv, address->sa_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
eth_commit_mac_addr_change(netdev, addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 get_address_bit(u8 addr[ETH_ALEN], u32 bit)
|
||||
{
|
||||
return ((addr[bit / 8]) >> (bit % 8)) & 1;
|
||||
}
|
||||
|
||||
static u32 lan865x_hash(u8 addr[ETH_ALEN])
|
||||
{
|
||||
u32 hash_index = 0;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
u32 hash = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
hash ^= get_address_bit(addr, (j * 6) + i);
|
||||
|
||||
hash_index |= (hash << i);
|
||||
}
|
||||
|
||||
return hash_index;
|
||||
}
|
||||
|
||||
static int lan865x_set_specific_multicast_addr(struct lan865x_priv *priv)
|
||||
{
|
||||
struct netdev_hw_addr *ha;
|
||||
u32 hash_lo = 0;
|
||||
u32 hash_hi = 0;
|
||||
int ret;
|
||||
|
||||
netdev_for_each_mc_addr(ha, priv->netdev) {
|
||||
u32 bit_num = lan865x_hash(ha->addr);
|
||||
|
||||
if (bit_num >= BIT(5))
|
||||
hash_hi |= (1 << (bit_num - BIT(5)));
|
||||
else
|
||||
hash_lo |= (1 << bit_num);
|
||||
}
|
||||
|
||||
/* Enabling specific multicast addresses */
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_HASH, hash_hi);
|
||||
if (ret) {
|
||||
netdev_err(priv->netdev, "Failed to write reg_hashh: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_L_HASH, hash_lo);
|
||||
if (ret)
|
||||
netdev_err(priv->netdev, "Failed to write reg_hashl: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lan865x_set_all_multicast_addr(struct lan865x_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Enabling all multicast addresses */
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_HASH,
|
||||
0xffffffff);
|
||||
if (ret) {
|
||||
netdev_err(priv->netdev, "Failed to write reg_hashh: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_L_HASH,
|
||||
0xffffffff);
|
||||
if (ret)
|
||||
netdev_err(priv->netdev, "Failed to write reg_hashl: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lan865x_clear_all_multicast_addr(struct lan865x_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_H_HASH, 0);
|
||||
if (ret) {
|
||||
netdev_err(priv->netdev, "Failed to write reg_hashh: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_L_HASH, 0);
|
||||
if (ret)
|
||||
netdev_err(priv->netdev, "Failed to write reg_hashl: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lan865x_multicast_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct lan865x_priv *priv = container_of(work, struct lan865x_priv,
|
||||
multicast_work);
|
||||
u32 regval = 0;
|
||||
int ret;
|
||||
|
||||
if (priv->netdev->flags & IFF_PROMISC) {
|
||||
/* Enabling promiscuous mode */
|
||||
regval |= MAC_NET_CFG_PROMISCUOUS_MODE;
|
||||
regval &= (~MAC_NET_CFG_MULTICAST_MODE);
|
||||
regval &= (~MAC_NET_CFG_UNICAST_MODE);
|
||||
} else if (priv->netdev->flags & IFF_ALLMULTI) {
|
||||
/* Enabling all multicast mode */
|
||||
if (lan865x_set_all_multicast_addr(priv))
|
||||
return;
|
||||
|
||||
regval &= (~MAC_NET_CFG_PROMISCUOUS_MODE);
|
||||
regval |= MAC_NET_CFG_MULTICAST_MODE;
|
||||
regval &= (~MAC_NET_CFG_UNICAST_MODE);
|
||||
} else if (!netdev_mc_empty(priv->netdev)) {
|
||||
/* Enabling specific multicast mode */
|
||||
if (lan865x_set_specific_multicast_addr(priv))
|
||||
return;
|
||||
|
||||
regval &= (~MAC_NET_CFG_PROMISCUOUS_MODE);
|
||||
regval |= MAC_NET_CFG_MULTICAST_MODE;
|
||||
regval &= (~MAC_NET_CFG_UNICAST_MODE);
|
||||
} else {
|
||||
/* Enabling local mac address only */
|
||||
if (lan865x_clear_all_multicast_addr(priv))
|
||||
return;
|
||||
}
|
||||
ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_NET_CFG, regval);
|
||||
if (ret)
|
||||
netdev_err(priv->netdev, "Failed to enable promiscuous/multicast/normal mode: %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
static void lan865x_set_multicast_list(struct net_device *netdev)
|
||||
{
|
||||
struct lan865x_priv *priv = netdev_priv(netdev);
|
||||
|
||||
schedule_work(&priv->multicast_work);
|
||||
}
|
||||
|
||||
static netdev_tx_t lan865x_send_packet(struct sk_buff *skb,
|
||||
struct net_device *netdev)
|
||||
{
|
||||
struct lan865x_priv *priv = netdev_priv(netdev);
|
||||
|
||||
return oa_tc6_start_xmit(priv->tc6, skb);
|
||||
}
|
||||
|
||||
static int lan865x_hw_disable(struct lan865x_priv *priv)
|
||||
{
|
||||
u32 regval;
|
||||
|
||||
if (oa_tc6_read_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, ®val))
|
||||
return -ENODEV;
|
||||
|
||||
regval &= ~(MAC_NET_CTL_TXEN | MAC_NET_CTL_RXEN);
|
||||
|
||||
if (oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, regval))
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lan865x_net_close(struct net_device *netdev)
|
||||
{
|
||||
struct lan865x_priv *priv = netdev_priv(netdev);
|
||||
int ret;
|
||||
|
||||
netif_stop_queue(netdev);
|
||||
phy_stop(netdev->phydev);
|
||||
ret = lan865x_hw_disable(priv);
|
||||
if (ret) {
|
||||
netdev_err(netdev, "Failed to disable the hardware: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lan865x_hw_enable(struct lan865x_priv *priv)
|
||||
{
|
||||
u32 regval;
|
||||
|
||||
if (oa_tc6_read_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, ®val))
|
||||
return -ENODEV;
|
||||
|
||||
regval |= MAC_NET_CTL_TXEN | MAC_NET_CTL_RXEN;
|
||||
|
||||
if (oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_NET_CTL, regval))
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lan865x_net_open(struct net_device *netdev)
|
||||
{
|
||||
struct lan865x_priv *priv = netdev_priv(netdev);
|
||||
int ret;
|
||||
|
||||
ret = lan865x_hw_enable(priv);
|
||||
if (ret) {
|
||||
netdev_err(netdev, "Failed to enable hardware: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
phy_start(netdev->phydev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops lan865x_netdev_ops = {
|
||||
.ndo_open = lan865x_net_open,
|
||||
.ndo_stop = lan865x_net_close,
|
||||
.ndo_start_xmit = lan865x_send_packet,
|
||||
.ndo_set_rx_mode = lan865x_set_multicast_list,
|
||||
.ndo_set_mac_address = lan865x_set_mac_address,
|
||||
};
|
||||
|
||||
static int lan865x_probe(struct spi_device *spi)
|
||||
{
|
||||
struct net_device *netdev;
|
||||
struct lan865x_priv *priv;
|
||||
int ret;
|
||||
|
||||
netdev = alloc_etherdev(sizeof(struct lan865x_priv));
|
||||
if (!netdev)
|
||||
return -ENOMEM;
|
||||
|
||||
priv = netdev_priv(netdev);
|
||||
priv->netdev = netdev;
|
||||
priv->spi = spi;
|
||||
spi_set_drvdata(spi, priv);
|
||||
INIT_WORK(&priv->multicast_work, lan865x_multicast_work_handler);
|
||||
|
||||
priv->tc6 = oa_tc6_init(spi, netdev);
|
||||
if (!priv->tc6) {
|
||||
ret = -ENODEV;
|
||||
goto free_netdev;
|
||||
}
|
||||
|
||||
/* As per the point s3 in the below errata, SPI receive Ethernet frame
|
||||
* transfer may halt when starting the next frame in the same data block
|
||||
* (chunk) as the end of a previous frame. The RFA field should be
|
||||
* configured to 01b or 10b for proper operation. In these modes, only
|
||||
* one receive Ethernet frame will be placed in a single data block.
|
||||
* When the RFA field is written to 01b, received frames will be forced
|
||||
* to only start in the first word of the data block payload (SWO=0). As
|
||||
* recommended, enable zero align receive frame feature for proper
|
||||
* operation.
|
||||
*
|
||||
* https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/Errata/LAN8650-1-Errata-80001075.pdf
|
||||
*/
|
||||
ret = oa_tc6_zero_align_receive_frame_enable(priv->tc6);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to set ZARFE: %d\n", ret);
|
||||
goto oa_tc6_exit;
|
||||
}
|
||||
|
||||
/* Get the MAC address from the SPI device tree node */
|
||||
if (device_get_ethdev_address(&spi->dev, netdev))
|
||||
eth_hw_addr_random(netdev);
|
||||
|
||||
ret = lan865x_set_hw_macaddr(priv, netdev->dev_addr);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed to configure MAC: %d\n", ret);
|
||||
goto oa_tc6_exit;
|
||||
}
|
||||
|
||||
netdev->if_port = IF_PORT_10BASET;
|
||||
netdev->irq = spi->irq;
|
||||
netdev->netdev_ops = &lan865x_netdev_ops;
|
||||
netdev->ethtool_ops = &lan865x_ethtool_ops;
|
||||
|
||||
ret = register_netdev(netdev);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Register netdev failed (ret = %d)", ret);
|
||||
goto oa_tc6_exit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
oa_tc6_exit:
|
||||
oa_tc6_exit(priv->tc6);
|
||||
free_netdev:
|
||||
free_netdev(priv->netdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lan865x_remove(struct spi_device *spi)
|
||||
{
|
||||
struct lan865x_priv *priv = spi_get_drvdata(spi);
|
||||
|
||||
cancel_work_sync(&priv->multicast_work);
|
||||
unregister_netdev(priv->netdev);
|
||||
oa_tc6_exit(priv->tc6);
|
||||
free_netdev(priv->netdev);
|
||||
}
|
||||
|
||||
static const struct spi_device_id spidev_spi_ids[] = {
|
||||
{ .name = "lan8650" },
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct of_device_id lan865x_dt_ids[] = {
|
||||
{ .compatible = "microchip,lan8650" },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lan865x_dt_ids);
|
||||
|
||||
static struct spi_driver lan865x_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = lan865x_dt_ids,
|
||||
},
|
||||
.probe = lan865x_probe,
|
||||
.remove = lan865x_remove,
|
||||
.id_table = spidev_spi_ids,
|
||||
};
|
||||
module_spi_driver(lan865x_driver);
|
||||
|
||||
MODULE_DESCRIPTION(DRV_NAME " 10Base-T1S MACPHY Ethernet Driver");
|
||||
MODULE_AUTHOR("Parthiban Veerasooran <parthiban.veerasooran@microchip.com>");
|
||||
MODULE_LICENSE("GPL");
|
1361
drivers/net/ethernet/oa_tc6.c
Normal file
1361
drivers/net/ethernet/oa_tc6.c
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -268,6 +268,34 @@ static int lan86xx_read_status(struct phy_device *phydev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* OPEN Alliance 10BASE-T1x compliance MAC-PHYs will have both C22 and
|
||||
* C45 registers space. If the PHY is discovered via C22 bus protocol it assumes
|
||||
* it uses C22 protocol and always uses C22 registers indirect access to access
|
||||
* C45 registers. This is because, we don't have a clean separation between
|
||||
* C22/C45 register space and C22/C45 MDIO bus protocols. Resulting, PHY C45
|
||||
* registers direct access can't be used which can save multiple SPI bus access.
|
||||
* To support this feature, set .read_mmd/.write_mmd in the PHY driver to call
|
||||
* .read_c45/.write_c45 in the OPEN Alliance framework
|
||||
* drivers/net/ethernet/oa_tc6.c
|
||||
*/
|
||||
static int lan865x_phy_read_mmd(struct phy_device *phydev, int devnum,
|
||||
u16 regnum)
|
||||
{
|
||||
struct mii_bus *bus = phydev->mdio.bus;
|
||||
int addr = phydev->mdio.addr;
|
||||
|
||||
return __mdiobus_c45_read(bus, addr, devnum, regnum);
|
||||
}
|
||||
|
||||
static int lan865x_phy_write_mmd(struct phy_device *phydev, int devnum,
|
||||
u16 regnum, u16 val)
|
||||
{
|
||||
struct mii_bus *bus = phydev->mdio.bus;
|
||||
int addr = phydev->mdio.addr;
|
||||
|
||||
return __mdiobus_c45_write(bus, addr, devnum, regnum, val);
|
||||
}
|
||||
|
||||
static struct phy_driver microchip_t1s_driver[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1),
|
||||
|
@ -285,6 +313,8 @@ static struct phy_driver microchip_t1s_driver[] = {
|
|||
.features = PHY_BASIC_T1S_P2MP_FEATURES,
|
||||
.config_init = lan865x_revb0_config_init,
|
||||
.read_status = lan86xx_read_status,
|
||||
.read_mmd = lan865x_phy_read_mmd,
|
||||
.write_mmd = lan865x_phy_write_mmd,
|
||||
.get_plca_cfg = genphy_c45_plca_get_cfg,
|
||||
.set_plca_cfg = genphy_c45_plca_set_cfg,
|
||||
.get_plca_status = genphy_c45_plca_get_status,
|
||||
|
|
24
include/linux/oa_tc6.h
Normal file
24
include/linux/oa_tc6.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* OPEN Alliance 10BASE‑T1x MAC‑PHY Serial Interface framework
|
||||
*
|
||||
* Link: https://opensig.org/download/document/OPEN_Alliance_10BASET1x_MAC-PHY_Serial_Interface_V1.1.pdf
|
||||
*
|
||||
* Author: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
|
||||
*/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
struct oa_tc6;
|
||||
|
||||
struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev);
|
||||
void oa_tc6_exit(struct oa_tc6 *tc6);
|
||||
int oa_tc6_write_register(struct oa_tc6 *tc6, u32 address, u32 value);
|
||||
int oa_tc6_write_registers(struct oa_tc6 *tc6, u32 address, u32 value[],
|
||||
u8 length);
|
||||
int oa_tc6_read_register(struct oa_tc6 *tc6, u32 address, u32 *value);
|
||||
int oa_tc6_read_registers(struct oa_tc6 *tc6, u32 address, u32 value[],
|
||||
u8 length);
|
||||
netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb);
|
||||
int oa_tc6_zero_align_receive_frame_enable(struct oa_tc6 *tc6);
|
|
@ -23,6 +23,7 @@
|
|||
#define MDIO_MMD_DTEXS 5 /* DTE Extender Sublayer */
|
||||
#define MDIO_MMD_TC 6 /* Transmission Convergence */
|
||||
#define MDIO_MMD_AN 7 /* Auto-Negotiation */
|
||||
#define MDIO_MMD_POWER_UNIT 13 /* PHY Power Unit */
|
||||
#define MDIO_MMD_C22EXT 29 /* Clause 22 extension */
|
||||
#define MDIO_MMD_VEND1 30 /* Vendor specific 1 */
|
||||
#define MDIO_MMD_VEND2 31 /* Vendor specific 2 */
|
||||
|
|
Loading…
Reference in New Issue
Block a user