From bd1d76a6f18f2222dc08c5aa9ebcd0445111a27d Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:21:17 +0100 Subject: [PATCH 01/16] net: stmmac: improve .set_clk_tx_rate() method error message Improve the .set_clk_tx_rate() method error message to include the PHY interface mode along with the speed, which will be helpful to the RK implementations. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Reviewed-by: Jacob Keller Link: https://patch.msgid.link/E1uPjjx-0049r5-NN@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index b948df1bff9a8..c3845ec62fbdb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1062,8 +1062,8 @@ static void stmmac_mac_link_up(struct phylink_config *config, interface, speed); if (ret < 0) netdev_err(priv->dev, - "failed to configure transmit clock for %dMbps: %pe\n", - speed, ERR_PTR(ret)); + "failed to configure %s transmit clock for %dMbps: %pe\n", + phy_modes(interface), speed, ERR_PTR(ret)); } stmmac_mac_set(priv, priv->ioaddr, true); -- 2.51.0 From c035e736038045b411cb368e63f07bc2f5dbc0e1 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Thu, 12 Jun 2025 17:28:33 +0200 Subject: [PATCH 02/16] dpll: add phase-offset-monitor feature to netlink spec Add enum dpll_feature_state for control over features. Add dpll device level attribute: DPLL_A_PHASE_OFFSET_MONITOR - to allow control over a phase offset monitor feature. Attribute is present and shall return current state of a feature (enum dpll_feature_state), if the device driver provides such capability, otherwie attribute shall not be present. Reviewed-by: Aleksandr Loktionov Reviewed-by: Milena Olech Reviewed-by: Jiri Pirko Signed-off-by: Arkadiusz Kubalewski Acked-by: Vadim Fedorenko Link: https://patch.msgid.link/20250612152835.1703397-2-arkadiusz.kubalewski@intel.com Signed-off-by: Jakub Kicinski --- Documentation/driver-api/dpll.rst | 18 ++++++++++++++++++ Documentation/netlink/specs/dpll.yaml | 24 ++++++++++++++++++++++++ drivers/dpll/dpll_nl.c | 5 +++-- include/uapi/linux/dpll.h | 12 ++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/Documentation/driver-api/dpll.rst b/Documentation/driver-api/dpll.rst index e6855cd37e852..195e1e5d9a587 100644 --- a/Documentation/driver-api/dpll.rst +++ b/Documentation/driver-api/dpll.rst @@ -214,6 +214,24 @@ offset values are fractional with 3-digit decimal places and shell be divided with ``DPLL_PIN_PHASE_OFFSET_DIVIDER`` to get integer part and modulo divided to get fractional part. +Phase offset monitor +==================== + +Phase offset measurement is typically performed against the current active +source. However, some DPLL (Digital Phase-Locked Loop) devices may offer +the capability to monitor phase offsets across all available inputs. +The attribute and current feature state shall be included in the response +message of the ``DPLL_CMD_DEVICE_GET`` command for supported DPLL devices. +In such cases, users can also control the feature using the +``DPLL_CMD_DEVICE_SET`` command by setting the ``enum dpll_feature_state`` +values for the attribute. +Once enabled the phase offset measurements for the input shall be returned +in the ``DPLL_A_PIN_PHASE_OFFSET`` attribute. + + =============================== ======================== + ``DPLL_A_PHASE_OFFSET_MONITOR`` attr state of a feature + =============================== ======================== + Embedded SYNC ============= diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml index 115d1a8f50bd3..3bd6851c1d3c9 100644 --- a/Documentation/netlink/specs/dpll.yaml +++ b/Documentation/netlink/specs/dpll.yaml @@ -240,6 +240,20 @@ definitions: integer part of a measured phase offset value. Value of (DPLL_A_PHASE_OFFSET % DPLL_PHASE_OFFSET_DIVIDER) is a fractional part of a measured phase offset value. + - + type: enum + name: feature-state + doc: | + Allow control (enable/disable) and status checking over features. + entries: + - + name: disable + doc: | + feature shall be disabled + - + name: enable + doc: | + feature shall be enabled attribute-sets: - @@ -293,6 +307,14 @@ attribute-sets: be put to message multiple times to indicate possible parallel quality levels (e.g. one specified by ITU option 1 and another one specified by option 2). + - + name: phase-offset-monitor + type: u32 + enum: feature-state + doc: Receive or request state of phase offset monitor feature. + If enabled, dpll device shall monitor and notify all currently + available inputs for changes of their phase offset against the + dpll device. - name: pin enum-name: dpll_a_pin @@ -483,6 +505,7 @@ operations: - temp - clock-id - type + - phase-offset-monitor dump: reply: *dev-attrs @@ -499,6 +522,7 @@ operations: request: attributes: - id + - phase-offset-monitor - name: device-create-ntf doc: Notification about device appearing diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c index fe9b6893d2614..8de90310c3be9 100644 --- a/drivers/dpll/dpll_nl.c +++ b/drivers/dpll/dpll_nl.c @@ -37,8 +37,9 @@ static const struct nla_policy dpll_device_get_nl_policy[DPLL_A_ID + 1] = { }; /* DPLL_CMD_DEVICE_SET - do */ -static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_ID + 1] = { +static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_PHASE_OFFSET_MONITOR + 1] = { [DPLL_A_ID] = { .type = NLA_U32, }, + [DPLL_A_PHASE_OFFSET_MONITOR] = NLA_POLICY_MAX(NLA_U32, 1), }; /* DPLL_CMD_PIN_ID_GET - do */ @@ -105,7 +106,7 @@ static const struct genl_split_ops dpll_nl_ops[] = { .doit = dpll_nl_device_set_doit, .post_doit = dpll_post_doit, .policy = dpll_device_set_nl_policy, - .maxattr = DPLL_A_ID, + .maxattr = DPLL_A_PHASE_OFFSET_MONITOR, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h index bf97d4b6d51f7..349e1b3ca1aea 100644 --- a/include/uapi/linux/dpll.h +++ b/include/uapi/linux/dpll.h @@ -192,6 +192,17 @@ enum dpll_pin_capabilities { #define DPLL_PHASE_OFFSET_DIVIDER 1000 +/** + * enum dpll_feature_state - Allow control (enable/disable) and status checking + * over features. + * @DPLL_FEATURE_STATE_DISABLE: feature shall be disabled + * @DPLL_FEATURE_STATE_ENABLE: feature shall be enabled + */ +enum dpll_feature_state { + DPLL_FEATURE_STATE_DISABLE, + DPLL_FEATURE_STATE_ENABLE, +}; + enum dpll_a { DPLL_A_ID = 1, DPLL_A_MODULE_NAME, @@ -204,6 +215,7 @@ enum dpll_a { DPLL_A_TYPE, DPLL_A_LOCK_STATUS_ERROR, DPLL_A_CLOCK_QUALITY_LEVEL, + DPLL_A_PHASE_OFFSET_MONITOR, __DPLL_A_MAX, DPLL_A_MAX = (__DPLL_A_MAX - 1) -- 2.51.0 From 2952daf44a84670a6aa9e13edbc105bdab83ccba Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Thu, 12 Jun 2025 17:28:34 +0200 Subject: [PATCH 03/16] dpll: add phase_offset_monitor_get/set callback ops Add new callback operations for a dpll device: - phase_offset_monitor_get(..) - to obtain current state of phase offset monitor feature from dpll device, - phase_offset_monitor_set(..) - to allow feature configuration. Obtain the feature state value using the get callback and provide it to the user if the device driver implements callbacks. Execute the set callback upon user requests. Reviewed-by: Milena Olech Reviewed-by: Jiri Pirko Signed-off-by: Arkadiusz Kubalewski Acked-by: Vadim Fedorenko Link: https://patch.msgid.link/20250612152835.1703397-3-arkadiusz.kubalewski@intel.com Signed-off-by: Jakub Kicinski --- drivers/dpll/dpll_netlink.c | 69 +++++++++++++++++++++++++++++++++++-- include/linux/dpll.h | 8 +++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index c130f87147fa3..4619aaa18b9c0 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -126,6 +126,26 @@ dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll, return 0; } +static int +dpll_msg_add_phase_offset_monitor(struct sk_buff *msg, struct dpll_device *dpll, + struct netlink_ext_ack *extack) +{ + const struct dpll_device_ops *ops = dpll_device_ops(dpll); + enum dpll_feature_state state; + int ret; + + if (ops->phase_offset_monitor_set && ops->phase_offset_monitor_get) { + ret = ops->phase_offset_monitor_get(dpll, dpll_priv(dpll), + &state, extack); + if (ret) + return ret; + if (nla_put_u32(msg, DPLL_A_PHASE_OFFSET_MONITOR, state)) + return -EMSGSIZE; + } + + return 0; +} + static int dpll_msg_add_lock_status(struct sk_buff *msg, struct dpll_device *dpll, struct netlink_ext_ack *extack) @@ -591,6 +611,9 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg, return ret; if (nla_put_u32(msg, DPLL_A_TYPE, dpll->type)) return -EMSGSIZE; + ret = dpll_msg_add_phase_offset_monitor(msg, dpll, extack); + if (ret) + return ret; return 0; } @@ -746,6 +769,31 @@ int dpll_pin_change_ntf(struct dpll_pin *pin) } EXPORT_SYMBOL_GPL(dpll_pin_change_ntf); +static int +dpll_phase_offset_monitor_set(struct dpll_device *dpll, struct nlattr *a, + struct netlink_ext_ack *extack) +{ + const struct dpll_device_ops *ops = dpll_device_ops(dpll); + enum dpll_feature_state state = nla_get_u32(a), old_state; + int ret; + + if (!(ops->phase_offset_monitor_set && ops->phase_offset_monitor_get)) { + NL_SET_ERR_MSG_ATTR(extack, a, "dpll device not capable of phase offset monitor"); + return -EOPNOTSUPP; + } + ret = ops->phase_offset_monitor_get(dpll, dpll_priv(dpll), &old_state, + extack); + if (ret) { + NL_SET_ERR_MSG(extack, "unable to get current state of phase offset monitor"); + return ret; + } + if (state == old_state) + return 0; + + return ops->phase_offset_monitor_set(dpll, dpll_priv(dpll), state, + extack); +} + static int dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a, struct netlink_ext_ack *extack) @@ -1533,12 +1581,29 @@ int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info) return genlmsg_reply(msg, info); } -int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info) +static int +dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info) { - /* placeholder for set command */ + int ret; + + if (info->attrs[DPLL_A_PHASE_OFFSET_MONITOR]) { + struct nlattr *a = info->attrs[DPLL_A_PHASE_OFFSET_MONITOR]; + + ret = dpll_phase_offset_monitor_set(dpll, a, info->extack); + if (ret) + return ret; + } + return 0; } +int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct dpll_device *dpll = info->user_ptr[0]; + + return dpll_set_from_nlattr(dpll, info); +} + int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { struct dpll_dump_ctx *ctx = dpll_dump_context(cb); diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 5e4f9ab1cf755..6ad6c2968a28c 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -30,6 +30,14 @@ struct dpll_device_ops { void *dpll_priv, unsigned long *qls, struct netlink_ext_ack *extack); + int (*phase_offset_monitor_set)(const struct dpll_device *dpll, + void *dpll_priv, + enum dpll_feature_state state, + struct netlink_ext_ack *extack); + int (*phase_offset_monitor_get)(const struct dpll_device *dpll, + void *dpll_priv, + enum dpll_feature_state *state, + struct netlink_ext_ack *extack); }; struct dpll_pin_ops { -- 2.51.0 From 863c7e5059363a37dba19df78a37fb0960b331fa Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Thu, 12 Jun 2025 17:28:35 +0200 Subject: [PATCH 04/16] ice: add phase offset monitor for all PPS dpll inputs Implement a new admin command and helper function to handle and obtain CGU measurements for input pins. Add new callback operations to control the dpll device-level feature "phase offset monitor," allowing it to be enabled or disabled. If the feature is enabled, provide users with measured phase offsets and notifications. Initialize PPS DPLL with new callback operations if the feature is supported by the firmware. Reviewed-by: Milena Olech Signed-off-by: Arkadiusz Kubalewski Acked-by: Vadim Fedorenko Link: https://patch.msgid.link/20250612152835.1703397-4-arkadiusz.kubalewski@intel.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/intel/ice/ice_adminq_cmd.h | 20 ++ drivers/net/ethernet/intel/ice/ice_common.c | 26 +++ drivers/net/ethernet/intel/ice/ice_common.h | 3 + drivers/net/ethernet/intel/ice/ice_dpll.c | 193 +++++++++++++++++- drivers/net/ethernet/intel/ice/ice_dpll.h | 8 + drivers/net/ethernet/intel/ice/ice_main.c | 4 + 6 files changed, 252 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index bdee499f991a6..0ae7387e05992 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -2272,6 +2272,22 @@ struct ice_aqc_get_pkg_info_resp { struct ice_aqc_get_pkg_info pkg_info[]; }; +#define ICE_CGU_INPUT_PHASE_OFFSET_BYTES 6 + +struct ice_cgu_input_measure { + u8 phase_offset[ICE_CGU_INPUT_PHASE_OFFSET_BYTES]; + __le32 freq; +} __packed __aligned(sizeof(__le16)); + +#define ICE_AQC_GET_CGU_IN_MEAS_DPLL_IDX_M ICE_M(0xf, 0) + +/* Get CGU input measure command response data structure (indirect 0x0C59) */ +struct ice_aqc_get_cgu_input_measure { + u8 dpll_idx_opt; + u8 length; + u8 rsvd[6]; +}; + #define ICE_AQC_GET_CGU_MAX_PHASE_ADJ GENMASK(30, 0) /* Get CGU abilities command response data structure (indirect 0x0C61) */ @@ -2721,6 +2737,7 @@ struct ice_aq_desc { struct ice_aqc_add_get_update_free_vsi vsi_cmd; struct ice_aqc_add_update_free_vsi_resp add_update_free_vsi_res; struct ice_aqc_download_pkg download_pkg; + struct ice_aqc_get_cgu_input_measure get_cgu_input_measure; struct ice_aqc_set_cgu_input_config set_cgu_input_config; struct ice_aqc_get_cgu_input_config get_cgu_input_config; struct ice_aqc_set_cgu_output_config set_cgu_output_config; @@ -2772,6 +2789,8 @@ enum ice_aq_err { ICE_AQ_RC_OK = 0, /* Success */ ICE_AQ_RC_EPERM = 1, /* Operation not permitted */ ICE_AQ_RC_ENOENT = 2, /* No such element */ + ICE_AQ_RC_ESRCH = 3, /* Bad opcode */ + ICE_AQ_RC_EAGAIN = 8, /* Try again */ ICE_AQ_RC_ENOMEM = 9, /* Out of memory */ ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */ ICE_AQ_RC_EEXIST = 13, /* Object already exists */ @@ -2927,6 +2946,7 @@ enum ice_adminq_opc { ice_aqc_opc_get_pkg_info_list = 0x0C43, /* 1588/SyncE commands/events */ + ice_aqc_opc_get_cgu_input_measure = 0x0C59, ice_aqc_opc_get_cgu_abilities = 0x0C61, ice_aqc_opc_set_cgu_input_config = 0x0C62, ice_aqc_opc_get_cgu_input_config = 0x0C63, diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 4fedf0181c4e1..48ff515d7c617 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -4970,6 +4970,32 @@ ice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid, return status; } +/** + * ice_aq_get_cgu_input_pin_measure - get input pin signal measurements + * @hw: pointer to the HW struct + * @dpll_idx: index of dpll to be measured + * @meas: array to be filled with results + * @meas_num: max number of results array can hold + * + * Get CGU measurements (0x0C59) of phase and frequency offsets for input + * pins on given dpll. + * + * Return: 0 on success or negative value on failure. + */ +int ice_aq_get_cgu_input_pin_measure(struct ice_hw *hw, u8 dpll_idx, + struct ice_cgu_input_measure *meas, + u16 meas_num) +{ + struct ice_aqc_get_cgu_input_measure *cmd; + struct ice_aq_desc desc; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_cgu_input_measure); + cmd = &desc.params.get_cgu_input_measure; + cmd->dpll_idx_opt = dpll_idx & ICE_AQC_GET_CGU_IN_MEAS_DPLL_IDX_M; + + return ice_aq_send_cmd(hw, &desc, meas, meas_num * sizeof(*meas), NULL); +} + /** * ice_aq_get_cgu_abilities - get cgu abilities * @hw: pointer to the HW struct diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 64c530b391917..c70f56d897dcb 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -229,6 +229,9 @@ void ice_replay_post(struct ice_hw *hw); struct ice_q_ctx * ice_get_lan_q_ctx(struct ice_hw *hw, u16 vsi_handle, u8 tc, u16 q_handle); int ice_sbq_rw_reg(struct ice_hw *hw, struct ice_sbq_msg_input *in, u16 flag); +int ice_aq_get_cgu_input_pin_measure(struct ice_hw *hw, u8 dpll_idx, + struct ice_cgu_input_measure *meas, + u16 meas_num); int ice_aq_get_cgu_abilities(struct ice_hw *hw, struct ice_aqc_get_cgu_abilities *abilities); diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index 9fc50bb3f35a8..d6190d9e32bac 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -12,6 +12,8 @@ #define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT 25 #define ICE_DPLL_PIN_GEN_RCLK_FREQ 1953125 #define ICE_DPLL_PIN_PRIO_OUTPUT 0xff +#define ICE_DPLL_INPUT_REF_NUM 10 +#define ICE_DPLL_PHASE_OFFSET_PERIOD 2 #define ICE_DPLL_SW_PIN_INPUT_BASE_SFP 4 #define ICE_DPLL_SW_PIN_INPUT_BASE_QSFP 6 #define ICE_DPLL_SW_PIN_OUTPUT_BASE 0 @@ -792,6 +794,67 @@ static int ice_dpll_mode_get(const struct dpll_device *dpll, void *dpll_priv, return 0; } +/** + * ice_dpll_phase_offset_monitor_set - set phase offset monitor state + * @dpll: registered dpll pointer + * @dpll_priv: private data pointer passed on dpll registration + * @state: feature state to be set + * @extack: error reporting + * + * Dpll subsystem callback. Enable/disable phase offset monitor feature of dpll. + * + * Context: Acquires and releases pf->dplls.lock + * Return: 0 - success + */ +static int ice_dpll_phase_offset_monitor_set(const struct dpll_device *dpll, + void *dpll_priv, + enum dpll_feature_state state, + struct netlink_ext_ack *extack) +{ + struct ice_dpll *d = dpll_priv; + struct ice_pf *pf = d->pf; + + mutex_lock(&pf->dplls.lock); + if (state == DPLL_FEATURE_STATE_ENABLE) + d->phase_offset_monitor_period = ICE_DPLL_PHASE_OFFSET_PERIOD; + else + d->phase_offset_monitor_period = 0; + mutex_unlock(&pf->dplls.lock); + + return 0; +} + +/** + * ice_dpll_phase_offset_monitor_get - get phase offset monitor state + * @dpll: registered dpll pointer + * @dpll_priv: private data pointer passed on dpll registration + * @state: on success holds current state of phase offset monitor + * @extack: error reporting + * + * Dpll subsystem callback. Provides current state of phase offset monitor + * features on dpll device. + * + * Context: Acquires and releases pf->dplls.lock + * Return: 0 - success + */ +static int ice_dpll_phase_offset_monitor_get(const struct dpll_device *dpll, + void *dpll_priv, + enum dpll_feature_state *state, + struct netlink_ext_ack *extack) +{ + struct ice_dpll *d = dpll_priv; + struct ice_pf *pf = d->pf; + + mutex_lock(&pf->dplls.lock); + if (d->phase_offset_monitor_period) + *state = DPLL_FEATURE_STATE_ENABLE; + else + *state = DPLL_FEATURE_STATE_DISABLE; + mutex_unlock(&pf->dplls.lock); + + return 0; +} + /** * ice_dpll_pin_state_set - set pin's state on dpll * @pin: pointer to a pin @@ -1757,6 +1820,8 @@ ice_dpll_phase_offset_get(const struct dpll_pin *pin, void *pin_priv, if (d->active_input == pin || (p->input && d->active_input == p->input->pin)) *phase_offset = d->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR; + else if (d->phase_offset_monitor_period) + *phase_offset = p->phase_offset * ICE_DPLL_PHASE_OFFSET_FACTOR; else *phase_offset = 0; mutex_unlock(&pf->dplls.lock); @@ -2216,6 +2281,13 @@ static const struct dpll_device_ops ice_dpll_ops = { .mode_get = ice_dpll_mode_get, }; +static const struct dpll_device_ops ice_dpll_pom_ops = { + .lock_status_get = ice_dpll_lock_status_get, + .mode_get = ice_dpll_mode_get, + .phase_offset_monitor_set = ice_dpll_phase_offset_monitor_set, + .phase_offset_monitor_get = ice_dpll_phase_offset_monitor_get, +}; + /** * ice_generate_clock_id - generates unique clock_id for registering dpll. * @pf: board private structure @@ -2260,6 +2332,110 @@ static void ice_dpll_notify_changes(struct ice_dpll *d) } } +/** + * ice_dpll_is_pps_phase_monitor - check if dpll capable of phase offset monitor + * @pf: pf private structure + * + * Check if firmware is capable of supporting admin command to provide + * phase offset monitoring on all the input pins on PPS dpll. + * + * Returns: + * * true - PPS dpll phase offset monitoring is supported + * * false - PPS dpll phase offset monitoring is not supported + */ +static bool ice_dpll_is_pps_phase_monitor(struct ice_pf *pf) +{ + struct ice_cgu_input_measure meas[ICE_DPLL_INPUT_REF_NUM]; + int ret = ice_aq_get_cgu_input_pin_measure(&pf->hw, DPLL_TYPE_PPS, meas, + ARRAY_SIZE(meas)); + + if (ret && pf->hw.adminq.sq_last_status == ICE_AQ_RC_ESRCH) + return false; + + return true; +} + +/** + * ice_dpll_pins_notify_mask - notify dpll subsystem about bulk pin changes + * @pins: array of ice_dpll_pin pointers registered within dpll subsystem + * @pin_num: number of pins + * @phase_offset_ntf_mask: bitmask of pin indexes to notify + * + * Iterate over array of pins and call dpll subsystem pin notify if + * corresponding pin index within bitmask is set. + * + * Context: Must be called while pf->dplls.lock is released. + */ +static void ice_dpll_pins_notify_mask(struct ice_dpll_pin *pins, + u8 pin_num, + u32 phase_offset_ntf_mask) +{ + int i = 0; + + for (i = 0; i < pin_num; i++) + if (phase_offset_ntf_mask & (1 << i)) + dpll_pin_change_ntf(pins[i].pin); +} + +/** + * ice_dpll_pps_update_phase_offsets - update phase offset measurements + * @pf: pf private structure + * @phase_offset_pins_updated: returns mask of updated input pin indexes + * + * Read phase offset measurements for PPS dpll device and store values in + * input pins array. On success phase_offset_pins_updated - fills bitmask of + * updated input pin indexes, pins shall be notified. + * + * Context: Shall be called with pf->dplls.lock being locked. + * Returns: + * * 0 - success or no data available + * * negative - AQ failure + */ +static int ice_dpll_pps_update_phase_offsets(struct ice_pf *pf, + u32 *phase_offset_pins_updated) +{ + struct ice_cgu_input_measure meas[ICE_DPLL_INPUT_REF_NUM]; + struct ice_dpll_pin *p; + s64 phase_offset, tmp; + int i, j, ret; + + *phase_offset_pins_updated = 0; + ret = ice_aq_get_cgu_input_pin_measure(&pf->hw, DPLL_TYPE_PPS, meas, + ARRAY_SIZE(meas)); + if (ret && pf->hw.adminq.sq_last_status == ICE_AQ_RC_EAGAIN) { + return 0; + } else if (ret) { + dev_err(ice_pf_to_dev(pf), + "failed to get input pin measurements dpll=%d, ret=%d %s\n", + DPLL_TYPE_PPS, ret, + ice_aq_str(pf->hw.adminq.sq_last_status)); + return ret; + } + for (i = 0; i < pf->dplls.num_inputs; i++) { + p = &pf->dplls.inputs[i]; + phase_offset = 0; + for (j = 0; j < ICE_CGU_INPUT_PHASE_OFFSET_BYTES; j++) { + tmp = meas[i].phase_offset[j]; +#ifdef __LITTLE_ENDIAN + phase_offset += tmp << 8 * j; +#else + phase_offset += tmp << 8 * + (ICE_CGU_INPUT_PHASE_OFFSET_BYTES - 1 - j); +#endif + } + phase_offset = sign_extend64(phase_offset, 47); + if (p->phase_offset != phase_offset) { + dev_dbg(ice_pf_to_dev(pf), + "phase offset changed for pin:%d old:%llx, new:%llx\n", + p->idx, p->phase_offset, phase_offset); + p->phase_offset = phase_offset; + *phase_offset_pins_updated |= (1 << i); + } + } + + return 0; +} + /** * ice_dpll_update_state - update dpll state * @pf: pf private structure @@ -2346,14 +2522,19 @@ static void ice_dpll_periodic_work(struct kthread_work *work) struct ice_pf *pf = container_of(d, struct ice_pf, dplls); struct ice_dpll *de = &pf->dplls.eec; struct ice_dpll *dp = &pf->dplls.pps; + u32 phase_offset_ntf = 0; int ret = 0; if (ice_is_reset_in_progress(pf->state)) goto resched; mutex_lock(&pf->dplls.lock); + d->periodic_counter++; ret = ice_dpll_update_state(pf, de, false); if (!ret) ret = ice_dpll_update_state(pf, dp, false); + if (!ret && dp->phase_offset_monitor_period && + d->periodic_counter % dp->phase_offset_monitor_period == 0) + ret = ice_dpll_pps_update_phase_offsets(pf, &phase_offset_ntf); if (ret) { d->cgu_state_acq_err_num++; /* stop rescheduling this worker */ @@ -2368,6 +2549,9 @@ static void ice_dpll_periodic_work(struct kthread_work *work) mutex_unlock(&pf->dplls.lock); ice_dpll_notify_changes(de); ice_dpll_notify_changes(dp); + if (phase_offset_ntf) + ice_dpll_pins_notify_mask(d->inputs, d->num_inputs, + phase_offset_ntf); resched: /* Run twice a second or reschedule if update failed */ @@ -2782,7 +2966,7 @@ static void ice_dpll_deinit_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu) { if (cgu) - dpll_device_unregister(d->dpll, &ice_dpll_ops, d); + dpll_device_unregister(d->dpll, d->ops, d); dpll_device_put(d->dpll); } @@ -2816,12 +3000,17 @@ ice_dpll_init_dpll(struct ice_pf *pf, struct ice_dpll *d, bool cgu, } d->pf = pf; if (cgu) { + const struct dpll_device_ops *ops = &ice_dpll_ops; + + if (type == DPLL_TYPE_PPS && ice_dpll_is_pps_phase_monitor(pf)) + ops = &ice_dpll_pom_ops; ice_dpll_update_state(pf, d, true); - ret = dpll_device_register(d->dpll, type, &ice_dpll_ops, d); + ret = dpll_device_register(d->dpll, type, ops, d); if (ret) { dpll_device_put(d->dpll); return ret; } + d->ops = ops; } return 0; diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.h b/drivers/net/ethernet/intel/ice/ice_dpll.h index 10cd12d709728..a5a5b61c51152 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.h +++ b/drivers/net/ethernet/intel/ice/ice_dpll.h @@ -31,6 +31,7 @@ enum ice_dpll_pin_sw { * @prop: pin properties * @freq: current frequency of a pin * @phase_adjust: current phase adjust value + * @phase_offset: monitored phase offset value */ struct ice_dpll_pin { struct dpll_pin *pin; @@ -46,6 +47,7 @@ struct ice_dpll_pin { struct ice_dpll_pin *input; struct ice_dpll_pin *output; enum dpll_pin_direction direction; + s64 phase_offset; u8 status; bool active; bool hidden; @@ -64,8 +66,10 @@ struct ice_dpll_pin { * @input_prio: priorities of each input * @dpll_state: current dpll sync state * @prev_dpll_state: last dpll sync state + * @phase_offset_monitor_period: period for phase offset monitor read frequency * @active_input: pointer to active input pin * @prev_input: pointer to previous active input pin + * @ops: holds the registered ops */ struct ice_dpll { struct dpll_device *dpll; @@ -81,8 +85,10 @@ struct ice_dpll { enum dpll_lock_status dpll_state; enum dpll_lock_status prev_dpll_state; enum dpll_mode mode; + u32 phase_offset_monitor_period; struct dpll_pin *active_input; struct dpll_pin *prev_input; + const struct dpll_device_ops *ops; }; /** ice_dplls - store info required for CCU (clock controlling unit) @@ -101,6 +107,7 @@ struct ice_dpll { * @clock_id: clock_id of dplls * @input_phase_adj_max: max phase adjust value for an input pins * @output_phase_adj_max: max phase adjust value for an output pins + * @periodic_counter: counter of periodic work executions */ struct ice_dplls { struct kthread_worker *kworker; @@ -121,6 +128,7 @@ struct ice_dplls { u64 clock_id; s32 input_phase_adj_max; s32 output_phase_adj_max; + u32 periodic_counter; bool generic; }; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 7a4b302d356b1..7959a65c0903b 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -7936,6 +7936,10 @@ const char *ice_aq_str(enum ice_aq_err aq_err) return "ICE_AQ_RC_EPERM"; case ICE_AQ_RC_ENOENT: return "ICE_AQ_RC_ENOENT"; + case ICE_AQ_RC_ESRCH: + return "ICE_AQ_RC_ESRCH"; + case ICE_AQ_RC_EAGAIN: + return "ICE_AQ_RC_EAGAIN"; case ICE_AQ_RC_ENOMEM: return "ICE_AQ_RC_ENOMEM"; case ICE_AQ_RC_EBUSY: -- 2.51.0 From 1f59e30403a747eb3a4e2d504018b3c4bcc3e54a Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:40:41 +0100 Subject: [PATCH 05/16] net: stmmac: rk: add get_interfaces() implementation RK platforms support RGMII and/or RMII depending on the SoC. Detect whether support for a SoC exists by whether the interface specific set_to functions have been populated, and set the appropriate bits in phylink's bitmap of interfaces. This assumes all dwmac interfaces on a SoC have identical support, but it should be noted that this is not true for RK3528 which only supports RGMII on GMAC1. However, the existing code structure permits RGMII to be configured on GMAC0 without complaint, so preserve this behaviour even though it is incorrect to avoid functional change. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk2j-004CF6-Mf@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 700858ff6f7c3..8006424ab0275 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -1864,6 +1864,18 @@ static void rk_gmac_powerdown(struct rk_priv_data *gmac) gmac_clk_enable(gmac, false); } +static void rk_get_interfaces(struct stmmac_priv *priv, void *bsp_priv, + unsigned long *interfaces) +{ + struct rk_priv_data *rk = bsp_priv; + + if (rk->ops->set_to_rgmii) + phy_interface_set_rgmii(interfaces); + + if (rk->ops->set_to_rmii) + __set_bit(PHY_INTERFACE_MODE_RMII, interfaces); +} + static int rk_set_clk_tx_rate(void *bsp_priv_, struct clk *clk_tx_i, phy_interface_t interface, int speed) { @@ -1919,6 +1931,7 @@ static int rk_gmac_probe(struct platform_device *pdev) plat_dat->tx_fifo_size = 2048; } + plat_dat->get_interfaces = rk_get_interfaces; plat_dat->set_clk_tx_rate = rk_set_clk_tx_rate; plat_dat->bsp_priv = rk_gmac_setup(pdev, plat_dat, data); -- 2.51.0 From e6e9e837d312ee872892d9207c58763f0838a36c Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:40:46 +0100 Subject: [PATCH 06/16] net: stmmac: rk: simplify set_*_speed() Rather than having lots of regmap_write()s to the same register but with different values depending on the speed, reorganise the functions to use a local variable for the value, and then have one regmap_write() call to write it to the register. This reduces the amount of code and is a step towards further reducing the code size. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk2o-004CFH-Q4@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 303 ++++++++++-------- 1 file changed, 161 insertions(+), 142 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 8006424ab0275..7a1a9f54748db 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -264,35 +264,37 @@ static void rk3128_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, - RK3128_GMAC_CLK_2_5M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, - RK3128_GMAC_CLK_25M); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, - RK3128_GMAC_CLK_125M); - else + if (speed == 10) { + con1 = RK3128_GMAC_CLK_2_5M; + } else if (speed == 100) { + con1 = RK3128_GMAC_CLK_25M; + } else if (speed == 1000) { + con1 = RK3128_GMAC_CLK_125M; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, con1); } static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; if (speed == 10) { - regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, - RK3128_GMAC_RMII_CLK_2_5M | - RK3128_GMAC_SPEED_10M); + con1 = RK3128_GMAC_RMII_CLK_2_5M | RK3128_GMAC_SPEED_10M; } else if (speed == 100) { - regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, - RK3128_GMAC_RMII_CLK_25M | - RK3128_GMAC_SPEED_100M); + con1 = RK3128_GMAC_RMII_CLK_25M | RK3128_GMAC_SPEED_100M; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, con1); } static const struct rk_gmac_ops rk3128_ops = { @@ -361,34 +363,37 @@ static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, - RK3228_GMAC_CLK_2_5M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, - RK3228_GMAC_CLK_25M); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, - RK3228_GMAC_CLK_125M); - else + if (speed == 10) { + con1 = RK3228_GMAC_CLK_2_5M; + } else if (speed == 100) { + con1 = RK3228_GMAC_CLK_25M; + } else if (speed == 1000) { + con1 = RK3228_GMAC_CLK_125M; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, con1); } static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, - RK3228_GMAC_RMII_CLK_2_5M | - RK3228_GMAC_SPEED_10M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, - RK3228_GMAC_RMII_CLK_25M | - RK3228_GMAC_SPEED_100M); - else + if (speed == 10) { + con1 = RK3228_GMAC_RMII_CLK_2_5M | RK3228_GMAC_SPEED_10M; + } else if (speed == 100) { + con1 = RK3228_GMAC_RMII_CLK_25M | RK3228_GMAC_SPEED_100M; + } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, con1); } static void rk3228_integrated_phy_powerup(struct rk_priv_data *priv) @@ -457,35 +462,37 @@ static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, - RK3288_GMAC_CLK_2_5M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, - RK3288_GMAC_CLK_25M); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, - RK3288_GMAC_CLK_125M); - else + if (speed == 10) { + con1 = RK3288_GMAC_CLK_2_5M; + } else if (speed == 100) { + con1 = RK3288_GMAC_CLK_25M; + } else if (speed == 1000) { + con1 = RK3288_GMAC_CLK_125M; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, con1); } static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; if (speed == 10) { - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, - RK3288_GMAC_RMII_CLK_2_5M | - RK3288_GMAC_SPEED_10M); + con1 = RK3288_GMAC_RMII_CLK_2_5M | RK3288_GMAC_SPEED_10M; } else if (speed == 100) { - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, - RK3288_GMAC_RMII_CLK_25M | - RK3288_GMAC_SPEED_100M); + con1 = RK3288_GMAC_RMII_CLK_25M | RK3288_GMAC_SPEED_100M; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, con1); } static const struct rk_gmac_ops rk3288_ops = { @@ -514,16 +521,18 @@ static void rk3308_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3308_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con0; if (speed == 10) { - regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0, - RK3308_GMAC_SPEED_10M); + con0 = RK3308_GMAC_SPEED_10M; } else if (speed == 100) { - regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0, - RK3308_GMAC_SPEED_100M); + con0 = RK3308_GMAC_SPEED_100M; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0, con0); } static const struct rk_gmac_ops rk3308_ops = { @@ -593,38 +602,40 @@ static void rk3328_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, - RK3328_GMAC_CLK_2_5M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, - RK3328_GMAC_CLK_25M); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, - RK3328_GMAC_CLK_125M); - else + if (speed == 10) { + con1 = RK3328_GMAC_CLK_2_5M; + } else if (speed == 100) { + con1 = RK3328_GMAC_CLK_25M; + } else if (speed == 1000) { + con1 = RK3328_GMAC_CLK_125M; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, con1); } static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int reg; + unsigned int reg, con; reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 : RK3328_GRF_MAC_CON1; - if (speed == 10) - regmap_write(bsp_priv->grf, reg, - RK3328_GMAC_RMII_CLK_2_5M | - RK3328_GMAC_SPEED_10M); - else if (speed == 100) - regmap_write(bsp_priv->grf, reg, - RK3328_GMAC_RMII_CLK_25M | - RK3328_GMAC_SPEED_100M); - else + if (speed == 10) { + con = RK3328_GMAC_RMII_CLK_2_5M | RK3328_GMAC_SPEED_10M; + } else if (speed == 100) { + con = RK3328_GMAC_RMII_CLK_25M | RK3328_GMAC_SPEED_100M; + } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, reg, con); } static void rk3328_integrated_phy_powerup(struct rk_priv_data *priv) @@ -693,35 +704,37 @@ static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con6; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, - RK3366_GMAC_CLK_2_5M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, - RK3366_GMAC_CLK_25M); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, - RK3366_GMAC_CLK_125M); - else + if (speed == 10) { + con6 = RK3366_GMAC_CLK_2_5M; + } else if (speed == 100) { + con6 = RK3366_GMAC_CLK_25M; + } else if (speed == 1000) { + con6 = RK3366_GMAC_CLK_125M; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, con6); } static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con6; if (speed == 10) { - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, - RK3366_GMAC_RMII_CLK_2_5M | - RK3366_GMAC_SPEED_10M); + con6 = RK3366_GMAC_RMII_CLK_2_5M | RK3366_GMAC_SPEED_10M; } else if (speed == 100) { - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, - RK3366_GMAC_RMII_CLK_25M | - RK3366_GMAC_SPEED_100M); + con6 = RK3366_GMAC_RMII_CLK_25M | RK3366_GMAC_SPEED_100M; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, con6); } static const struct rk_gmac_ops rk3366_ops = { @@ -780,35 +793,37 @@ static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con15; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, - RK3368_GMAC_CLK_2_5M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, - RK3368_GMAC_CLK_25M); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, - RK3368_GMAC_CLK_125M); - else + if (speed == 10) { + con15 = RK3368_GMAC_CLK_2_5M; + } else if (speed == 100) { + con15 = RK3368_GMAC_CLK_25M; + } else if (speed == 1000) { + con15 = RK3368_GMAC_CLK_125M; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, con15); } static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con15; if (speed == 10) { - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, - RK3368_GMAC_RMII_CLK_2_5M | - RK3368_GMAC_SPEED_10M); + con15 = RK3368_GMAC_RMII_CLK_2_5M | RK3368_GMAC_SPEED_10M; } else if (speed == 100) { - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, - RK3368_GMAC_RMII_CLK_25M | - RK3368_GMAC_SPEED_100M); + con15 = RK3368_GMAC_RMII_CLK_25M | RK3368_GMAC_SPEED_100M; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, con15); } static const struct rk_gmac_ops rk3368_ops = { @@ -867,35 +882,37 @@ static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con5; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, - RK3399_GMAC_CLK_2_5M); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, - RK3399_GMAC_CLK_25M); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, - RK3399_GMAC_CLK_125M); - else + if (speed == 10) { + con5 = RK3399_GMAC_CLK_2_5M; + } else if (speed == 100) { + con5 = RK3399_GMAC_CLK_25M; + } else if (speed == 1000) { + con5 = RK3399_GMAC_CLK_125M; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, con5); } static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con5; if (speed == 10) { - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, - RK3399_GMAC_RMII_CLK_2_5M | - RK3399_GMAC_SPEED_10M); + con5 = RK3399_GMAC_RMII_CLK_2_5M | RK3399_GMAC_SPEED_10M; } else if (speed == 100) { - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, - RK3399_GMAC_RMII_CLK_25M | - RK3399_GMAC_SPEED_100M); + con5 = RK3399_GMAC_RMII_CLK_25M | RK3399_GMAC_SPEED_100M; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, con5); } static const struct rk_gmac_ops rk3399_ops = { @@ -968,18 +985,20 @@ static void rk3528_set_to_rmii(struct rk_priv_data *bsp_priv) static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con5; - if (speed == 10) - regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, - RK3528_GMAC1_CLK_RGMII_DIV50); - else if (speed == 100) - regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, - RK3528_GMAC1_CLK_RGMII_DIV5); - else if (speed == 1000) - regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, - RK3528_GMAC1_CLK_RGMII_DIV1); - else + if (speed == 10) { + con5 = RK3528_GMAC1_CLK_RGMII_DIV50; + } else if (speed == 100) { + con5 = RK3528_GMAC1_CLK_RGMII_DIV5; + } else if (speed == 1000) { + con5 = RK3528_GMAC1_CLK_RGMII_DIV1; + } else { dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); + return; + } + + regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, con5); } static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) @@ -987,13 +1006,13 @@ static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) struct device *dev = &bsp_priv->pdev->dev; unsigned int reg, val; - if (speed == 10) + if (speed == 10) { val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV20 : RK3528_GMAC0_CLK_RMII_DIV20; - else if (speed == 100) + } else if (speed == 100) { val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV2 : RK3528_GMAC0_CLK_RMII_DIV2; - else { + } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); return; } @@ -1430,18 +1449,18 @@ static void rv1108_set_to_rmii(struct rk_priv_data *bsp_priv) static void rv1108_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; + unsigned int con0; if (speed == 10) { - regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0, - RV1108_GMAC_RMII_CLK_2_5M | - RV1108_GMAC_SPEED_10M); + con0 = RV1108_GMAC_RMII_CLK_2_5M | RV1108_GMAC_SPEED_10M; } else if (speed == 100) { - regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0, - RV1108_GMAC_RMII_CLK_25M | - RV1108_GMAC_SPEED_100M); + con0 = RV1108_GMAC_RMII_CLK_25M | RV1108_GMAC_SPEED_100M; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0, con0); } static const struct rk_gmac_ops rv1108_ops = { -- 2.51.0 From 3de607d13b6bd7fd85759d085b6996112bf6cfe2 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:40:51 +0100 Subject: [PATCH 07/16] net: stmmac: rk: add struct for programming register based speeds There is a common pattern in the driver where many SoCs need to write a single register with a value dependent on the interface mode and speed. Rather than having a lot of repeated code, add some common functions and a struct to contain the values to be written to a register to select the RGMII and RMII speeds. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk2t-004CFN-Td@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 432 +++++++++--------- 1 file changed, 204 insertions(+), 228 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 7a1a9f54748db..7b5e989bb77f1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -24,6 +24,15 @@ #include "stmmac_platform.h" struct rk_priv_data; + +struct rk_reg_speed_data { + unsigned int rgmii_10; + unsigned int rgmii_100; + unsigned int rgmii_1000; + unsigned int rmii_10; + unsigned int rmii_100; +}; + struct rk_gmac_ops { void (*set_to_rgmii)(struct rk_priv_data *bsp_priv, int tx_delay, int rx_delay); @@ -83,6 +92,67 @@ struct rk_priv_data { struct regmap *php_grf; }; +static int rk_set_reg_speed(struct rk_priv_data *bsp_priv, + const struct rk_reg_speed_data *rsd, + unsigned int reg, phy_interface_t interface, + int speed) +{ + unsigned int val; + + if (phy_interface_mode_is_rgmii(interface)) { + if (speed == SPEED_10) { + val = rsd->rgmii_10; + } else if (speed == SPEED_100) { + val = rsd->rgmii_100; + } else if (speed == SPEED_1000) { + val = rsd->rgmii_1000; + } else { + /* Phylink will not allow inappropriate speeds for + * interface modes, so this should never happen. + */ + return -EINVAL; + } + } else if (interface == PHY_INTERFACE_MODE_RMII) { + if (speed == SPEED_10) { + val = rsd->rmii_10; + } else if (speed == SPEED_100) { + val = rsd->rmii_100; + } else { + /* Phylink will not allow inappropriate speeds for + * interface modes, so this should never happen. + */ + return -EINVAL; + } + } else { + /* This should never happen, as .get_interfaces() limits + * the interface modes that are supported to RGMII and/or + * RMII. + */ + return -EINVAL; + } + + regmap_write(bsp_priv->grf, reg, val); + + return 0; + +} + +static int rk_set_reg_speed_rgmii(struct rk_priv_data *bsp_priv, + const struct rk_reg_speed_data *rsd, + unsigned int reg, int speed) +{ + return rk_set_reg_speed(bsp_priv, rsd, reg, PHY_INTERFACE_MODE_RGMII, + speed); +} + +static int rk_set_reg_speed_rmii(struct rk_priv_data *bsp_priv, + const struct rk_reg_speed_data *rsd, + unsigned int reg, int speed) +{ + return rk_set_reg_speed(bsp_priv, rsd, reg, PHY_INTERFACE_MODE_RMII, + speed); +} + #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) @@ -261,40 +331,30 @@ static void rk3128_set_to_rmii(struct rk_priv_data *bsp_priv) RK3128_GMAC_PHY_INTF_SEL_RMII | RK3128_GMAC_RMII_MODE); } +static const struct rk_reg_speed_data rk3128_reg_speed_data = { + .rgmii_10 = RK3128_GMAC_CLK_2_5M, + .rgmii_100 = RK3128_GMAC_CLK_25M, + .rgmii_1000 = RK3128_GMAC_CLK_125M, + .rmii_10 = RK3128_GMAC_RMII_CLK_2_5M | RK3128_GMAC_SPEED_10M, + .rmii_100 = RK3128_GMAC_RMII_CLK_25M | RK3128_GMAC_SPEED_100M, +}; + static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con1; - if (speed == 10) { - con1 = RK3128_GMAC_CLK_2_5M; - } else if (speed == 100) { - con1 = RK3128_GMAC_CLK_25M; - } else if (speed == 1000) { - con1 = RK3128_GMAC_CLK_125M; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3128_reg_speed_data, + RK3128_GRF_MAC_CON1, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, con1); } static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con1; - if (speed == 10) { - con1 = RK3128_GMAC_RMII_CLK_2_5M | RK3128_GMAC_SPEED_10M; - } else if (speed == 100) { - con1 = RK3128_GMAC_RMII_CLK_25M | RK3128_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3128_reg_speed_data, + RK3128_GRF_MAC_CON1, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, con1); } static const struct rk_gmac_ops rk3128_ops = { @@ -360,40 +420,30 @@ static void rk3228_set_to_rmii(struct rk_priv_data *bsp_priv) regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, GRF_BIT(11)); } +static const struct rk_reg_speed_data rk3228_reg_speed_data = { + .rgmii_10 = RK3228_GMAC_CLK_2_5M, + .rgmii_100 = RK3228_GMAC_CLK_25M, + .rgmii_1000 = RK3228_GMAC_CLK_125M, + .rmii_10 = RK3228_GMAC_RMII_CLK_2_5M | RK3228_GMAC_SPEED_10M, + .rmii_100 = RK3228_GMAC_RMII_CLK_25M | RK3228_GMAC_SPEED_100M, +}; + static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con1; - if (speed == 10) { - con1 = RK3228_GMAC_CLK_2_5M; - } else if (speed == 100) { - con1 = RK3228_GMAC_CLK_25M; - } else if (speed == 1000) { - con1 = RK3228_GMAC_CLK_125M; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3228_reg_speed_data, + RK3228_GRF_MAC_CON1, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, con1); } static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con1; - if (speed == 10) { - con1 = RK3228_GMAC_RMII_CLK_2_5M | RK3228_GMAC_SPEED_10M; - } else if (speed == 100) { - con1 = RK3228_GMAC_RMII_CLK_25M | RK3228_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3228_reg_speed_data, + RK3228_GRF_MAC_CON1, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, con1); } static void rk3228_integrated_phy_powerup(struct rk_priv_data *priv) @@ -459,40 +509,30 @@ static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv) RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE); } +static const struct rk_reg_speed_data rk3288_reg_speed_data = { + .rgmii_10 = RK3288_GMAC_CLK_2_5M, + .rgmii_100 = RK3288_GMAC_CLK_25M, + .rgmii_1000 = RK3288_GMAC_CLK_125M, + .rmii_10 = RK3288_GMAC_RMII_CLK_2_5M | RK3288_GMAC_SPEED_10M, + .rmii_100 = RK3288_GMAC_RMII_CLK_25M | RK3288_GMAC_SPEED_100M, +}; + static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con1; - if (speed == 10) { - con1 = RK3288_GMAC_CLK_2_5M; - } else if (speed == 100) { - con1 = RK3288_GMAC_CLK_25M; - } else if (speed == 1000) { - con1 = RK3288_GMAC_CLK_125M; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3288_reg_speed_data, + RK3288_GRF_SOC_CON1, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, con1); } static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con1; - if (speed == 10) { - con1 = RK3288_GMAC_RMII_CLK_2_5M | RK3288_GMAC_SPEED_10M; - } else if (speed == 100) { - con1 = RK3288_GMAC_RMII_CLK_25M | RK3288_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3288_reg_speed_data, + RK3288_GRF_SOC_CON1, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, con1); } static const struct rk_gmac_ops rk3288_ops = { @@ -518,21 +558,18 @@ static void rk3308_set_to_rmii(struct rk_priv_data *bsp_priv) RK3308_GMAC_PHY_INTF_SEL_RMII); } +static const struct rk_reg_speed_data rk3308_reg_speed_data = { + .rmii_10 = RK3308_GMAC_SPEED_10M, + .rmii_100 = RK3308_GMAC_SPEED_100M, +}; + static void rk3308_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con0; - if (speed == 10) { - con0 = RK3308_GMAC_SPEED_10M; - } else if (speed == 100) { - con0 = RK3308_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3308_reg_speed_data, + RK3308_GRF_MAC_CON0, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3308_GRF_MAC_CON0, con0); } static const struct rk_gmac_ops rk3308_ops = { @@ -599,43 +636,33 @@ static void rk3328_set_to_rmii(struct rk_priv_data *bsp_priv) RK3328_GMAC_RMII_MODE); } +static const struct rk_reg_speed_data rk3328_reg_speed_data = { + .rgmii_10 = RK3328_GMAC_CLK_2_5M, + .rgmii_100 = RK3328_GMAC_CLK_25M, + .rgmii_1000 = RK3328_GMAC_CLK_125M, + .rmii_10 = RK3328_GMAC_RMII_CLK_2_5M | RK3328_GMAC_SPEED_10M, + .rmii_100 = RK3328_GMAC_RMII_CLK_25M | RK3328_GMAC_SPEED_100M, +}; + static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con1; - if (speed == 10) { - con1 = RK3328_GMAC_CLK_2_5M; - } else if (speed == 100) { - con1 = RK3328_GMAC_CLK_25M; - } else if (speed == 1000) { - con1 = RK3328_GMAC_CLK_125M; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3328_reg_speed_data, + RK3328_GRF_MAC_CON1, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, con1); } static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int reg, con; + unsigned int reg; reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 : RK3328_GRF_MAC_CON1; - if (speed == 10) { - con = RK3328_GMAC_RMII_CLK_2_5M | RK3328_GMAC_SPEED_10M; - } else if (speed == 100) { - con = RK3328_GMAC_RMII_CLK_25M | RK3328_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3328_reg_speed_data, reg, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, reg, con); } static void rk3328_integrated_phy_powerup(struct rk_priv_data *priv) @@ -701,40 +728,30 @@ static void rk3366_set_to_rmii(struct rk_priv_data *bsp_priv) RK3366_GMAC_PHY_INTF_SEL_RMII | RK3366_GMAC_RMII_MODE); } +static const struct rk_reg_speed_data rk3366_reg_speed_data = { + .rgmii_10 = RK3366_GMAC_CLK_2_5M, + .rgmii_100 = RK3366_GMAC_CLK_25M, + .rgmii_1000 = RK3366_GMAC_CLK_125M, + .rmii_10 = RK3366_GMAC_RMII_CLK_2_5M | RK3366_GMAC_SPEED_10M, + .rmii_100 = RK3366_GMAC_RMII_CLK_25M | RK3366_GMAC_SPEED_100M, +}; + static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con6; - if (speed == 10) { - con6 = RK3366_GMAC_CLK_2_5M; - } else if (speed == 100) { - con6 = RK3366_GMAC_CLK_25M; - } else if (speed == 1000) { - con6 = RK3366_GMAC_CLK_125M; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3366_reg_speed_data, + RK3366_GRF_SOC_CON6, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, con6); } static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con6; - if (speed == 10) { - con6 = RK3366_GMAC_RMII_CLK_2_5M | RK3366_GMAC_SPEED_10M; - } else if (speed == 100) { - con6 = RK3366_GMAC_RMII_CLK_25M | RK3366_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3366_reg_speed_data, + RK3366_GRF_SOC_CON6, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON6, con6); } static const struct rk_gmac_ops rk3366_ops = { @@ -790,40 +807,30 @@ static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv) RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE); } +static const struct rk_reg_speed_data rk3368_reg_speed_data = { + .rgmii_10 = RK3368_GMAC_CLK_2_5M, + .rgmii_100 = RK3368_GMAC_CLK_25M, + .rgmii_1000 = RK3368_GMAC_CLK_125M, + .rmii_10 = RK3368_GMAC_RMII_CLK_2_5M | RK3368_GMAC_SPEED_10M, + .rmii_100 = RK3368_GMAC_RMII_CLK_25M | RK3368_GMAC_SPEED_100M, +}; + static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con15; - if (speed == 10) { - con15 = RK3368_GMAC_CLK_2_5M; - } else if (speed == 100) { - con15 = RK3368_GMAC_CLK_25M; - } else if (speed == 1000) { - con15 = RK3368_GMAC_CLK_125M; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3368_reg_speed_data, + RK3368_GRF_SOC_CON15, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, con15); } static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con15; - if (speed == 10) { - con15 = RK3368_GMAC_RMII_CLK_2_5M | RK3368_GMAC_SPEED_10M; - } else if (speed == 100) { - con15 = RK3368_GMAC_RMII_CLK_25M | RK3368_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3368_reg_speed_data, + RK3368_GRF_SOC_CON15, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15, con15); } static const struct rk_gmac_ops rk3368_ops = { @@ -879,40 +886,30 @@ static void rk3399_set_to_rmii(struct rk_priv_data *bsp_priv) RK3399_GMAC_PHY_INTF_SEL_RMII | RK3399_GMAC_RMII_MODE); } +static const struct rk_reg_speed_data rk3399_reg_speed_data = { + .rgmii_10 = RK3399_GMAC_CLK_2_5M, + .rgmii_100 = RK3399_GMAC_CLK_25M, + .rgmii_1000 = RK3399_GMAC_CLK_125M, + .rmii_10 = RK3399_GMAC_RMII_CLK_2_5M | RK3399_GMAC_SPEED_10M, + .rmii_100 = RK3399_GMAC_RMII_CLK_25M | RK3399_GMAC_SPEED_100M, +}; + static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con5; - if (speed == 10) { - con5 = RK3399_GMAC_CLK_2_5M; - } else if (speed == 100) { - con5 = RK3399_GMAC_CLK_25M; - } else if (speed == 1000) { - con5 = RK3399_GMAC_CLK_125M; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3399_reg_speed_data, + RK3399_GRF_SOC_CON5, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, con5); } static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con5; - if (speed == 10) { - con5 = RK3399_GMAC_RMII_CLK_2_5M | RK3399_GMAC_SPEED_10M; - } else if (speed == 100) { - con5 = RK3399_GMAC_RMII_CLK_25M | RK3399_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rk3399_reg_speed_data, + RK3399_GRF_SOC_CON5, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON5, con5); } static const struct rk_gmac_ops rk3399_ops = { @@ -982,45 +979,44 @@ static void rk3528_set_to_rmii(struct rk_priv_data *bsp_priv) RK3528_GMAC0_CLK_RMII_DIV2); } +static const struct rk_reg_speed_data rk3528_gmac0_reg_speed_data = { + .rmii_10 = RK3528_GMAC0_CLK_RMII_DIV20, + .rmii_100 = RK3528_GMAC0_CLK_RMII_DIV2, +}; + +static const struct rk_reg_speed_data rk3528_gmac1_reg_speed_data = { + .rgmii_10 = RK3528_GMAC1_CLK_RGMII_DIV50, + .rgmii_100 = RK3528_GMAC1_CLK_RGMII_DIV5, + .rgmii_1000 = RK3528_GMAC1_CLK_RGMII_DIV1, + .rmii_10 = RK3528_GMAC1_CLK_RMII_DIV20, + .rmii_100 = RK3528_GMAC1_CLK_RMII_DIV2, +}; + static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con5; - if (speed == 10) { - con5 = RK3528_GMAC1_CLK_RGMII_DIV50; - } else if (speed == 100) { - con5 = RK3528_GMAC1_CLK_RGMII_DIV5; - } else if (speed == 1000) { - con5 = RK3528_GMAC1_CLK_RGMII_DIV1; - } else { + if (rk_set_reg_speed_rgmii(bsp_priv, &rk3528_gmac1_reg_speed_data, + RK3528_VPU_GRF_GMAC_CON5, speed)) dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RK3528_VPU_GRF_GMAC_CON5, con5); } static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int reg, val; + const struct rk_reg_speed_data *rsd; + unsigned int reg; - if (speed == 10) { - val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV20 : - RK3528_GMAC0_CLK_RMII_DIV20; - } else if (speed == 100) { - val = bsp_priv->id == 1 ? RK3528_GMAC1_CLK_RMII_DIV2 : - RK3528_GMAC0_CLK_RMII_DIV2; + if (bsp_priv->id == 1) { + rsd = &rk3528_gmac1_reg_speed_data; + reg = RK3528_VPU_GRF_GMAC_CON5; } else { - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; + rsd = &rk3528_gmac0_reg_speed_data; + reg = RK3528_VO_GRF_GMAC_CON; } - reg = bsp_priv->id == 1 ? RK3528_VPU_GRF_GMAC_CON5 : - RK3528_VO_GRF_GMAC_CON; - - regmap_write(bsp_priv->grf, reg, val); + if (rk_set_reg_speed_rmii(bsp_priv, rsd, reg, speed)) + dev_err(dev, "unknown speed value for RMII! speed=%d", speed); } static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv, @@ -1224,42 +1220,25 @@ static void rk3576_set_to_rmii(struct rk_priv_data *bsp_priv) regmap_write(bsp_priv->grf, offset_con, RK3576_GMAC_RMII_MODE); } +static const struct rk_reg_speed_data rk3578_reg_speed_data = { + .rgmii_10 = RK3576_GMAC_CLK_RGMII_DIV50, + .rgmii_100 = RK3576_GMAC_CLK_RGMII_DIV5, + .rgmii_1000 = RK3576_GMAC_CLK_RGMII_DIV1, + .rmii_10 = RK3576_GMAC_CLK_RMII_DIV20, + .rmii_100 = RK3576_GMAC_CLK_RMII_DIV2, +}; + static void rk3576_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int val = 0, offset_con; - - switch (speed) { - case 10: - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) - val = RK3576_GMAC_CLK_RMII_DIV20; - else - val = RK3576_GMAC_CLK_RGMII_DIV50; - break; - case 100: - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) - val = RK3576_GMAC_CLK_RMII_DIV2; - else - val = RK3576_GMAC_CLK_RGMII_DIV5; - break; - case 1000: - if (bsp_priv->phy_iface != PHY_INTERFACE_MODE_RMII) - val = RK3576_GMAC_CLK_RGMII_DIV1; - else - goto err; - break; - default: - goto err; - } + unsigned int offset_con; offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 : RK3576_GRF_GMAC_CON0; - regmap_write(bsp_priv->grf, offset_con, val); - - return; -err: - dev_err(dev, "unknown speed value for GMAC speed=%d", speed); + if (rk_set_reg_speed(bsp_priv, &rk3578_reg_speed_data, offset_con, + bsp_priv->phy_iface, speed)) + dev_err(dev, "unknown speed value for GMAC speed=%d", speed); } static void rk3576_set_clock_selection(struct rk_priv_data *bsp_priv, bool input, @@ -1446,21 +1425,18 @@ static void rv1108_set_to_rmii(struct rk_priv_data *bsp_priv) RV1108_GMAC_PHY_INTF_SEL_RMII); } +static const struct rk_reg_speed_data rv1108_reg_speed_data = { + .rmii_10 = RV1108_GMAC_RMII_CLK_2_5M | RV1108_GMAC_SPEED_10M, + .rmii_100 = RV1108_GMAC_RMII_CLK_25M | RV1108_GMAC_SPEED_100M, +}; + static void rv1108_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct device *dev = &bsp_priv->pdev->dev; - unsigned int con0; - if (speed == 10) { - con0 = RV1108_GMAC_RMII_CLK_2_5M | RV1108_GMAC_SPEED_10M; - } else if (speed == 100) { - con0 = RV1108_GMAC_RMII_CLK_25M | RV1108_GMAC_SPEED_100M; - } else { + if (rk_set_reg_speed_rmii(bsp_priv, &rv1108_reg_speed_data, + RV1108_GRF_GMAC_CON0, speed)) dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; - } - - regmap_write(bsp_priv->grf, RV1108_GRF_GMAC_CON0, con0); } static const struct rk_gmac_ops rv1108_ops = { -- 2.51.0 From 29f0aca1391498c73cd8bedc28c6e7e40f204995 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:40:57 +0100 Subject: [PATCH 08/16] net: stmmac: rk: combine rv1126 set_*_speed() methods Just like rk3568, there is no need to have separate RGMII and RMII methods to set clk_mac_speed() as rgmii_clock() can be used to return the clock rate for both RGMII and RMII interface modes. Combine these two methods. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk2z-004CFT-0e@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 33 +++---------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 7b5e989bb77f1..c7b64f0a2931c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -1496,7 +1496,7 @@ static void rv1126_set_to_rmii(struct rk_priv_data *bsp_priv) RV1126_GMAC_PHY_INTF_SEL_RMII); } -static void rv1126_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static void rv1126_set_clk_mac_speed(struct rk_priv_data *bsp_priv, int speed) { struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; struct device *dev = &bsp_priv->pdev->dev; @@ -1505,32 +1505,7 @@ static void rv1126_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) rate = rgmii_clock(speed); if (rate < 0) { - dev_err(dev, "unknown speed value for RGMII speed=%d", speed); - return; - } - - ret = clk_set_rate(clk_mac_speed, rate); - if (ret) - dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n", - __func__, rate, ret); -} - -static void rv1126_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; - struct device *dev = &bsp_priv->pdev->dev; - unsigned long rate; - int ret; - - switch (speed) { - case 10: - rate = 2500000; - break; - case 100: - rate = 25000000; - break; - default: - dev_err(dev, "unknown speed value for RGMII speed=%d", speed); + dev_err(dev, "unknown speed value for GMAC speed=%d", speed); return; } @@ -1543,8 +1518,8 @@ static void rv1126_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) static const struct rk_gmac_ops rv1126_ops = { .set_to_rgmii = rv1126_set_to_rgmii, .set_to_rmii = rv1126_set_to_rmii, - .set_rgmii_speed = rv1126_set_rgmii_speed, - .set_rmii_speed = rv1126_set_rmii_speed, + .set_rgmii_speed = rv1126_set_clk_mac_speed, + .set_rmii_speed = rv1126_set_clk_mac_speed, }; static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) -- 2.51.0 From d8d6096f816117a5732ff96550b59be7ea9f4683 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:41:02 +0100 Subject: [PATCH 09/16] net: stmmac: rk: combine clk_mac_speed rate setting functions rk3568_set_gmac_speed() and rv1126_set_clk_mac_speed() are now identical. Combine these so we have a single copy of this code. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk34-004CFZ-3y@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 65 +++++++------------ 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index c7b64f0a2931c..eeef11b605666 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -153,6 +153,25 @@ static int rk_set_reg_speed_rmii(struct rk_priv_data *bsp_priv, speed); } +static void rk_set_clk_mac_speed(struct rk_priv_data *bsp_priv, int speed) +{ + struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; + struct device *dev = &bsp_priv->pdev->dev; + long rate; + int ret; + + rate = rgmii_clock(speed); + if (rate < 0) { + dev_err(dev, "unknown speed value for GMAC speed=%d", speed); + return; + } + + ret = clk_set_rate(clk_mac_speed, rate); + if (ret) + dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n", + __func__, rate, ret); +} + #define HIWORD_UPDATE(val, mask, shift) \ ((val) << (shift) | (mask) << ((shift) + 16)) @@ -1113,30 +1132,11 @@ static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv) regmap_write(bsp_priv->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII); } -static void rk3568_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; - struct device *dev = &bsp_priv->pdev->dev; - long rate; - int ret; - - rate = rgmii_clock(speed); - if (rate < 0) { - dev_err(dev, "unknown speed value for GMAC speed=%d", speed); - return; - } - - ret = clk_set_rate(clk_mac_speed, rate); - if (ret) - dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n", - __func__, rate, ret); -} - static const struct rk_gmac_ops rk3568_ops = { .set_to_rgmii = rk3568_set_to_rgmii, .set_to_rmii = rk3568_set_to_rmii, - .set_rgmii_speed = rk3568_set_gmac_speed, - .set_rmii_speed = rk3568_set_gmac_speed, + .set_rgmii_speed = rk_set_clk_mac_speed, + .set_rmii_speed = rk_set_clk_mac_speed, .regs_valid = true, .regs = { 0xfe2a0000, /* gmac0 */ @@ -1496,30 +1496,11 @@ static void rv1126_set_to_rmii(struct rk_priv_data *bsp_priv) RV1126_GMAC_PHY_INTF_SEL_RMII); } -static void rv1126_set_clk_mac_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; - struct device *dev = &bsp_priv->pdev->dev; - long rate; - int ret; - - rate = rgmii_clock(speed); - if (rate < 0) { - dev_err(dev, "unknown speed value for GMAC speed=%d", speed); - return; - } - - ret = clk_set_rate(clk_mac_speed, rate); - if (ret) - dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n", - __func__, rate, ret); -} - static const struct rk_gmac_ops rv1126_ops = { .set_to_rgmii = rv1126_set_to_rgmii, .set_to_rmii = rv1126_set_to_rmii, - .set_rgmii_speed = rv1126_set_clk_mac_speed, - .set_rmii_speed = rv1126_set_clk_mac_speed, + .set_rgmii_speed = rk_set_clk_mac_speed, + .set_rmii_speed = rk_set_clk_mac_speed, }; static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) -- 2.51.0 From 3930c2cca657bfd03c229a272f21f9b0f2685fad Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:41:07 +0100 Subject: [PATCH 10/16] net: stmmac: rk: combine .set_*_speed() methods As a result of the previous patches, many of the .set_rgmii_speed() and .set_rmii_speed() implementations are identical apart from the interface mode. Add a new .set_speed() function which takes the interface mode in addition to the speed, and use it to combine the separate implementations, calling the common rk_set_reg_speed() function. Also convert rk_set_clk_mac_speed() to be called by this new method pointer, rather than having these implementations called from both .set_*_speed() methods. Remove all the error messages from the .set_speed() methods, as these return an error code which is propagated up to stmmac_mac_link_up() which will print the error. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk39-004CFf-7a@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 274 +++++------------- 1 file changed, 79 insertions(+), 195 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index eeef11b605666..8ad6b3b0e2823 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -39,6 +39,8 @@ struct rk_gmac_ops { void (*set_to_rmii)(struct rk_priv_data *bsp_priv); void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); + int (*set_speed)(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed); void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input, bool enable); void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv); @@ -137,39 +139,17 @@ static int rk_set_reg_speed(struct rk_priv_data *bsp_priv, } -static int rk_set_reg_speed_rgmii(struct rk_priv_data *bsp_priv, - const struct rk_reg_speed_data *rsd, - unsigned int reg, int speed) -{ - return rk_set_reg_speed(bsp_priv, rsd, reg, PHY_INTERFACE_MODE_RGMII, - speed); -} - -static int rk_set_reg_speed_rmii(struct rk_priv_data *bsp_priv, - const struct rk_reg_speed_data *rsd, - unsigned int reg, int speed) -{ - return rk_set_reg_speed(bsp_priv, rsd, reg, PHY_INTERFACE_MODE_RMII, - speed); -} - -static void rk_set_clk_mac_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk_set_clk_mac_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; - struct device *dev = &bsp_priv->pdev->dev; long rate; - int ret; rate = rgmii_clock(speed); - if (rate < 0) { - dev_err(dev, "unknown speed value for GMAC speed=%d", speed); - return; - } + if (rate < 0) + return rate; - ret = clk_set_rate(clk_mac_speed, rate); - if (ret) - dev_err(dev, "%s: set clk_mac_speed rate %ld failed %d\n", - __func__, rate, ret); + return clk_set_rate(clk_mac_speed, rate); } #define HIWORD_UPDATE(val, mask, shift) \ @@ -358,29 +338,17 @@ static const struct rk_reg_speed_data rk3128_reg_speed_data = { .rmii_100 = RK3128_GMAC_RMII_CLK_25M | RK3128_GMAC_SPEED_100M, }; -static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3128_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3128_reg_speed_data, - RK3128_GRF_MAC_CON1, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rk3128_reg_speed_data, - RK3128_GRF_MAC_CON1, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3128_reg_speed_data, + RK3128_GRF_MAC_CON1, interface, speed); } static const struct rk_gmac_ops rk3128_ops = { .set_to_rgmii = rk3128_set_to_rgmii, .set_to_rmii = rk3128_set_to_rmii, - .set_rgmii_speed = rk3128_set_rgmii_speed, - .set_rmii_speed = rk3128_set_rmii_speed, + .set_speed = rk3128_set_speed, }; #define RK3228_GRF_MAC_CON0 0x0900 @@ -447,22 +415,11 @@ static const struct rk_reg_speed_data rk3228_reg_speed_data = { .rmii_100 = RK3228_GMAC_RMII_CLK_25M | RK3228_GMAC_SPEED_100M, }; -static void rk3228_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3228_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3228_reg_speed_data, - RK3228_GRF_MAC_CON1, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3228_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rk3228_reg_speed_data, - RK3228_GRF_MAC_CON1, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3228_reg_speed_data, + RK3228_GRF_MAC_CON1, interface, speed); } static void rk3228_integrated_phy_powerup(struct rk_priv_data *priv) @@ -476,8 +433,7 @@ static void rk3228_integrated_phy_powerup(struct rk_priv_data *priv) static const struct rk_gmac_ops rk3228_ops = { .set_to_rgmii = rk3228_set_to_rgmii, .set_to_rmii = rk3228_set_to_rmii, - .set_rgmii_speed = rk3228_set_rgmii_speed, - .set_rmii_speed = rk3228_set_rmii_speed, + .set_speed = rk3228_set_speed, .integrated_phy_powerup = rk3228_integrated_phy_powerup, .integrated_phy_powerdown = rk_gmac_integrated_ephy_powerdown, }; @@ -536,29 +492,17 @@ static const struct rk_reg_speed_data rk3288_reg_speed_data = { .rmii_100 = RK3288_GMAC_RMII_CLK_25M | RK3288_GMAC_SPEED_100M, }; -static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3288_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3288_reg_speed_data, - RK3288_GRF_SOC_CON1, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rk3288_reg_speed_data, - RK3288_GRF_SOC_CON1, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3288_reg_speed_data, + RK3288_GRF_SOC_CON1, interface, speed); } static const struct rk_gmac_ops rk3288_ops = { .set_to_rgmii = rk3288_set_to_rgmii, .set_to_rmii = rk3288_set_to_rmii, - .set_rgmii_speed = rk3288_set_rgmii_speed, - .set_rmii_speed = rk3288_set_rmii_speed, + .set_speed = rk3288_set_speed, }; #define RK3308_GRF_MAC_CON0 0x04a0 @@ -582,18 +526,16 @@ static const struct rk_reg_speed_data rk3308_reg_speed_data = { .rmii_100 = RK3308_GMAC_SPEED_100M, }; -static void rk3308_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3308_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rk3308_reg_speed_data, - RK3308_GRF_MAC_CON0, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3308_reg_speed_data, + RK3308_GRF_MAC_CON0, interface, speed); } static const struct rk_gmac_ops rk3308_ops = { .set_to_rmii = rk3308_set_to_rmii, - .set_rmii_speed = rk3308_set_rmii_speed, + .set_speed = rk3308_set_speed, }; #define RK3328_GRF_MAC_CON0 0x0900 @@ -663,25 +605,18 @@ static const struct rk_reg_speed_data rk3328_reg_speed_data = { .rmii_100 = RK3328_GMAC_RMII_CLK_25M | RK3328_GMAC_SPEED_100M, }; -static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3328_reg_speed_data, - RK3328_GRF_MAC_CON1, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3328_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; unsigned int reg; - reg = bsp_priv->integrated_phy ? RK3328_GRF_MAC_CON2 : - RK3328_GRF_MAC_CON1; + if (interface == PHY_INTERFACE_MODE_RMII && bsp_priv->integrated_phy) + reg = RK3328_GRF_MAC_CON2; + else + reg = RK3328_GRF_MAC_CON1; - if (rk_set_reg_speed_rmii(bsp_priv, &rk3328_reg_speed_data, reg, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3328_reg_speed_data, reg, + interface, speed); } static void rk3328_integrated_phy_powerup(struct rk_priv_data *priv) @@ -695,8 +630,7 @@ static void rk3328_integrated_phy_powerup(struct rk_priv_data *priv) static const struct rk_gmac_ops rk3328_ops = { .set_to_rgmii = rk3328_set_to_rgmii, .set_to_rmii = rk3328_set_to_rmii, - .set_rgmii_speed = rk3328_set_rgmii_speed, - .set_rmii_speed = rk3328_set_rmii_speed, + .set_speed = rk3328_set_speed, .integrated_phy_powerup = rk3328_integrated_phy_powerup, .integrated_phy_powerdown = rk_gmac_integrated_ephy_powerdown, }; @@ -755,29 +689,17 @@ static const struct rk_reg_speed_data rk3366_reg_speed_data = { .rmii_100 = RK3366_GMAC_RMII_CLK_25M | RK3366_GMAC_SPEED_100M, }; -static void rk3366_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3366_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3366_reg_speed_data, - RK3366_GRF_SOC_CON6, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3366_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rk3366_reg_speed_data, - RK3366_GRF_SOC_CON6, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3366_reg_speed_data, + RK3366_GRF_SOC_CON6, interface, speed); } static const struct rk_gmac_ops rk3366_ops = { .set_to_rgmii = rk3366_set_to_rgmii, .set_to_rmii = rk3366_set_to_rmii, - .set_rgmii_speed = rk3366_set_rgmii_speed, - .set_rmii_speed = rk3366_set_rmii_speed, + .set_speed = rk3366_set_speed, }; #define RK3368_GRF_SOC_CON15 0x043c @@ -834,29 +756,17 @@ static const struct rk_reg_speed_data rk3368_reg_speed_data = { .rmii_100 = RK3368_GMAC_RMII_CLK_25M | RK3368_GMAC_SPEED_100M, }; -static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3368_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3368_reg_speed_data, - RK3368_GRF_SOC_CON15, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rk3368_reg_speed_data, - RK3368_GRF_SOC_CON15, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3368_reg_speed_data, + RK3368_GRF_SOC_CON15, interface, speed); } static const struct rk_gmac_ops rk3368_ops = { .set_to_rgmii = rk3368_set_to_rgmii, .set_to_rmii = rk3368_set_to_rmii, - .set_rgmii_speed = rk3368_set_rgmii_speed, - .set_rmii_speed = rk3368_set_rmii_speed, + .set_speed = rk3368_set_speed, }; #define RK3399_GRF_SOC_CON5 0xc214 @@ -913,29 +823,17 @@ static const struct rk_reg_speed_data rk3399_reg_speed_data = { .rmii_100 = RK3399_GMAC_RMII_CLK_25M | RK3399_GMAC_SPEED_100M, }; -static void rk3399_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3399_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3399_reg_speed_data, - RK3399_GRF_SOC_CON5, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3399_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rk3399_reg_speed_data, - RK3399_GRF_SOC_CON5, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3399_reg_speed_data, + RK3399_GRF_SOC_CON5, interface, speed); } static const struct rk_gmac_ops rk3399_ops = { .set_to_rgmii = rk3399_set_to_rgmii, .set_to_rmii = rk3399_set_to_rmii, - .set_rgmii_speed = rk3399_set_rgmii_speed, - .set_rmii_speed = rk3399_set_rmii_speed, + .set_speed = rk3399_set_speed, }; #define RK3528_VO_GRF_GMAC_CON 0x0018 @@ -1011,18 +909,9 @@ static const struct rk_reg_speed_data rk3528_gmac1_reg_speed_data = { .rmii_100 = RK3528_GMAC1_CLK_RMII_DIV2, }; -static void rk3528_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3528_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface,int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rgmii(bsp_priv, &rk3528_gmac1_reg_speed_data, - RK3528_VPU_GRF_GMAC_CON5, speed)) - dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -} - -static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -{ - struct device *dev = &bsp_priv->pdev->dev; const struct rk_reg_speed_data *rsd; unsigned int reg; @@ -1034,8 +923,7 @@ static void rk3528_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) reg = RK3528_VO_GRF_GMAC_CON; } - if (rk_set_reg_speed_rmii(bsp_priv, rsd, reg, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, rsd, reg, interface, speed); } static void rk3528_set_clock_selection(struct rk_priv_data *bsp_priv, @@ -1069,8 +957,7 @@ static void rk3528_integrated_phy_powerdown(struct rk_priv_data *bsp_priv) static const struct rk_gmac_ops rk3528_ops = { .set_to_rgmii = rk3528_set_to_rgmii, .set_to_rmii = rk3528_set_to_rmii, - .set_rgmii_speed = rk3528_set_rgmii_speed, - .set_rmii_speed = rk3528_set_rmii_speed, + .set_speed = rk3528_set_speed, .set_clock_selection = rk3528_set_clock_selection, .integrated_phy_powerup = rk3528_integrated_phy_powerup, .integrated_phy_powerdown = rk3528_integrated_phy_powerdown, @@ -1135,8 +1022,7 @@ static void rk3568_set_to_rmii(struct rk_priv_data *bsp_priv) static const struct rk_gmac_ops rk3568_ops = { .set_to_rgmii = rk3568_set_to_rgmii, .set_to_rmii = rk3568_set_to_rmii, - .set_rgmii_speed = rk_set_clk_mac_speed, - .set_rmii_speed = rk_set_clk_mac_speed, + .set_speed = rk_set_clk_mac_speed, .regs_valid = true, .regs = { 0xfe2a0000, /* gmac0 */ @@ -1228,17 +1114,16 @@ static const struct rk_reg_speed_data rk3578_reg_speed_data = { .rmii_100 = RK3576_GMAC_CLK_RMII_DIV2, }; -static void rk3576_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3576_set_gmac_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; unsigned int offset_con; offset_con = bsp_priv->id == 1 ? RK3576_GRF_GMAC_CON1 : RK3576_GRF_GMAC_CON0; - if (rk_set_reg_speed(bsp_priv, &rk3578_reg_speed_data, offset_con, - bsp_priv->phy_iface, speed)) - dev_err(dev, "unknown speed value for GMAC speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rk3578_reg_speed_data, offset_con, + interface, speed); } static void rk3576_set_clock_selection(struct rk_priv_data *bsp_priv, bool input, @@ -1260,8 +1145,7 @@ static void rk3576_set_clock_selection(struct rk_priv_data *bsp_priv, bool input static const struct rk_gmac_ops rk3576_ops = { .set_to_rgmii = rk3576_set_to_rgmii, .set_to_rmii = rk3576_set_to_rmii, - .set_rgmii_speed = rk3576_set_gmac_speed, - .set_rmii_speed = rk3576_set_gmac_speed, + .set_speed = rk3576_set_gmac_speed, .set_clock_selection = rk3576_set_clock_selection, .php_grf_required = true, .regs_valid = true, @@ -1345,26 +1229,26 @@ static void rk3588_set_to_rmii(struct rk_priv_data *bsp_priv) RK3588_GMAC_CLK_RMII_MODE(bsp_priv->id)); } -static void rk3588_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed) +static int rk3588_set_gmac_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; unsigned int val = 0, id = bsp_priv->id; switch (speed) { case 10: - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) + if (interface == PHY_INTERFACE_MODE_RMII) val = RK3588_GMA_CLK_RMII_DIV20(id); else val = RK3588_GMAC_CLK_RGMII_DIV50(id); break; case 100: - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) + if (interface == PHY_INTERFACE_MODE_RMII) val = RK3588_GMA_CLK_RMII_DIV2(id); else val = RK3588_GMAC_CLK_RGMII_DIV5(id); break; case 1000: - if (bsp_priv->phy_iface != PHY_INTERFACE_MODE_RMII) + if (interface != PHY_INTERFACE_MODE_RMII) val = RK3588_GMAC_CLK_RGMII_DIV1(id); else goto err; @@ -1375,9 +1259,9 @@ static void rk3588_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed) regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1, val); - return; + return 0; err: - dev_err(dev, "unknown speed value for GMAC speed=%d", speed); + return -EINVAL; } static void rk3588_set_clock_selection(struct rk_priv_data *bsp_priv, bool input, @@ -1395,8 +1279,7 @@ static void rk3588_set_clock_selection(struct rk_priv_data *bsp_priv, bool input static const struct rk_gmac_ops rk3588_ops = { .set_to_rgmii = rk3588_set_to_rgmii, .set_to_rmii = rk3588_set_to_rmii, - .set_rgmii_speed = rk3588_set_gmac_speed, - .set_rmii_speed = rk3588_set_gmac_speed, + .set_speed = rk3588_set_gmac_speed, .set_clock_selection = rk3588_set_clock_selection, .php_grf_required = true, .regs_valid = true, @@ -1430,18 +1313,16 @@ static const struct rk_reg_speed_data rv1108_reg_speed_data = { .rmii_100 = RV1108_GMAC_RMII_CLK_25M | RV1108_GMAC_SPEED_100M, }; -static void rv1108_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int rv1108_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { - struct device *dev = &bsp_priv->pdev->dev; - - if (rk_set_reg_speed_rmii(bsp_priv, &rv1108_reg_speed_data, - RV1108_GRF_GMAC_CON0, speed)) - dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return rk_set_reg_speed(bsp_priv, &rv1108_reg_speed_data, + RV1108_GRF_GMAC_CON0, interface, speed); } static const struct rk_gmac_ops rv1108_ops = { .set_to_rmii = rv1108_set_to_rmii, - .set_rmii_speed = rv1108_set_rmii_speed, + .set_speed = rv1108_set_speed, }; #define RV1126_GRF_GMAC_CON0 0X0070 @@ -1499,8 +1380,7 @@ static void rv1126_set_to_rmii(struct rk_priv_data *bsp_priv) static const struct rk_gmac_ops rv1126_ops = { .set_to_rgmii = rv1126_set_to_rgmii, .set_to_rmii = rv1126_set_to_rmii, - .set_rgmii_speed = rk_set_clk_mac_speed, - .set_rmii_speed = rk_set_clk_mac_speed, + .set_speed = rk_set_clk_mac_speed, }; static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat) @@ -1833,6 +1713,10 @@ static int rk_set_clk_tx_rate(void *bsp_priv_, struct clk *clk_tx_i, struct rk_priv_data *bsp_priv = bsp_priv_; struct device *dev = &bsp_priv->pdev->dev; + if (bsp_priv->ops->set_speed) + return bsp_priv->ops->set_speed(bsp_priv, bsp_priv->phy_iface, + speed); + switch (bsp_priv->phy_iface) { case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: -- 2.51.0 From c5cddcdbd2af9c3622820e31a250d7a656e2588e Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:41:12 +0100 Subject: [PATCH 11/16] net: stmmac: rk: simplify px30_set_rmii_speed() px30_set_rmii_speed() doesn't need to be as verbose as it is - it merely needs the values for the register and clock rate which depend on the speed, and then call the appropriate functions. Rewrite the function to make it so. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk3E-004CFl-BZ@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 8ad6b3b0e2823..72f2b80bf3bb7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -250,6 +250,8 @@ static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) { struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; struct device *dev = &bsp_priv->pdev->dev; + unsigned int con1; + long rate; int ret; if (!clk_mac_speed) { @@ -258,25 +260,22 @@ static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) } if (speed == 10) { - regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, - PX30_GMAC_SPEED_10M); - - ret = clk_set_rate(clk_mac_speed, 2500000); - if (ret) - dev_err(dev, "%s: set clk_mac_speed rate 2500000 failed: %d\n", - __func__, ret); + con1 = PX30_GMAC_SPEED_10M; + rate = 2500000; } else if (speed == 100) { - regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, - PX30_GMAC_SPEED_100M); - - ret = clk_set_rate(clk_mac_speed, 25000000); - if (ret) - dev_err(dev, "%s: set clk_mac_speed rate 25000000 failed: %d\n", - __func__, ret); - + con1 = PX30_GMAC_SPEED_100M; + rate = 25000000; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + return; } + + regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, con1); + + ret = clk_set_rate(clk_mac_speed, rate); + if (ret) + dev_err(dev, "%s: set clk_mac_speed rate %ld failed: %d\n", + __func__, rate, ret); } static const struct rk_gmac_ops px30_ops = { -- 2.51.0 From 9165487d21a47be6bf0c87a85c68373ca2ad170a Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:41:17 +0100 Subject: [PATCH 12/16] net: stmmac: rk: convert px30_set_rmii_speed() to .set_speed() Convert px30_set_rmii_speed() to use the common .set_speed() method, which eliminates another user of the older .set_*_speed() methods. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk3J-004CFr-FE@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 72f2b80bf3bb7..7cdb09037da0e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -246,17 +246,17 @@ static void px30_set_to_rmii(struct rk_priv_data *bsp_priv) PX30_GMAC_PHY_INTF_SEL_RMII); } -static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) +static int px30_set_speed(struct rk_priv_data *bsp_priv, + phy_interface_t interface, int speed) { struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk; struct device *dev = &bsp_priv->pdev->dev; unsigned int con1; long rate; - int ret; if (!clk_mac_speed) { dev_err(dev, "%s: Missing clk_mac_speed clock\n", __func__); - return; + return -EINVAL; } if (speed == 10) { @@ -267,20 +267,17 @@ static void px30_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) rate = 25000000; } else { dev_err(dev, "unknown speed value for RMII! speed=%d", speed); - return; + return -EINVAL; } regmap_write(bsp_priv->grf, PX30_GRF_GMAC_CON1, con1); - ret = clk_set_rate(clk_mac_speed, rate); - if (ret) - dev_err(dev, "%s: set clk_mac_speed rate %ld failed: %d\n", - __func__, rate, ret); + return clk_set_rate(clk_mac_speed, rate); } static const struct rk_gmac_ops px30_ops = { .set_to_rmii = px30_set_to_rmii, - .set_rmii_speed = px30_set_rmii_speed, + .set_speed = px30_set_speed, }; #define RK3128_GRF_MAC_CON0 0x0168 -- 2.51.0 From 0f3a079786bade0bdadd4c9db6d63459827a3717 Mon Sep 17 00:00:00 2001 From: "Russell King (Oracle)" Date: Thu, 12 Jun 2025 16:41:22 +0100 Subject: [PATCH 13/16] net: stmmac: rk: remove obsolete .set_*_speed() methods Now that no SoC implements the .set_*_speed() methods, we can get rid of these methods and the now unused code in rk_set_clk_tx_rate(). Arrange for the function to return an error when the .set_speed() method is not implemented. Signed-off-by: Russell King (Oracle) Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/E1uPk3O-004CFx-Ir@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski --- .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 7cdb09037da0e..18ae12df4a850 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -37,8 +37,6 @@ struct rk_gmac_ops { void (*set_to_rgmii)(struct rk_priv_data *bsp_priv, int tx_delay, int rx_delay); void (*set_to_rmii)(struct rk_priv_data *bsp_priv); - void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); - void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); int (*set_speed)(struct rk_priv_data *bsp_priv, phy_interface_t interface, int speed); void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input, @@ -1707,29 +1705,12 @@ static int rk_set_clk_tx_rate(void *bsp_priv_, struct clk *clk_tx_i, phy_interface_t interface, int speed) { struct rk_priv_data *bsp_priv = bsp_priv_; - struct device *dev = &bsp_priv->pdev->dev; if (bsp_priv->ops->set_speed) return bsp_priv->ops->set_speed(bsp_priv, bsp_priv->phy_iface, speed); - switch (bsp_priv->phy_iface) { - case PHY_INTERFACE_MODE_RGMII: - case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - if (bsp_priv->ops->set_rgmii_speed) - bsp_priv->ops->set_rgmii_speed(bsp_priv, speed); - break; - case PHY_INTERFACE_MODE_RMII: - if (bsp_priv->ops->set_rmii_speed) - bsp_priv->ops->set_rmii_speed(bsp_priv, speed); - break; - default: - dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); - } - - return 0; + return -EINVAL; } static int rk_gmac_probe(struct platform_device *pdev) -- 2.51.0 From c969149bafbeb8ae113747e00ae3ef97461f2cd4 Mon Sep 17 00:00:00 2001 From: Yuesong Li Date: Fri, 13 Jun 2025 18:20:12 +0800 Subject: [PATCH 14/16] net: amt: convert to use secs_to_jiffies Since secs_to_jiffies()(commit:b35108a51cf7) has been introduced, we can use it to avoid scaling the time to msec. Signed-off-by: Yuesong Li Reviewed-by: Joe Damato Reviewed-by: Taehee Yoo Link: https://patch.msgid.link/20250613102014.3070898-1-liyuesong@vivo.com Signed-off-by: Jakub Kicinski --- drivers/net/amt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 734a0b3242a9b..fb130fde68c07 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -979,7 +979,7 @@ static void amt_event_send_request(struct amt_dev *amt) amt->req_cnt++; out: exp = min_t(u32, (1 * (1 << amt->req_cnt)), AMT_MAX_REQ_TIMEOUT); - mod_delayed_work(amt_wq, &amt->req_wq, msecs_to_jiffies(exp * 1000)); + mod_delayed_work(amt_wq, &amt->req_wq, secs_to_jiffies(exp)); } static void amt_req_work(struct work_struct *work) -- 2.51.0 From ffe8a49091767f71802a3c601c121aa0ab84ac5f Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Fri, 13 Jun 2025 12:15:47 +0530 Subject: [PATCH 15/16] net: ti: icssg-prueth: Read firmware-names from device tree Refactor the way firmware names are handled for the ICSSG PRUETH driver. Instead of using hardcoded firmware name arrays for different modes (EMAC, SWITCH, HSR), the driver now reads the firmware names from the device tree property "firmware-name". Only the EMAC firmware names are specified in the device tree property. The firmware names for all other supported modes are generated dynamically based on the EMAC firmware names by replacing substrings (e.g., "eth" with "sw" or "hsr") as appropriate. Example: Below are the firmwares used currently for PRU0 core EMAC: ti-pruss/am65x-sr2-pru0-prueth-fw.elf SW : ti-pruss/am65x-sr2-pru0-prusw-fw.elf HSR : ti-pruss/am65x-sr2-pru0-pruhsr-fw.elf All three firmware names are same except for the operating mode. In general for PRU0 core, firmware name is, ti-pruss/am65x-sr2-pru0-pru-fw.elf Since the EMAC firmware names are defined in DT, driver will read those directly and for other modes swap the mode name. i.e. eth -> sw or eth -> hsr. This preserves backwards compatibility as ICSSG driver is supported only by AM65x and AM64x. Both of these have "firmware-name" property populated in their device tree. Signed-off-by: MD Danish Anwar Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250613064547.44394-1-danishanwar@ti.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 135 +++++++++++++------ drivers/net/ethernet/ti/icssg/icssg_prueth.h | 12 +- 2 files changed, 102 insertions(+), 45 deletions(-) diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 86fc1278127c7..a1e013b0a0ebc 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -125,45 +125,6 @@ static irqreturn_t prueth_tx_ts_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static struct icssg_firmwares icssg_hsr_firmwares[] = { - { - .pru = "ti-pruss/am65x-sr2-pru0-pruhsr-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu0-pruhsr-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru0-pruhsr-fw.elf", - }, - { - .pru = "ti-pruss/am65x-sr2-pru1-pruhsr-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu1-pruhsr-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru1-pruhsr-fw.elf", - } -}; - -static struct icssg_firmwares icssg_switch_firmwares[] = { - { - .pru = "ti-pruss/am65x-sr2-pru0-prusw-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu0-prusw-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru0-prusw-fw.elf", - }, - { - .pru = "ti-pruss/am65x-sr2-pru1-prusw-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu1-prusw-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru1-prusw-fw.elf", - } -}; - -static struct icssg_firmwares icssg_emac_firmwares[] = { - { - .pru = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", - }, - { - .pru = "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf", - } -}; - static int prueth_start(struct rproc *rproc, const char *fw_name) { int ret; @@ -186,11 +147,11 @@ static int prueth_emac_start(struct prueth *prueth) int ret, slice; if (prueth->is_switch_mode) - firmwares = icssg_switch_firmwares; + firmwares = prueth->icssg_switch_firmwares; else if (prueth->is_hsr_offload_mode) - firmwares = icssg_hsr_firmwares; + firmwares = prueth->icssg_hsr_firmwares; else - firmwares = icssg_emac_firmwares; + firmwares = prueth->icssg_emac_firmwares; for (slice = 0; slice < PRUETH_NUM_MACS; slice++) { ret = prueth_start(prueth->pru[slice], firmwares[slice].pru); @@ -1632,6 +1593,87 @@ static void prueth_unregister_notifiers(struct prueth *prueth) unregister_netdevice_notifier(&prueth->prueth_netdevice_nb); } +static void icssg_read_firmware_names(struct device_node *np, + struct icssg_firmwares *fw) +{ + int i; + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + of_property_read_string_index(np, "firmware-name", i * 3 + 0, + &fw[i].pru); + of_property_read_string_index(np, "firmware-name", i * 3 + 1, + &fw[i].rtu); + of_property_read_string_index(np, "firmware-name", i * 3 + 2, + &fw[i].txpru); + } +} + +/* icssg_firmware_name_replace - Replace a substring in firmware name + * @dev: device pointer for memory allocation + * @src: source firmware name string + * @from: substring to replace + * @to: replacement substring + * + * Return: a newly allocated string with the replacement, or the original + * string if replacement is not possible. + */ +static const char *icssg_firmware_name_replace(struct device *dev, + const char *src, + const char *from, + const char *to) +{ + size_t prefix, from_len, to_len, total; + const char *p = strstr(src, from); + char *buf; + + if (!p) + return src; /* fallback: no replacement, use original */ + + prefix = p - src; + from_len = strlen(from); + to_len = strlen(to); + total = strlen(src) - from_len + to_len + 1; + + buf = devm_kzalloc(dev, total, GFP_KERNEL); + if (!buf) + return src; /* fallback: allocation failed, use original */ + + strscpy(buf, src, prefix + 1); + strscpy(buf + prefix, to, to_len + 1); + strscpy(buf + prefix + to_len, p + from_len, total - prefix - to_len); + + return buf; +} + +/** + * icssg_mode_firmware_names - Generate firmware names for a specific mode + * @dev: device pointer for logging and context + * @src: source array of firmware name structures + * @dst: destination array to store updated firmware name structures + * @from: substring in firmware names to be replaced + * @to: substring to replace @from in firmware names + * + * Iterates over all MACs and replaces occurrences of the @from substring + * with @to in the firmware names (pru, rtu, txpru) for each MAC. The + * updated firmware names are stored in the @dst array. + */ +static void icssg_mode_firmware_names(struct device *dev, + struct icssg_firmwares *src, + struct icssg_firmwares *dst, + const char *from, const char *to) +{ + int i; + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + dst[i].pru = icssg_firmware_name_replace(dev, src[i].pru, + from, to); + dst[i].rtu = icssg_firmware_name_replace(dev, src[i].rtu, + from, to); + dst[i].txpru = icssg_firmware_name_replace(dev, src[i].txpru, + from, to); + } +} + static int prueth_probe(struct platform_device *pdev) { struct device_node *eth_node, *eth_ports_node; @@ -1808,6 +1850,15 @@ static int prueth_probe(struct platform_device *pdev) icss_iep_init_fw(prueth->iep1); } + /* Read EMAC firmware names from device tree */ + icssg_read_firmware_names(np, prueth->icssg_emac_firmwares); + + /* Generate other mode firmware names based on EMAC firmware names */ + icssg_mode_firmware_names(dev, prueth->icssg_emac_firmwares, + prueth->icssg_switch_firmwares, "eth", "sw"); + icssg_mode_firmware_names(dev, prueth->icssg_emac_firmwares, + prueth->icssg_hsr_firmwares, "eth", "hsr"); + spin_lock_init(&prueth->vtbl_lock); spin_lock_init(&prueth->stats_lock); /* setup netdev interfaces */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index 23c465f1ce7ff..c03e3b3626c17 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -259,9 +259,9 @@ struct prueth_pdata { }; struct icssg_firmwares { - char *pru; - char *rtu; - char *txpru; + const char *pru; + const char *rtu; + const char *txpru; }; /** @@ -300,6 +300,9 @@ struct icssg_firmwares { * @is_switchmode_supported: indicates platform support for switch mode * @switch_id: ID for mapping switch ports to bridge * @default_vlan: Default VLAN for host + * @icssg_emac_firmwares: Firmware names for EMAC mode, indexed per MAC + * @icssg_switch_firmwares: Firmware names for SWITCH mode, indexed per MAC + * @icssg_hsr_firmwares: Firmware names for HSR mode, indexed per MAC */ struct prueth { struct device *dev; @@ -343,6 +346,9 @@ struct prueth { spinlock_t vtbl_lock; /** @stats_lock: Lock for reading icssg stats */ spinlock_t stats_lock; + struct icssg_firmwares icssg_emac_firmwares[PRUETH_NUM_MACS]; + struct icssg_firmwares icssg_switch_firmwares[PRUETH_NUM_MACS]; + struct icssg_firmwares icssg_hsr_firmwares[PRUETH_NUM_MACS]; }; struct emac_tx_ts_response { -- 2.51.0 From 0c17270f9b920e4e1777488f1911bbfdaf2af3be Mon Sep 17 00:00:00 2001 From: Yajun Deng Date: Thu, 12 Jun 2025 14:27:07 +0000 Subject: [PATCH 16/16] net: sysfs: Implement is_visible for phys_(port_id, port_name, switch_id) phys_port_id_show, phys_port_name_show and phys_switch_id_show would return -EOPNOTSUPP if the netdev didn't implement the corresponding method. There is no point in creating these files if they are unsupported. Put these attributes in netdev_phys_group and implement the is_visible method. make phys_(port_id, port_name, switch_id) invisible if the netdev dosen't implement the corresponding method. Signed-off-by: Yajun Deng Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250612142707.4644-1-yajun.deng@linux.dev Signed-off-by: Jakub Kicinski --- include/linux/netdevice.h | 2 +- net/core/net-sysfs.c | 59 +++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index adb14db257984..9cbc4e54b7e4a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2388,7 +2388,7 @@ struct net_device { struct dm_hw_stat_delta __rcu *dm_private; #endif struct device dev; - const struct attribute_group *sysfs_groups[4]; + const struct attribute_group *sysfs_groups[5]; const struct attribute_group *sysfs_rx_queue_group; const struct rtnl_link_ops *rtnl_link_ops; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 1ace0cd01adce..c9b9693863999 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -641,12 +641,6 @@ static ssize_t phys_port_id_show(struct device *dev, struct netdev_phys_item_id ppid; ssize_t ret; - /* The check is also done in dev_get_phys_port_id; this helps returning - * early without hitting the locking section below. - */ - if (!netdev->netdev_ops->ndo_get_phys_port_id) - return -EOPNOTSUPP; - ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev); if (ret) return ret; @@ -668,13 +662,6 @@ static ssize_t phys_port_name_show(struct device *dev, char name[IFNAMSIZ]; ssize_t ret; - /* The checks are also done in dev_get_phys_port_name; this helps - * returning early without hitting the locking section below. - */ - if (!netdev->netdev_ops->ndo_get_phys_port_name && - !netdev->devlink_port) - return -EOPNOTSUPP; - ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev); if (ret) return ret; @@ -696,14 +683,6 @@ static ssize_t phys_switch_id_show(struct device *dev, struct netdev_phys_item_id ppid = { }; ssize_t ret; - /* The checks are also done in dev_get_phys_port_name; this helps - * returning early without hitting the locking section below. This works - * because recurse is false when calling dev_get_port_parent_id. - */ - if (!netdev->netdev_ops->ndo_get_port_parent_id && - !netdev->devlink_port) - return -EOPNOTSUPP; - ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev); if (ret) return ret; @@ -718,6 +697,40 @@ static ssize_t phys_switch_id_show(struct device *dev, } static DEVICE_ATTR_RO(phys_switch_id); +static struct attribute *netdev_phys_attrs[] __ro_after_init = { + &dev_attr_phys_port_id.attr, + &dev_attr_phys_port_name.attr, + &dev_attr_phys_switch_id.attr, + NULL, +}; + +static umode_t netdev_phys_is_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = kobj_to_dev(kobj); + struct net_device *netdev = to_net_dev(dev); + + if (attr == &dev_attr_phys_port_id.attr) { + if (!netdev->netdev_ops->ndo_get_phys_port_id) + return 0; + } else if (attr == &dev_attr_phys_port_name.attr) { + if (!netdev->netdev_ops->ndo_get_phys_port_name && + !netdev->devlink_port) + return 0; + } else if (attr == &dev_attr_phys_switch_id.attr) { + if (!netdev->netdev_ops->ndo_get_port_parent_id && + !netdev->devlink_port) + return 0; + } + + return attr->mode; +} + +static const struct attribute_group netdev_phys_group = { + .attrs = netdev_phys_attrs, + .is_visible = netdev_phys_is_visible, +}; + static ssize_t threaded_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -783,9 +796,6 @@ static struct attribute *net_class_attrs[] __ro_after_init = { &dev_attr_tx_queue_len.attr, &dev_attr_gro_flush_timeout.attr, &dev_attr_napi_defer_hard_irqs.attr, - &dev_attr_phys_port_id.attr, - &dev_attr_phys_port_name.attr, - &dev_attr_phys_switch_id.attr, &dev_attr_proto_down.attr, &dev_attr_carrier_up_count.attr, &dev_attr_carrier_down_count.attr, @@ -2328,6 +2338,7 @@ int netdev_register_kobject(struct net_device *ndev) groups++; *groups++ = &netstat_group; + *groups++ = &netdev_phys_group; if (wireless_group_needed(ndev)) *groups++ = &wireless_group; -- 2.51.0