2019-10-14 21:51:20 +05:30
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018, Sensor-Technik Wiedemann GmbH
2019-05-02 23:23:30 +03:00
* Copyright ( c ) 2018 - 2019 , Vladimir Oltean < olteanv @ gmail . com >
*/
# ifndef _SJA1105_H
# define _SJA1105_H
net: dsa: sja1105: Add support for the PTP clock
The design of this PHC driver is influenced by the switch's behavior
w.r.t. timestamping. It exposes two PTP counters, one free-running
(PTPTSCLK) and the other offset- and frequency-corrected in hardware
through PTPCLKVAL, PTPCLKADD and PTPCLKRATE. The MACs can sample either
of these for frame timestamps.
However, the user manual warns that taking timestamps based on the
corrected clock is less than useful, as the switch can deliver corrupted
timestamps in a variety of circumstances.
Therefore, this PHC uses the free-running PTPTSCLK together with a
timecounter/cyclecounter structure that translates it into a software
time domain. Thus, the settime/adjtime and adjfine callbacks are
hardware no-ops.
The timestamps (introduced in a further patch) will also be translated
to the correct time domain before being handed over to the userspace PTP
stack.
The introduction of a second set of PHC operations that operate on the
hardware PTPCLKVAL/PTPCLKADD/PTPCLKRATE in the future is somewhat
unavoidable, as the TTEthernet core uses the corrected PTP time domain.
However, the free-running counter + timecounter structure combination
will suffice for now, as the resulting timestamps yield a sub-50 ns
synchronization offset in steady state using linuxptp.
For this patch, in absence of frame timestamping, the operations of the
switch PHC were tested by syncing it to the system time as a local slave
clock with:
phc2sys -s CLOCK_REALTIME -c swp2 -O 0 -m -S 0.01
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-06-08 15:04:34 +03:00
# include <linux/ptp_clock_kernel.h>
# include <linux/timecounter.h>
2019-05-02 23:23:30 +03:00
# include <linux/dsa/sja1105.h>
# include <net/dsa.h>
2019-05-05 13:19:27 +03:00
# include <linux/mutex.h>
2019-05-02 23:23:30 +03:00
# include "sja1105_static_config.h"
# define SJA1105_NUM_PORTS 5
# define SJA1105_NUM_TC 8
# define SJA1105ET_FDB_BIN_SIZE 4
2019-05-02 23:23:36 +03:00
/* The hardware value is in multiples of 10 ms.
* The passed parameter is in multiples of 1 ms .
*/
# define SJA1105_AGEING_TIME_MS(ms) ((ms) / 10)
2019-05-02 23:23:30 +03:00
2019-11-12 02:11:53 +02:00
typedef enum {
SPI_READ = 0 ,
SPI_WRITE = 1 ,
} sja1105_spi_rw_mode_t ;
2019-09-15 05:00:02 +03:00
# include "sja1105_tas.h"
2019-10-12 02:18:15 +03:00
# include "sja1105_ptp.h"
2019-09-15 05:00:02 +03:00
2019-05-02 23:23:30 +03:00
/* Keeps the different addresses between E/T and P/Q/R/S */
struct sja1105_regs {
u64 device_id ;
u64 prod_id ;
u64 status ;
2019-05-02 23:23:37 +03:00
u64 port_control ;
2019-05-02 23:23:30 +03:00
u64 rgu ;
u64 config ;
2020-03-20 13:29:37 +02:00
u64 sgmii ;
2019-05-02 23:23:30 +03:00
u64 rmii_pll1 ;
net: dsa: sja1105: Add support for the PTP clock
The design of this PHC driver is influenced by the switch's behavior
w.r.t. timestamping. It exposes two PTP counters, one free-running
(PTPTSCLK) and the other offset- and frequency-corrected in hardware
through PTPCLKVAL, PTPCLKADD and PTPCLKRATE. The MACs can sample either
of these for frame timestamps.
However, the user manual warns that taking timestamps based on the
corrected clock is less than useful, as the switch can deliver corrupted
timestamps in a variety of circumstances.
Therefore, this PHC uses the free-running PTPTSCLK together with a
timecounter/cyclecounter structure that translates it into a software
time domain. Thus, the settime/adjtime and adjfine callbacks are
hardware no-ops.
The timestamps (introduced in a further patch) will also be translated
to the correct time domain before being handed over to the userspace PTP
stack.
The introduction of a second set of PHC operations that operate on the
hardware PTPCLKVAL/PTPCLKADD/PTPCLKRATE in the future is somewhat
unavoidable, as the TTEthernet core uses the corrected PTP time domain.
However, the free-running counter + timecounter structure combination
will suffice for now, as the resulting timestamps yield a sub-50 ns
synchronization offset in steady state using linuxptp.
For this patch, in absence of frame timestamping, the operations of the
switch PHC were tested by syncing it to the system time as a local slave
clock with:
phc2sys -s CLOCK_REALTIME -c swp2 -O 0 -m -S 0.01
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-06-08 15:04:34 +03:00
u64 ptp_control ;
2019-10-16 21:41:02 +03:00
u64 ptpclkval ;
net: dsa: sja1105: Add support for the PTP clock
The design of this PHC driver is influenced by the switch's behavior
w.r.t. timestamping. It exposes two PTP counters, one free-running
(PTPTSCLK) and the other offset- and frequency-corrected in hardware
through PTPCLKVAL, PTPCLKADD and PTPCLKRATE. The MACs can sample either
of these for frame timestamps.
However, the user manual warns that taking timestamps based on the
corrected clock is less than useful, as the switch can deliver corrupted
timestamps in a variety of circumstances.
Therefore, this PHC uses the free-running PTPTSCLK together with a
timecounter/cyclecounter structure that translates it into a software
time domain. Thus, the settime/adjtime and adjfine callbacks are
hardware no-ops.
The timestamps (introduced in a further patch) will also be translated
to the correct time domain before being handed over to the userspace PTP
stack.
The introduction of a second set of PHC operations that operate on the
hardware PTPCLKVAL/PTPCLKADD/PTPCLKRATE in the future is somewhat
unavoidable, as the TTEthernet core uses the corrected PTP time domain.
However, the free-running counter + timecounter structure combination
will suffice for now, as the resulting timestamps yield a sub-50 ns
synchronization offset in steady state using linuxptp.
For this patch, in absence of frame timestamping, the operations of the
switch PHC were tested by syncing it to the system time as a local slave
clock with:
phc2sys -s CLOCK_REALTIME -c swp2 -O 0 -m -S 0.01
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-06-08 15:04:34 +03:00
u64 ptpclkrate ;
2019-11-12 02:11:54 +02:00
u64 ptpclkcorp ;
u64 ptpschtm ;
2019-06-08 15:04:35 +03:00
u64 ptpegr_ts [ SJA1105_NUM_PORTS ] ;
2019-05-02 23:23:30 +03:00
u64 pad_mii_tx [ SJA1105_NUM_PORTS ] ;
2019-06-08 19:12:27 +03:00
u64 pad_mii_id [ SJA1105_NUM_PORTS ] ;
2019-05-02 23:23:30 +03:00
u64 cgu_idiv [ SJA1105_NUM_PORTS ] ;
u64 mii_tx_clk [ SJA1105_NUM_PORTS ] ;
u64 mii_rx_clk [ SJA1105_NUM_PORTS ] ;
u64 mii_ext_tx_clk [ SJA1105_NUM_PORTS ] ;
u64 mii_ext_rx_clk [ SJA1105_NUM_PORTS ] ;
u64 rgmii_tx_clk [ SJA1105_NUM_PORTS ] ;
u64 rmii_ref_clk [ SJA1105_NUM_PORTS ] ;
u64 rmii_ext_tx_clk [ SJA1105_NUM_PORTS ] ;
u64 mac [ SJA1105_NUM_PORTS ] ;
u64 mac_hl1 [ SJA1105_NUM_PORTS ] ;
u64 mac_hl2 [ SJA1105_NUM_PORTS ] ;
u64 qlevel [ SJA1105_NUM_PORTS ] ;
} ;
struct sja1105_info {
u64 device_id ;
/* Needed for distinction between P and R, and between Q and S
* ( since the parts with / without SGMII share the same
* switch core and device_id )
*/
u64 part_no ;
2019-06-08 15:04:35 +03:00
/* E/T and P/Q/R/S have partial timestamps of different sizes.
* They must be reconstructed on both families anyway to get the full
* 64 - bit values back .
*/
int ptp_ts_bits ;
/* Also SPI commands are of different sizes to retrieve
* the egress timestamps .
*/
int ptpegr_ts_bytes ;
2019-05-02 23:23:30 +03:00
const struct sja1105_dynamic_table_ops * dyn_ops ;
const struct sja1105_table_ops * static_ops ;
const struct sja1105_regs * regs ;
2019-11-13 00:16:41 +02:00
int ( * reset_cmd ) ( struct dsa_switch * ds ) ;
net: dsa: sja1105: Error out if RGMII delays are requested in DT
Documentation/devicetree/bindings/net/ethernet.txt is confusing because
it says what the MAC should not do, but not what it *should* do:
* "rgmii-rxid" (RGMII with internal RX delay provided by the PHY, the MAC
should not add an RX delay in this case)
The gap in semantics is threefold:
1. Is it illegal for the MAC to apply the Rx internal delay by itself,
and simplify the phy_mode (mask off "rgmii-rxid" into "rgmii") before
passing it to of_phy_connect? The documentation would suggest yes.
1. For "rgmii-rxid", while the situation with the Rx clock skew is more
or less clear (needs to be added by the PHY), what should the MAC
driver do about the Tx delays? Is it an implicit wild card for the
MAC to apply delays in the Tx direction if it can? What if those were
already added as serpentine PCB traces, how could that be made more
obvious through DT bindings so that the MAC doesn't attempt to add
them twice and again potentially break the link?
3. If the interface is a fixed-link and therefore the PHY object is
fixed (a purely software entity that obviously cannot add clock
skew), what is the meaning of the above property?
So an interpretation of the RGMII bindings was chosen that hopefully
does not contradict their intention but also makes them more applied.
The SJA1105 driver understands to act upon "rgmii-*id" phy-mode bindings
if the port is in the PHY role (either explicitly, or if it is a
fixed-link). Otherwise it always passes the duty of setting up delays to
the PHY driver.
The error behavior that this patch adds is required on SJA1105E/T where
the MAC really cannot apply internal delays. If the other end of the
fixed-link cannot apply RGMII delays either (this would be specified
through its own DT bindings), then the situation requires PCB delays.
For SJA1105P/Q/R/S, this is however hardware supported and the error is
thus only temporary. I created a stub function pointer for configuring
delays per-port on RXC and TXC, and will implement it when I have access
to a board with this hardware setup.
Meanwhile do not allow the user to select an invalid configuration.
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-05-02 23:23:32 +03:00
int ( * setup_rgmii_delay ) ( const void * ctx , int port ) ;
2019-06-03 00:11:57 +03:00
/* Prototypes from include/net/dsa.h */
int ( * fdb_add_cmd ) ( struct dsa_switch * ds , int port ,
const unsigned char * addr , u16 vid ) ;
int ( * fdb_del_cmd ) ( struct dsa_switch * ds , int port ,
const unsigned char * addr , u16 vid ) ;
2019-11-12 02:11:53 +02:00
void ( * ptp_cmd_packing ) ( u8 * buf , struct sja1105_ptp_cmd * cmd ,
enum packing_op op ) ;
2019-05-02 23:23:30 +03:00
const char * name ;
} ;
struct sja1105_private {
struct sja1105_static_config static_config ;
net: dsa: sja1105: Error out if RGMII delays are requested in DT
Documentation/devicetree/bindings/net/ethernet.txt is confusing because
it says what the MAC should not do, but not what it *should* do:
* "rgmii-rxid" (RGMII with internal RX delay provided by the PHY, the MAC
should not add an RX delay in this case)
The gap in semantics is threefold:
1. Is it illegal for the MAC to apply the Rx internal delay by itself,
and simplify the phy_mode (mask off "rgmii-rxid" into "rgmii") before
passing it to of_phy_connect? The documentation would suggest yes.
1. For "rgmii-rxid", while the situation with the Rx clock skew is more
or less clear (needs to be added by the PHY), what should the MAC
driver do about the Tx delays? Is it an implicit wild card for the
MAC to apply delays in the Tx direction if it can? What if those were
already added as serpentine PCB traces, how could that be made more
obvious through DT bindings so that the MAC doesn't attempt to add
them twice and again potentially break the link?
3. If the interface is a fixed-link and therefore the PHY object is
fixed (a purely software entity that obviously cannot add clock
skew), what is the meaning of the above property?
So an interpretation of the RGMII bindings was chosen that hopefully
does not contradict their intention but also makes them more applied.
The SJA1105 driver understands to act upon "rgmii-*id" phy-mode bindings
if the port is in the PHY role (either explicitly, or if it is a
fixed-link). Otherwise it always passes the duty of setting up delays to
the PHY driver.
The error behavior that this patch adds is required on SJA1105E/T where
the MAC really cannot apply internal delays. If the other end of the
fixed-link cannot apply RGMII delays either (this would be specified
through its own DT bindings), then the situation requires PCB delays.
For SJA1105P/Q/R/S, this is however hardware supported and the error is
thus only temporary. I created a stub function pointer for configuring
delays per-port on RXC and TXC, and will implement it when I have access
to a board with this hardware setup.
Meanwhile do not allow the user to select an invalid configuration.
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-05-02 23:23:32 +03:00
bool rgmii_rx_delay [ SJA1105_NUM_PORTS ] ;
bool rgmii_tx_delay [ SJA1105_NUM_PORTS ] ;
2019-05-02 23:23:30 +03:00
const struct sja1105_info * info ;
struct gpio_desc * reset_gpio ;
struct spi_device * spidev ;
struct dsa_switch * ds ;
2019-05-05 13:19:27 +03:00
struct sja1105_port ports [ SJA1105_NUM_PORTS ] ;
/* Serializes transmission of management frames so that
* the switch doesn ' t confuse them with one another .
*/
struct mutex mgmt_lock ;
2019-06-08 15:04:40 +03:00
struct sja1105_tagger_data tagger_data ;
2019-10-12 02:18:15 +03:00
struct sja1105_ptp_data ptp_data ;
2019-09-15 05:00:02 +03:00
struct sja1105_tas_data tas_data ;
2019-05-02 23:23:30 +03:00
} ;
# include "sja1105_dynamic_config.h"
struct sja1105_spi_message {
u64 access ;
u64 read_count ;
u64 address ;
} ;
2019-09-15 05:00:02 +03:00
/* From sja1105_main.c */
2019-11-12 23:22:00 +02:00
enum sja1105_reset_reason {
SJA1105_VLAN_FILTERING = 0 ,
SJA1105_RX_HWTSTAMPING ,
SJA1105_AGEING_TIME ,
SJA1105_SCHEDULING ,
} ;
int sja1105_static_config_reload ( struct sja1105_private * priv ,
enum sja1105_reset_reason reason ) ;
2019-09-15 05:00:02 +03:00
2019-05-02 23:23:30 +03:00
/* From sja1105_spi.c */
2019-10-01 22:18:01 +03:00
int sja1105_xfer_buf ( const struct sja1105_private * priv ,
sja1105_spi_rw_mode_t rw , u64 reg_addr ,
net: dsa: sja1105: Switch to scatter/gather API for SPI
This reworks the SPI transfer implementation to make use of more of the
SPI core features. The main benefit is to avoid the memcpy in
sja1105_xfer_buf().
The memcpy was only needed because the function was transferring a
single buffer at a time. So it needed to copy the caller-provided buffer
at buf + 4, to store the SPI message header in the "headroom" area.
But the SPI core supports scatter-gather messages, comprised of multiple
transfers. We can actually use those to break apart every SPI message
into 2 transfers: one for the header and one for the actual payload.
To keep the behavior the same regarding the chip select signal, it is
necessary to tell the SPI core to de-assert the chip select after each
chunk. This was not needed before, because each spi_message contained
only 1 single transfer.
The meaning of the per-transfer cs_change=1 is:
- If the transfer is the last one of the message, keep CS asserted
- Otherwise, deassert CS
We need to deassert CS in the "otherwise" case, which was implicit
before.
Avoiding the memcpy creates yet another opportunity. The device can't
process more than 256 bytes of SPI payload at a time, so the
sja1105_xfer_long_buf() function used to exist, to split the larger
caller buffer into chunks.
But these chunks couldn't be used as scatter/gather buffers for
spi_message until now, because of that memcpy (we would have needed more
memory for each chunk). So we can now remove the sja1105_xfer_long_buf()
function and have a single implementation for long and short buffers.
Another benefit is lower usage of stack memory. Previously we had to
store 2 SPI buffers for each chunk. Due to the elimination of the
memcpy, we can now send pointers to the actual chunks from the
caller-supplied buffer to the SPI core.
Since the patch merges two functions into a rewritten implementation,
the function prototype was also changed, mainly for cosmetic consistency
with the structures used within it.
Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-10-12 01:31:15 +03:00
u8 * buf , size_t len ) ;
2019-10-01 22:18:00 +03:00
int sja1105_xfer_u32 ( const struct sja1105_private * priv ,
2019-11-09 13:32:22 +02:00
sja1105_spi_rw_mode_t rw , u64 reg_addr , u32 * value ,
struct ptp_system_timestamp * ptp_sts ) ;
2019-10-01 22:18:00 +03:00
int sja1105_xfer_u64 ( const struct sja1105_private * priv ,
2019-11-09 13:32:22 +02:00
sja1105_spi_rw_mode_t rw , u64 reg_addr , u64 * value ,
struct ptp_system_timestamp * ptp_sts ) ;
2019-05-02 23:23:30 +03:00
int sja1105_static_config_upload ( struct sja1105_private * priv ) ;
2019-06-08 16:03:43 +03:00
int sja1105_inhibit_tx ( const struct sja1105_private * priv ,
unsigned long port_bitmap , bool tx_inhibited ) ;
2019-05-02 23:23:30 +03:00
extern struct sja1105_info sja1105e_info ;
extern struct sja1105_info sja1105t_info ;
extern struct sja1105_info sja1105p_info ;
extern struct sja1105_info sja1105q_info ;
extern struct sja1105_info sja1105r_info ;
extern struct sja1105_info sja1105s_info ;
/* From sja1105_clocking.c */
typedef enum {
XMII_MAC = 0 ,
XMII_PHY = 1 ,
} sja1105_mii_role_t ;
typedef enum {
XMII_MODE_MII = 0 ,
XMII_MODE_RMII = 1 ,
XMII_MODE_RGMII = 2 ,
2020-03-20 13:29:37 +02:00
XMII_MODE_SGMII = 3 ,
2019-05-02 23:23:30 +03:00
} sja1105_phy_interface_t ;
typedef enum {
SJA1105_SPEED_10MBPS = 3 ,
SJA1105_SPEED_100MBPS = 2 ,
SJA1105_SPEED_1000MBPS = 1 ,
SJA1105_SPEED_AUTO = 0 ,
} sja1105_speed_t ;
2019-06-08 19:12:28 +03:00
int sja1105pqrs_setup_rgmii_delay ( const void * ctx , int port ) ;
2019-05-02 23:23:30 +03:00
int sja1105_clocking_setup_port ( struct sja1105_private * priv , int port ) ;
int sja1105_clocking_setup ( struct sja1105_private * priv ) ;
2019-05-02 23:23:35 +03:00
/* From sja1105_ethtool.c */
void sja1105_get_ethtool_stats ( struct dsa_switch * ds , int port , u64 * data ) ;
void sja1105_get_strings ( struct dsa_switch * ds , int port ,
u32 stringset , u8 * data ) ;
int sja1105_get_sset_count ( struct dsa_switch * ds , int port , int sset ) ;
2019-05-02 23:23:30 +03:00
2019-05-02 23:23:35 +03:00
/* From sja1105_dynamic_config.c */
2019-05-02 23:23:30 +03:00
int sja1105_dynamic_config_read ( struct sja1105_private * priv ,
enum sja1105_blk_idx blk_idx ,
int index , void * entry ) ;
int sja1105_dynamic_config_write ( struct sja1105_private * priv ,
enum sja1105_blk_idx blk_idx ,
int index , void * entry , bool keep ) ;
2019-06-03 00:15:45 +03:00
enum sja1105_iotag {
SJA1105_C_TAG = 0 , /* Inner VLAN header */
SJA1105_S_TAG = 1 , /* Outer VLAN header */
} ;
2019-06-03 00:11:57 +03:00
u8 sja1105et_fdb_hash ( struct sja1105_private * priv , const u8 * addr , u16 vid ) ;
int sja1105et_fdb_add ( struct dsa_switch * ds , int port ,
const unsigned char * addr , u16 vid ) ;
int sja1105et_fdb_del ( struct dsa_switch * ds , int port ,
const unsigned char * addr , u16 vid ) ;
int sja1105pqrs_fdb_add ( struct dsa_switch * ds , int port ,
const unsigned char * addr , u16 vid ) ;
int sja1105pqrs_fdb_del ( struct dsa_switch * ds , int port ,
const unsigned char * addr , u16 vid ) ;
2019-05-02 23:23:31 +03:00
2019-05-02 23:23:30 +03:00
/* Common implementations for the static and dynamic configs */
size_t sja1105_l2_forwarding_entry_packing ( void * buf , void * entry_ptr ,
enum packing_op op ) ;
size_t sja1105pqrs_l2_lookup_entry_packing ( void * buf , void * entry_ptr ,
enum packing_op op ) ;
size_t sja1105et_l2_lookup_entry_packing ( void * buf , void * entry_ptr ,
enum packing_op op ) ;
size_t sja1105_vlan_lookup_entry_packing ( void * buf , void * entry_ptr ,
enum packing_op op ) ;
size_t sja1105pqrs_mac_config_entry_packing ( void * buf , void * entry_ptr ,
enum packing_op op ) ;
# endif