2668 lines
71 KiB
C
2668 lines
71 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2021 JLSemi Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation version 2.
|
|
*
|
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
|
* kind, whether express or implied; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
*/
|
|
#include "jlsemi-core.h"
|
|
#include <linux/phy.h>
|
|
#include <linux/module.h>
|
|
#include <linux/version.h>
|
|
#include <linux/netdevice.h>
|
|
|
|
#define JL1XXX_PAGE24 24
|
|
#define JL1XXX_LED_BLINK_REG 25
|
|
|
|
#define JL1XXX_PAGE128 128
|
|
#define JL1XXX_LED_GPIO_REG 29
|
|
#define JL1XXX_WOL_CTRL_REG 28
|
|
|
|
#define JL2XXX_PAGE3332 3332
|
|
#define JL2XXX_LED_CTRL_REG 16
|
|
#define JL2XXX_PAGE4096 4096
|
|
#define JL2XXX_LED_BLINK_REG 20
|
|
#define JL2XXX_LED_POLARITY_REG 19
|
|
|
|
#define JL2XXX_PAGE128 128
|
|
#define JL2XXX_FLD_CTRL_REG 28
|
|
#define JL2XXX_FLD_EN BIT(13)
|
|
#define JL2XXX_FLD_MASK 0x1800
|
|
#define JL2XXX_FLD_MASK_HEAD 11
|
|
#define JL2XXX_FLD_DELAY_00MS 0
|
|
#define JL2XXX_FLD_DELAY_10MS 1
|
|
#define JL2XXX_FLD_DELAY_20MS 2
|
|
#define JL2XXX_FLD_DELAY_40MS 3
|
|
|
|
#define JL2XXX_SPEED10 0
|
|
#define JL2XXX_SPEED100 1
|
|
#define JL2XXX_SPEED1000 2
|
|
|
|
#define JL2XXX_PHY_MODE_REG 30
|
|
#define JL2XXX_FIBER_1000 BIT(12)
|
|
#define JL2XXX_FIBER_100 BIT(11)
|
|
#define JL2XXX_PHY_FIBER_MODE_MASK 0x1800
|
|
#define JL2XXX_BMCR_DUPLEX BIT(8)
|
|
#define JL2XXX_LPA_FIBER_1000HALF 0x40
|
|
#define JL2XXX_LPA_FIBER_1000FULL 0x20
|
|
#define JL2XXX_BMCR_SPEED_LSB BIT(13)
|
|
#define JL2XXX_BMCR_SPEED_MSB BIT(6)
|
|
#define JL2XXX_BMCR_AN_RESTART BIT(9)
|
|
|
|
|
|
|
|
#define JL2XXX_SUPP_LED_MODE (JL2XXX_LED0_LINK10 | \
|
|
JL2XXX_LED0_LINK100 | \
|
|
JL2XXX_LED0_LINK1000 | \
|
|
JL2XXX_LED0_ACTIVITY | \
|
|
JL2XXX_LED1_LINK10 | \
|
|
JL2XXX_LED1_LINK100 | \
|
|
JL2XXX_LED1_LINK1000 | \
|
|
JL2XXX_LED1_ACTIVITY | \
|
|
JL2XXX_LED2_LINK10 | \
|
|
JL2XXX_LED2_LINK100 | \
|
|
JL2XXX_LED2_LINK1000 | \
|
|
JL2XXX_LED2_ACTIVITY)
|
|
|
|
#define JL1XXX_SUPP_GPIO (JL1XXX_GPIO_LED0_EN | \
|
|
JL1XXX_GPIO_LED0_OUT | \
|
|
JL1XXX_GPIO_LED1_EN | \
|
|
JL1XXX_GPIO_LED1_OUT)
|
|
|
|
#define JL1XXX_SUPP_LED_MODE (JL1XXX_LED0_EEE | \
|
|
JL1XXX_LED0_100_ACTIVITY | \
|
|
JL1XXX_LED0_10_ACTIVITY | \
|
|
JL1XXX_LED0_100_LINK | \
|
|
JL1XXX_LED0_10_LINK | \
|
|
JL1XXX_LED1_EEE | \
|
|
JL1XXX_LED1_100_ACTIVITY | \
|
|
JL1XXX_LED1_10_ACTIVITY | \
|
|
JL1XXX_LED1_100_LINK | \
|
|
JL1XXX_LED1_10_LINK)
|
|
|
|
/************************* Configuration section *************************/
|
|
|
|
|
|
/************************* JLSemi iteration code *************************/
|
|
static int jl1xxx_led_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
/* Enable LED operation */
|
|
jlsemi_set_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_LED_REG, JL1XXX_LED_EN);
|
|
|
|
/* Set led mode */
|
|
if (priv->led.enable & JL1XXX_LED_MODE_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE129,
|
|
JL1XXX_LED_MODE_REG,
|
|
JL1XXX_SUPP_LED_MODE,
|
|
priv->led.mode);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
/* Set led period */
|
|
if (priv->led.enable & JL1XXX_LED_GLOABL_PERIOD_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE24,
|
|
JL1XXX_LED_BLINK_REG,
|
|
LED_PERIOD_MASK,
|
|
LEDPERIOD(
|
|
priv->led.global_period));
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
/* Set led on time */
|
|
if (priv->led.enable & JL1XXX_LED_GLOBAL_ON_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE24,
|
|
JL1XXX_LED_BLINK_REG,
|
|
LED_ON_MASK,
|
|
LEDON(priv->led.global_on));
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
/*Set led gpio output */
|
|
if (priv->led.enable & JL1XXX_LED_GPIO_OUT_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE128,
|
|
JL1XXX_LED_GPIO_REG,
|
|
JL1XXX_SUPP_GPIO,
|
|
priv->led.gpio_output);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_led_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
/* Set led mode */
|
|
if (priv->led.enable & JL2XXX_LED_MODE_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE3332,
|
|
JL2XXX_LED_CTRL_REG,
|
|
JL2XXX_SUPP_LED_MODE,
|
|
priv->led.mode);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
/* Set led period */
|
|
if (priv->led.enable & JL2XXX_LED_GLOABL_PERIOD_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE4096,
|
|
JL2XXX_LED_BLINK_REG,
|
|
LED_PERIOD_MASK,
|
|
LEDPERIOD(
|
|
priv->led.global_period));
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
/* Set led on time */
|
|
if (priv->led.enable & JL2XXX_LED_GLOBAL_ON_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE4096,
|
|
JL2XXX_LED_BLINK_REG,
|
|
LED_ON_MASK,
|
|
LEDON(priv->led.global_on));
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
/* Set led polarity */
|
|
if (priv->led.enable & JL2XXX_LED_POLARITY_EN) {
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE4096,
|
|
JL2XXX_LED_POLARITY_REG,
|
|
priv->led.polarity);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct device *jlsemi_get_mdio(struct phy_device *phydev)
|
|
{
|
|
#if JLSEMI_DEV_COMPATIBLE
|
|
struct device *dev = &phydev->dev;
|
|
#else
|
|
struct device *dev = &phydev->mdio.dev;
|
|
#endif
|
|
return dev;
|
|
}
|
|
|
|
static struct device_node *get_device_node(struct phy_device *phydev)
|
|
{
|
|
struct device *dev = jlsemi_get_mdio(phydev);
|
|
|
|
return dev->of_node;
|
|
}
|
|
|
|
static int jl1xxx_dts_led_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl1xxx,led-enable",
|
|
&priv->led.enable);
|
|
of_property_read_u32(of_node, "jl1xxx,led-mode",
|
|
&priv->led.mode);
|
|
of_property_read_u32(of_node, "jl1xxx,led-period",
|
|
&priv->led.global_period);
|
|
of_property_read_u32(of_node, "jl1xxx,led-on",
|
|
&priv->led.global_on);
|
|
of_property_read_u32(of_node, "jl1xxx,led-gpio",
|
|
&priv->led.gpio_output);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_dts_wol_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl1xxx,wol-enable",
|
|
&priv->wol.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_dts_intr_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl1xxx,interrupt-enable",
|
|
&priv->intr.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_dts_mdi_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl1xxx,mdi-enable",
|
|
&priv->mdi.enable);
|
|
of_property_read_u32(of_node, "jl1xxx,mdi-rate",
|
|
&priv->mdi.rate);
|
|
of_property_read_u32(of_node, "jl1xxx,mdi-amplitude",
|
|
&priv->mdi.amplitude);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_dts_rmii_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl1xxx,rmii-enable",
|
|
&priv->rmii.enable);
|
|
of_property_read_u32(of_node, "jl1xxx,rmii-rx_timing",
|
|
&priv->rmii.rx_timing);
|
|
of_property_read_u32(of_node, "jl1xxx,rmii-tx_timing",
|
|
&priv->rmii.tx_timing);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int jl2xxx_dts_led_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,led-enable",
|
|
&priv->led.enable);
|
|
of_property_read_u32(of_node, "jl2xxx,led-mode",
|
|
&priv->led.mode);
|
|
of_property_read_u32(of_node, "jl2xxx,led-period",
|
|
&priv->led.global_period);
|
|
of_property_read_u32(of_node, "jl2xxx,led-on",
|
|
&priv->led.global_on);
|
|
of_property_read_u32(of_node, "jl2xxx,led-polarity",
|
|
&priv->led.polarity);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_c_macro_led_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
|
|
/* Config LED */
|
|
struct jl_led_ctrl led_cfg = {
|
|
.enable = JL1XXX_LED_CTRL_EN,
|
|
.mode = JL1XXX_CFG_LED_MODE,
|
|
.global_period = JL1XXX_GLOBAL_PERIOD_MS,
|
|
.global_on = JL1XXX_GLOBAL_ON_MS,
|
|
.gpio_output = JL1XXX_CFG_GPIO,
|
|
};
|
|
|
|
priv->led = led_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_c_macro_wol_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_wol_ctrl wol_cfg = {
|
|
.enable = JL1XXX_WOL_CTRL_EN,
|
|
};
|
|
|
|
priv->wol = wol_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_c_macro_intr_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_intr_ctrl intr_cfg = {
|
|
.enable = JL1XXX_INTR_CTRL_EN,
|
|
};
|
|
|
|
priv->intr = intr_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_c_macro_mdi_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_mdi_ctrl mdi_cfg = {
|
|
.enable = JL1XXX_MDI_CTRL_EN,
|
|
.rate = JL1XXX_MDI_RATE,
|
|
.amplitude = JL1XXX_MDI_AMPLITUDE,
|
|
};
|
|
|
|
priv->mdi = mdi_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_c_macro_rmii_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_rmii_ctrl rmii_cfg = {
|
|
.enable = JL1XXX_RMII_CTRL_EN,
|
|
.tx_timing = JL1XXX_RMII_TX_TIMING,
|
|
.rx_timing = JL1XXX_RMII_RX_TIMING,
|
|
};
|
|
|
|
priv->rmii = rmii_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_led_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_led_ctrl led_cfg = {
|
|
.enable = JL2XXX_LED_CTRL_EN,
|
|
.mode = JL2XXX_CFG_LED_MODE,
|
|
.global_period = JL2XXX_GLOBAL_PERIOD_MS,
|
|
.global_on = JL2XXX_GLOBAL_ON_MS,
|
|
.polarity = JL2XXX_LED_POLARITY,
|
|
};
|
|
|
|
priv->led = led_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_wol_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct jl_wol_ctrl *wol = &priv->wol;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl1xxx_dts_wol_cfg_get(phydev);
|
|
else
|
|
jl1xxx_c_macro_wol_cfg_get(phydev);
|
|
|
|
/* Supported by default */
|
|
wol->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_intr_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct jl_intr_ctrl *intr = &priv->intr;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl1xxx_dts_intr_cfg_get(phydev);
|
|
else
|
|
jl1xxx_c_macro_intr_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
intr->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_mdi_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct jl_mdi_ctrl *mdi = &priv->mdi;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl1xxx_dts_mdi_cfg_get(phydev);
|
|
else
|
|
jl1xxx_c_macro_mdi_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
mdi->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_rmii_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct jl_rmii_ctrl *rmii = &priv->rmii;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl1xxx_dts_rmii_cfg_get(phydev);
|
|
else
|
|
jl1xxx_c_macro_rmii_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
rmii->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_led_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
struct jl_led_ctrl *led = &priv->led;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl1xxx_dts_led_cfg_get(phydev);
|
|
else
|
|
jl1xxx_c_macro_led_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
led->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_led_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_led_ctrl *led = &priv->led;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_led_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_led_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
led->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int jl2xxx_dts_fld_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,fld-enable",
|
|
&priv->fld.enable);
|
|
of_property_read_u32(of_node, "jl2xxx,fld-delay",
|
|
&priv->fld.delay);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_wol_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,wol-enable",
|
|
&priv->wol.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_intr_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,interrupt-enable",
|
|
&priv->intr.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_downshift_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,downshift-enable",
|
|
&priv->downshift.enable);
|
|
of_property_read_u32(of_node, "jl2xxx,downshift-count",
|
|
&priv->downshift.count);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_rgmii_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,rgmii-enable",
|
|
&priv->rgmii.enable);
|
|
of_property_read_u32(of_node, "jl2xxx,rgmii-tx-delay",
|
|
&priv->rgmii.tx_delay);
|
|
of_property_read_u32(of_node, "jl2xxx,rgmii-rx-delay",
|
|
&priv->rgmii.rx_delay);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_patch_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,patch-enable",
|
|
&priv->patch.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_clk_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,clk-enable",
|
|
&priv->clk.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_work_mode_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,work_mode-enable",
|
|
&priv->work_mode.enable);
|
|
of_property_read_u32(of_node, "jl2xxx,work_mode-mode",
|
|
&priv->work_mode.mode);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_lpbk_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,lpbk-enable",
|
|
&priv->lpbk.enable);
|
|
of_property_read_u32(of_node, "jl2xxx,lpbk-mode",
|
|
&priv->lpbk.mode);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_slew_rate_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,slew_rate-enable",
|
|
&priv->slew_rate.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_dts_rxc_out_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct device_node *of_node = get_device_node(phydev);
|
|
|
|
of_property_read_u32(of_node, "jl2xxx,rxc_out-enable",
|
|
&priv->rxc_out.enable);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_fld_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_fld_ctrl fld_cfg = {
|
|
.enable = JL2XXX_FLD_CTRL_EN,
|
|
.delay = JL2XXX_FLD_DELAY,
|
|
};
|
|
|
|
priv->fld = fld_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_wol_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_wol_ctrl wol_cfg = {
|
|
.enable = JL2XXX_WOL_CTRL_EN,
|
|
};
|
|
|
|
priv->wol = wol_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_intr_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_intr_ctrl intr_cfg = {
|
|
.enable = JL2XXX_INTR_CTRL_EN,
|
|
};
|
|
|
|
priv->intr = intr_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_downshift_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_downshift_ctrl downshift_cfg = {
|
|
.enable = JL2XXX_DSFT_CTRL_EN,
|
|
.count = JL2XXX_DSFT_AN_CNT,
|
|
};
|
|
|
|
priv->downshift = downshift_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_rgmii_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_rgmii_ctrl rgmii_cfg = {
|
|
.enable = JL2XXX_RGMII_CTRL_EN,
|
|
.rx_delay = JL2XXX_RGMII_RX_DLY_2NS,
|
|
.tx_delay = JL2XXX_RGMII_TX_DLY_2NS,
|
|
};
|
|
|
|
priv->rgmii = rgmii_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_patch_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_patch_ctrl patch_cfg = {
|
|
.enable = JL2XXX_PATCH_CTRL_EN,
|
|
};
|
|
|
|
priv->patch = patch_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_clk_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_clk_ctrl clk_cfg = {
|
|
.enable = JL2XXX_CLK_CTRL_EN,
|
|
};
|
|
|
|
priv->clk = clk_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_work_mode_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_work_mode_ctrl work_mode_cfg = {
|
|
.enable = JL2XXX_WORK_MODE_CTRL_EN,
|
|
.mode = JL2XXX_WORK_MODE_MODE,
|
|
};
|
|
|
|
priv->work_mode = work_mode_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_lpbk_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_loopback_ctrl lpbk_cfg = {
|
|
.enable = JL2XXX_LPBK_CTRL_EN,
|
|
.mode = JL2XXX_LPBK_MODE,
|
|
};
|
|
|
|
priv->lpbk = lpbk_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_slew_rate_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_slew_rate_ctrl slew_rate_cfg = {
|
|
.enable = JL2XXX_SLEW_RATE_CTRL_EN,
|
|
};
|
|
|
|
priv->slew_rate = slew_rate_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_c_macro_rxc_out_cfg_get(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
struct jl_rxc_out_ctrl rxc_out_cfg = {
|
|
.enable = JL2XXX_RXC_OUT_CTRL_EN,
|
|
};
|
|
|
|
priv->rxc_out = rxc_out_cfg;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_fld_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_fld_ctrl *fld = &priv->fld;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_fld_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_fld_cfg_get(phydev);
|
|
|
|
/* Supported by default */
|
|
fld->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_wol_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_wol_ctrl *wol = &priv->wol;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_wol_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_wol_cfg_get(phydev);
|
|
|
|
/* Supported by default */
|
|
wol->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_intr_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_intr_ctrl *intr = &priv->intr;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_intr_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_intr_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
intr->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_downshift_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_downshift_ctrl *downshift = &priv->downshift;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_downshift_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_downshift_cfg_get(phydev);
|
|
|
|
/* Supported by default */
|
|
downshift->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_rgmii_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_rgmii_ctrl *rgmii = &priv->rgmii;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_rgmii_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_rgmii_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
rgmii->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_patch_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_patch_ctrl *patch = &priv->patch;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_patch_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_patch_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
patch->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_clk_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_clk_ctrl *clk = &priv->clk;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_clk_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_clk_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
clk->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_work_mode_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_work_mode_ctrl *work_mode = &priv->work_mode;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_work_mode_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_work_mode_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
work_mode->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_lpbk_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_loopback_ctrl *lpbk = &priv->lpbk;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_lpbk_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_lpbk_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
lpbk->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_slew_rate_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_slew_rate_ctrl *slew_rate = &priv->slew_rate;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_slew_rate_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_slew_rate_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
slew_rate->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_rxc_out_operation_args(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
struct jl_rxc_out_ctrl *rxc_out = &priv->rxc_out;
|
|
|
|
if (JLSEMI_KERNEL_DEVICE_TREE_USE)
|
|
jl2xxx_dts_rxc_out_cfg_get(phydev);
|
|
else
|
|
jl2xxx_c_macro_rxc_out_cfg_get(phydev);
|
|
|
|
/* Not supported by default */
|
|
rxc_out->ethtool = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_fld_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
u8 val;
|
|
|
|
val = priv->fld.delay & 0xff;
|
|
err = jl2xxx_fld_dynamic_op_set(phydev, &val);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_wol_cfg_rmii(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
/* WOL Function should be in RMII Mode, the rmii
|
|
* clock direction should be output
|
|
*/
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_RMII_CTRL_REG,
|
|
JL1XXX_RMII_OUT,
|
|
JL1XXX_RMII_MODE);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl1xxx_wol_clear(struct phy_device *phydev)
|
|
{
|
|
jlsemi_set_bits(phydev, JL1XXX_PAGE129,
|
|
JL1XXX_WOL_CTRL_REG, JL1XXX_WOL_CLEAR);
|
|
|
|
jlsemi_clear_bits(phydev, JL1XXX_PAGE129,
|
|
JL1XXX_WOL_CTRL_REG, JL1XXX_WOL_CLEAR);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static bool jl1xxx_wol_receive_check(struct phy_device *phydev)
|
|
{
|
|
if (jlsemi_fetch_bit(phydev, JL1XXX_PAGE129,
|
|
JL1XXX_WOL_CTRL_REG, JL1xxx_WOL_RECEIVE))
|
|
return true;
|
|
else
|
|
return false;
|
|
|
|
}
|
|
|
|
static int jl1xxx_wol_enable(struct phy_device *phydev, bool enable)
|
|
{
|
|
if (enable)
|
|
jlsemi_clear_bits(phydev, JL1XXX_PAGE129,
|
|
JL1XXX_WOL_CTRL_REG, JL1XXX_WOL_DIS);
|
|
else
|
|
jlsemi_set_bits(phydev, JL1XXX_PAGE129,
|
|
JL1XXX_WOL_CTRL_REG, JL1XXX_WOL_DIS);
|
|
|
|
return 0;
|
|
}
|
|
static int jl1xxx_wol_store_mac_addr(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
jlsemi_write_page(phydev, JL1XXX_PAGE129);
|
|
|
|
/* Store the device address for the magic packet */
|
|
err = phy_write(phydev, JL1XXX_MAC_ADDR2_REG,
|
|
((ADDR8_HIGH_TO_LOW(
|
|
phydev->attached_dev->dev_addr[0]) << 8) |
|
|
ADDR8_HIGH_TO_LOW(
|
|
phydev->attached_dev->dev_addr[1])));
|
|
if (err < 0)
|
|
return err;
|
|
err = phy_write(phydev, JL1XXX_MAC_ADDR1_REG,
|
|
((ADDR8_HIGH_TO_LOW(
|
|
phydev->attached_dev->dev_addr[2]) << 8) |
|
|
ADDR8_HIGH_TO_LOW(
|
|
phydev->attached_dev->dev_addr[3])));
|
|
if (err < 0)
|
|
return err;
|
|
err = phy_write(phydev, JL1XXX_MAC_ADDR0_REG,
|
|
((ADDR8_HIGH_TO_LOW(
|
|
phydev->attached_dev->dev_addr[4]) << 8) |
|
|
ADDR8_HIGH_TO_LOW(
|
|
phydev->attached_dev->dev_addr[5])));
|
|
if (err < 0)
|
|
return err;
|
|
|
|
/* change page to 0 */
|
|
jlsemi_write_page(phydev, JL1XXX_PAGE0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_wol_enable(struct phy_device *phydev, bool enable)
|
|
{
|
|
if (enable) {
|
|
jlsemi_set_bits(phydev, JL2XXX_WOL_CTRL_PAGE,
|
|
JL2XXX_WOL_CTRL_REG, JL2XXX_WOL_GLB_EN);
|
|
jlsemi_clear_bits(phydev, JL2XXX_WOL_STAS_PAGE,
|
|
JL2XXX_WOL_STAS_REG, JL2XXX_WOL_EN);
|
|
} else {
|
|
jlsemi_clear_bits(phydev, JL2XXX_WOL_CTRL_PAGE,
|
|
JL2XXX_WOL_CTRL_REG, JL2XXX_WOL_GLB_EN);
|
|
jlsemi_set_bits(phydev, JL2XXX_WOL_STAS_PAGE,
|
|
JL2XXX_WOL_STAS_REG, JL2XXX_WOL_EN);
|
|
}
|
|
jlsemi_soft_reset(phydev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_wol_active_low_polarity(struct phy_device *phydev, bool low)
|
|
{
|
|
if (low)
|
|
jlsemi_set_bits(phydev, JL2XXX_WOL_STAS_PAGE,
|
|
JL2XXX_WOL_STAS_REG, JL2XXX_WOL_POLARITY);
|
|
else
|
|
jlsemi_clear_bits(phydev, JL2XXX_WOL_STAS_PAGE,
|
|
JL2XXX_WOL_STAS_REG, JL2XXX_WOL_POLARITY);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_wol_clear(struct phy_device *phydev)
|
|
{
|
|
jlsemi_set_bits(phydev, JL2XXX_WOL_STAS_PAGE,
|
|
JL2XXX_WOL_STAS_REG, JL2XXX_WOL_EVENT);
|
|
jlsemi_clear_bits(phydev, JL2XXX_WOL_STAS_PAGE,
|
|
JL2XXX_WOL_STAS_REG, JL2XXX_WOL_EVENT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_store_mac_addr(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
jlsemi_write_page(phydev, JL2XXX_WOL_STAS_PAGE);
|
|
|
|
/* Store the device address for the magic packet */
|
|
err = phy_write(phydev, JL2XXX_MAC_ADDR2_REG,
|
|
((phydev->attached_dev->dev_addr[0] << 8) |
|
|
phydev->attached_dev->dev_addr[1]));
|
|
if (err < 0)
|
|
return err;
|
|
err = phy_write(phydev, JL2XXX_MAC_ADDR1_REG,
|
|
((phydev->attached_dev->dev_addr[2] << 8) |
|
|
phydev->attached_dev->dev_addr[3]));
|
|
if (err < 0)
|
|
return err;
|
|
err = phy_write(phydev, JL2XXX_MAC_ADDR0_REG,
|
|
((phydev->attached_dev->dev_addr[4] << 8) |
|
|
phydev->attached_dev->dev_addr[5]));
|
|
if (err < 0)
|
|
return err;
|
|
|
|
/* change page to 0 */
|
|
jlsemi_write_page(phydev, JL2XXX_PAGE0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Get fast link down for jl2xxx */
|
|
#if (JL2XXX_PHY_TUNABLE)
|
|
int jl2xxx_fld_dynamic_op_get(struct phy_device *phydev, u8 *msecs)
|
|
{
|
|
int ret;
|
|
u16 val;
|
|
|
|
ret = jlsemi_read_paged(phydev, JL2XXX_PAGE128,
|
|
JL2XXX_FLD_CTRL_REG);
|
|
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (ret & JL2XXX_FLD_EN) {
|
|
*msecs = ETHTOOL_PHY_FAST_LINK_DOWN_OFF;
|
|
return 0;
|
|
}
|
|
|
|
val = (ret & JL2XXX_FLD_MASK) >> JL2XXX_FLD_MASK_HEAD;
|
|
|
|
switch (val) {
|
|
case JL2XXX_FLD_DELAY_00MS:
|
|
*msecs = 0;
|
|
break;
|
|
case JL2XXX_FLD_DELAY_10MS:
|
|
*msecs = 10;
|
|
break;
|
|
case JL2XXX_FLD_DELAY_20MS:
|
|
*msecs = 20;
|
|
break;
|
|
case JL2XXX_FLD_DELAY_40MS:
|
|
*msecs = 40;
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
/* Set fast link down for jl2xxx */
|
|
int jl2xxx_fld_dynamic_op_set(struct phy_device *phydev, const u8 *msecs)
|
|
{
|
|
u16 val;
|
|
int ret;
|
|
|
|
#if (JL2XXX_PHY_TUNABLE)
|
|
if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
|
|
return jlsemi_clear_bits(phydev, JL2XXX_PAGE128,
|
|
JL2XXX_FLD_CTRL_REG,
|
|
JL2XXX_FLD_EN);
|
|
#endif
|
|
if (*msecs <= 5)
|
|
val = JL2XXX_FLD_DELAY_00MS;
|
|
else if (*msecs <= 15)
|
|
val = JL2XXX_FLD_DELAY_10MS;
|
|
else if (*msecs <= 30)
|
|
val = JL2XXX_FLD_DELAY_20MS;
|
|
else
|
|
val = JL2XXX_FLD_DELAY_40MS;
|
|
|
|
val = val << JL2XXX_FLD_MASK_HEAD;
|
|
|
|
ret = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE128,
|
|
JL2XXX_FLD_CTRL_REG,
|
|
JL2XXX_FLD_MASK, val);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
ret = jlsemi_set_bits(phydev, JL2XXX_PAGE128,
|
|
JL2XXX_FLD_CTRL_REG,
|
|
JL2XXX_FLD_EN);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_downshift_dynamic_op_get(struct phy_device *phydev, u8 *data)
|
|
{
|
|
int val, cnt, enable;
|
|
|
|
val = jlsemi_read_paged(phydev, JL2XXX_PAGE0,
|
|
JL2XXX_DSFT_CTRL_REG);
|
|
|
|
if (val < 0)
|
|
return val;
|
|
|
|
enable = val & JL2XXX_DSFT_EN;
|
|
cnt = (val & JL2XXX_DSFT_AN_MASK) + 1;
|
|
|
|
#if (JL2XXX_PHY_TUNABLE)
|
|
*data = enable ? cnt : DOWNSHIFT_DEV_DISABLE;
|
|
#else
|
|
*data = enable ? cnt : 0;
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_downshift_dynamic_op_set(struct phy_device *phydev, u8 cnt)
|
|
{
|
|
int val, err;
|
|
|
|
if (cnt > JL2XXX_DSFT_CNT_MAX)
|
|
return -E2BIG;
|
|
|
|
if (!cnt) {
|
|
err = jlsemi_clear_bits(phydev, JL2XXX_PAGE0,
|
|
JL2XXX_DSFT_CTRL_REG,
|
|
JL2XXX_DSFT_EN);
|
|
} else {
|
|
val = ((cnt - 1) & JL2XXX_DSFT_AN_MASK) | JL2XXX_DSFT_EN |
|
|
JL2XXX_DSFT_SMART_EN | JL2XXX_DSFT_AN_ERR_EN |
|
|
JL2XXX_DSFT_STL_CNT(18);
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE0,
|
|
JL2XXX_DSFT_CTRL_REG,
|
|
JL2XXX_DSFT_AN_MASK, val);
|
|
}
|
|
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_downshift_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
err = jl2xxx_downshift_dynamic_op_set(phydev,
|
|
priv->downshift.count);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_rgmii_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if (priv->rgmii.enable & JL2XXX_RGMII_TX_DLY_EN) {
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE3336,
|
|
JL2XXX_RGMII_CTRL_REG,
|
|
priv->rgmii.tx_delay);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
} else {
|
|
err = jlsemi_clear_bits(phydev, JL2XXX_PAGE3336,
|
|
JL2XXX_RGMII_CTRL_REG,
|
|
priv->rgmii.tx_delay);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->rgmii.enable & JL2XXX_RGMII_RX_DLY_EN) {
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE3336,
|
|
JL2XXX_RGMII_CTRL_REG,
|
|
priv->rgmii.rx_delay);
|
|
if (err < 0)
|
|
return err;
|
|
} else {
|
|
err = jlsemi_clear_bits(phydev, JL2XXX_PAGE3336,
|
|
JL2XXX_RGMII_CTRL_REG,
|
|
priv->rgmii.rx_delay);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
err = jlsemi_soft_reset(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_clk_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if (priv->clk.enable & JL2XXX_125M_CLK_OUT_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE2627,
|
|
JL2XXX_CLK_CTRL_REG,
|
|
JL2XXX_CLK_SSC_EN,
|
|
JL2XXX_CLK_OUT_PIN |
|
|
JL2XXX_CLK_125M_OUT |
|
|
JL2XXXX_CLK_SRC);
|
|
if (err < 0)
|
|
return err;
|
|
} else if (priv->clk.enable & JL2XXX_25M_CLK_OUT_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE2627,
|
|
JL2XXX_CLK_CTRL_REG,
|
|
JL2XXX_CLK_SSC_EN |
|
|
JL2XXX_CLK_125M_OUT,
|
|
JL2XXX_CLK_OUT_PIN |
|
|
JL2XXXX_CLK_SRC);
|
|
if (err < 0)
|
|
return err;
|
|
} else if (priv->clk.enable & JL2XXX_CLK_OUT_DIS) {
|
|
err = jlsemi_clear_bits(phydev, JL2XXX_PAGE2627,
|
|
JL2XXX_CLK_CTRL_REG,
|
|
JL2XXX_CLK_OUT_PIN);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
err = jlsemi_soft_reset(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_slew_rate_static_op_set(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE258,
|
|
JL2XXX_SLEW_RATE_CTRL_REG,
|
|
JL2XXX_SLEW_RATE_EN | JL2XXX_SLEW_RATE_REF_CLK |
|
|
JL2XXX_SLEW_RATE_SEL_CLK);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_rxc_out_static_op_set(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE18,
|
|
JL2XXX_RXC_OUT_REG, JL2XXX_RXC_OUT);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_soft_reset(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_work_mode_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE18,
|
|
JL2XXX_WORK_MODE_REG,
|
|
JL2XXX_WORK_MODE_MASK,
|
|
priv->work_mode.mode);
|
|
|
|
err = jlsemi_soft_reset(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline int __genphy_setup_forced(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
int ctl = 0;
|
|
|
|
phydev->pause = phydev->asym_pause = 0;
|
|
|
|
if (phydev->speed == SPEED_1000)
|
|
ctl |= BMCR_SPEED1000;
|
|
else if (phydev->speed == SPEED_100)
|
|
ctl |= BMCR_SPEED100;
|
|
|
|
if (phydev->duplex == DUPLEX_FULL)
|
|
ctl |= BMCR_FULLDPLX;
|
|
|
|
err = phy_write(phydev, MII_BMCR, ctl);
|
|
|
|
return err;
|
|
}
|
|
|
|
int jl2xxx_config_aneg_fiber(struct phy_device *phydev)
|
|
{
|
|
if (phydev->autoneg != AUTONEG_ENABLE)
|
|
return __genphy_setup_forced(phydev);
|
|
|
|
/* Dou to fiber auto mode only support 1000M,
|
|
* we set 1000M speed to reg0
|
|
* NOTE: Do need restart AN otherwise will link down
|
|
*/
|
|
jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE0,
|
|
JL2XXX_BMCR_REG,
|
|
JL2XXX_BMCR_SPEED_LSB,
|
|
JL2XXX_BMCR_SPEED_MSB | BMCR_ANENABLE);
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_fiber_autoneg_config(struct phy_device *phydev)
|
|
{
|
|
int speed;
|
|
int duplex;
|
|
|
|
speed = jlsemi_read_paged(phydev, JL2XXX_PAGE0, JL2XXX_PHY_MODE_REG);
|
|
if (speed < 0)
|
|
return speed;
|
|
|
|
duplex = jlsemi_fetch_bit(phydev, JL2XXX_PAGE0,
|
|
MII_BMCR, JL2XXX_BMCR_DUPLEX);
|
|
if (duplex < 0)
|
|
return duplex;
|
|
|
|
if (duplex)
|
|
phydev->duplex = DUPLEX_FULL;
|
|
else
|
|
phydev->duplex = DUPLEX_HALF;
|
|
|
|
speed &= JL2XXX_PHY_FIBER_MODE_MASK;
|
|
switch (speed) {
|
|
case JL2XXX_FIBER_1000:
|
|
phydev->speed = SPEED_1000;
|
|
break;
|
|
case JL2XXX_FIBER_100:
|
|
phydev->speed = SPEED_100;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_update_fiber_status(struct phy_device *phydev)
|
|
{
|
|
int status;
|
|
int link;
|
|
|
|
status = jlsemi_read_paged(phydev, JL2XXX_PAGE0, JL2XXX_PHY_MODE_REG);
|
|
if (status < 0)
|
|
return status;
|
|
|
|
link = status & JL2XXX_PHY_FIBER_MODE_MASK;
|
|
|
|
if (link)
|
|
phydev->link = 1;
|
|
else
|
|
phydev->link = 0;
|
|
|
|
if (phydev->autoneg == AUTONEG_ENABLE)
|
|
jl2xxx_fiber_autoneg_config(phydev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool jl2xxx_read_fiber_status(struct phy_device *phydev)
|
|
{
|
|
bool fiber_ok = false;
|
|
u16 phy_mode;
|
|
int val;
|
|
|
|
val = jlsemi_read_paged(phydev, JL2XXX_PAGE18, JL2XXX_WORK_MODE_REG);
|
|
phy_mode = val & JL2XXX_WORK_MODE_MASK;
|
|
|
|
if ((phydev->interface != PHY_INTERFACE_MODE_SGMII) &&
|
|
((phy_mode == JL2XXX_FIBER_RGMII_MODE) ||
|
|
(phy_mode == JL2XXX_UTP_FIBER_RGMII_MODE))) {
|
|
jl2xxx_update_fiber_status(phydev);
|
|
if (phydev->link)
|
|
fiber_ok = true;
|
|
}
|
|
|
|
return fiber_ok;
|
|
}
|
|
|
|
static int jl2xxx_force_speed(struct phy_device *phydev, u16 speed)
|
|
{
|
|
int err;
|
|
|
|
if (speed == JL2XXX_SPEED1000)
|
|
jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE0, MII_BMCR,
|
|
BMCR_SPEED100, BMCR_SPEED1000);
|
|
else if (speed == JL2XXX_SPEED100)
|
|
jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE0, MII_BMCR,
|
|
BMCR_SPEED1000, BMCR_SPEED100);
|
|
else if (speed == JL2XXX_SPEED10)
|
|
jlsemi_clear_bits(phydev, JL2XXX_PAGE0, MII_BMCR,
|
|
BMCR_SPEED1000 | BMCR_SPEED100);
|
|
|
|
err = jlsemi_clear_bits(phydev, JL2XXX_PAGE0, MII_BMCR,
|
|
BMCR_ANENABLE);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int jl2xxx_lpbk_force_speed(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
|
|
if (priv->lpbk.mode == JL2XXX_LPBK_PCS_1000M)
|
|
jl2xxx_force_speed(phydev, JL2XXX_SPEED1000);
|
|
else if (priv->lpbk.mode == JL2XXX_LPBK_PCS_100M)
|
|
jl2xxx_force_speed(phydev, JL2XXX_SPEED100);
|
|
else if (priv->lpbk.mode == JL2XXX_LPBK_PCS_10M)
|
|
jl2xxx_force_speed(phydev, JL2XXX_SPEED10);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_lpbk_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if ((priv->lpbk.mode == JL2XXX_LPBK_PCS_10M) ||
|
|
(priv->lpbk.mode == JL2XXX_LPBK_PCS_100M) ||
|
|
(priv->lpbk.mode == JL2XXX_LPBK_PCS_1000M)) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE0,
|
|
MII_BMCR, BMCR_LOOPBACK,
|
|
BMCR_LOOPBACK);
|
|
if (err < 0)
|
|
return err;
|
|
err = jl2xxx_lpbk_force_speed(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
} else if (priv->lpbk.mode == JL2XXX_LPBK_PMD_1000M) {
|
|
err = jlsemi_clear_bits(phydev, JL2XXX_PAGE160,
|
|
JL2XXX_REG25, JL2XXX_CPU_RESET);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
jlsemi_write_page(phydev, JL2XXX_PAGE173);
|
|
phy_write(phydev, JL2XXX_REG16, JL2XXX_LOAD_GO);
|
|
phy_write(phydev, JL2XXX_REG17, JL2XXX_LOAD_DATA0);
|
|
jlsemi_write_page(phydev, JL2XXX_PAGE0);
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE160,
|
|
JL2XXX_REG25, JL2XXX_CPU_RESET);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE0,
|
|
JL2XXX_REG20,
|
|
JL2XXX_LPBK_MODE_MASK,
|
|
JL2XXX_LPBK_PMD_MODE);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE18, JL2XXX_REG21,
|
|
JL2XXX_SPEED1000_NO_AN);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_soft_reset(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
} else if (priv->lpbk.mode == JL2XXX_LPBK_EXT_STUB_1000M) {
|
|
err = jlsemi_clear_bits(phydev, JL2XXX_PAGE160,
|
|
JL2XXX_REG25, JL2XXX_CPU_RESET);
|
|
if (err < 0)
|
|
return err;
|
|
jlsemi_write_page(phydev, JL2XXX_PAGE173);
|
|
phy_write(phydev, JL2XXX_REG16, JL2XXX_LOAD_GO);
|
|
phy_write(phydev, JL2XXX_REG17, JL2XXX_LOAD_DATA0);
|
|
jlsemi_write_page(phydev, JL2XXX_PAGE0);
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE160,
|
|
JL2XXX_REG25, JL2XXX_CPU_RESET);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_modify_paged_reg(phydev, JL2XXX_PAGE0,
|
|
JL2XXX_REG20,
|
|
JL2XXX_LPBK_MODE_MASK,
|
|
JL2XXX_LPBK_EXT_MODE);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE18, JL2XXX_REG21,
|
|
JL2XXX_SPEED1000_NO_AN);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_soft_reset(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl1xxx_mdi_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if (priv->mdi.enable & JL1XXX_MDI_RATE_EN) {
|
|
err = jlsemi_set_bits(phydev, JL1XXX_PAGE24,
|
|
JL1XXX_REG24, priv->mdi.rate);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->mdi.enable & JL1XXX_MDI_AMPLITUDE_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE24,
|
|
JL1XXX_REG24,
|
|
JL1XXX_MDI_TX_BM_MASK,
|
|
JL1XXX_MDI_TX_BM(
|
|
priv->mdi.amplitude));
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl1xxx_rmii_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if (priv->rmii.enable & JL1XXX_RMII_MODE_EN) {
|
|
err = jlsemi_set_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16, JL1XXX_RMII_MODE);
|
|
if (err < 0)
|
|
return err;
|
|
} else {
|
|
err = jlsemi_clear_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16, JL1XXX_RMII_MODE);
|
|
if (err < 0)
|
|
return err;
|
|
return 0;
|
|
}
|
|
|
|
if (priv->rmii.enable & JL1XXX_RMII_CLK_50M_INPUT_EN) {
|
|
err = jlsemi_set_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16,
|
|
JL1XXX_RMII_CLK_50M_INPUT);
|
|
if (err < 0)
|
|
return err;
|
|
} else {
|
|
err = jlsemi_clear_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16,
|
|
JL1XXX_RMII_CLK_50M_INPUT);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->rmii.enable & JL1XXX_RMII_CRS_DV_EN) {
|
|
err = jlsemi_set_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16,
|
|
JL1XXX_RMII_CRS_DV);
|
|
if (err < 0)
|
|
return err;
|
|
} else {
|
|
err = jlsemi_clear_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16,
|
|
JL1XXX_RMII_CRS_DV);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->rmii.enable & JL1XXX_RMII_TX_SKEW_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16,
|
|
JL1XXX_RMII_TX_SKEW_MASK,
|
|
JL1XXX_RMII_TX_SKEW(
|
|
priv->rmii.tx_timing));
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->rmii.enable & JL1XXX_RMII_RX_SKEW_EN) {
|
|
err = jlsemi_modify_paged_reg(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_REG16,
|
|
JL1XXX_RMII_RX_SKEW_MASK,
|
|
JL1XXX_RMII_RX_SKEW(
|
|
priv->rmii.rx_timing));
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static u16 patch_fw_versions0[] = {0x9101, 0x9107};
|
|
static u16 patch_fw_versions1[] = {0x1101};
|
|
static u16 patch_fw_versions2[] = {0x930a};
|
|
|
|
static u16 patch_version0 = 0xdef2;
|
|
static u32 init_data0[] = {
|
|
0x1f00a0, 0x1903f3, 0x1f0012, 0x150100, 0x1f00ad, 0x100000,
|
|
0x11e0c6, 0x1f00a0, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb,
|
|
0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1f00ad, 0x110000,
|
|
0x120400, 0x130093, 0x140000, 0x150193, 0x160000, 0x170213,
|
|
0x180000, 0x12040c, 0x130293, 0x140000, 0x150313, 0x160000,
|
|
0x170393, 0x180000, 0x120418, 0x130413, 0x140000, 0x150493,
|
|
0x160000, 0x170513, 0x180000, 0x120424, 0x130593, 0x140000,
|
|
0x150613, 0x160000, 0x170693, 0x180000, 0x120430, 0x130713,
|
|
0x140000, 0x150793, 0x160000, 0x171137, 0x180000, 0x12043c,
|
|
0x13006f, 0x140060, 0x15a001, 0x160113, 0x17fd41, 0x18d026,
|
|
0x120448, 0x13d406, 0x14d222, 0x1517b7, 0x160800, 0x17aa23,
|
|
0x189407, 0x120454, 0x130713, 0x1430f0, 0x1567b7, 0x160800,
|
|
0x17a423, 0x1846e7, 0x120460, 0x13a703, 0x14a587, 0x156685,
|
|
0x168f55, 0x17ac23, 0x18a4e7, 0x12046c, 0x1367b9, 0x145737,
|
|
0x150800, 0x168793, 0x17ef27, 0x182023, 0x120478, 0x1374f7,
|
|
0x1407b7, 0x150800, 0x165bfc, 0x17d493, 0x180037, 0x120484,
|
|
0x13f493, 0x141f04, 0x15f793, 0x1607f7, 0x178fc5, 0x18c03e,
|
|
0x120490, 0x134702, 0x140793, 0x150210, 0x160763, 0x1700f7,
|
|
0x180793, 0x12049c, 0x130270, 0x140c63, 0x1530f7, 0x16a001,
|
|
0x1707b7, 0x180002, 0x1204a8, 0x138793, 0x146967, 0x15c83e,
|
|
0x1617b7, 0x170002, 0x188793, 0x1204b4, 0x13e567, 0x14c43e,
|
|
0x1537b7, 0x160002, 0x178793, 0x186867, 0x1204c0, 0x13c23e,
|
|
0x1447b7, 0x150002, 0x168793, 0x17e9a7, 0x1866b7, 0x1204cc,
|
|
0x130800, 0x14ca3e, 0x15a783, 0x166d86, 0x1775c1, 0x188713,
|
|
0x1204d8, 0x130ff5, 0x148ff9, 0x156735, 0x160713, 0x178007,
|
|
0x188fd9, 0x1204e4, 0x13ac23, 0x146cf6, 0x15a783, 0x1665c6,
|
|
0x175737, 0x180800, 0x1204f0, 0x136611, 0x14f793, 0x15f0f7,
|
|
0x16e793, 0x170807, 0x18ae23, 0x1204fc, 0x1364f6, 0x142783,
|
|
0x155c47, 0x169bf5, 0x172223, 0x185cf7, 0x120508, 0x13a703,
|
|
0x14f5c6, 0x158f51, 0x16ae23, 0x17f4e6, 0x180737, 0x120514,
|
|
0x130809, 0x14433c, 0x158fd1, 0x16c33c, 0x170637, 0x180800,
|
|
0x120520, 0x134a74, 0x14679d, 0x158793, 0x160e07, 0x179ae1,
|
|
0x18e693, 0x12052c, 0x130036, 0x14ca74, 0x154678, 0x1676e1,
|
|
0x178693, 0x185006, 0x120538, 0x138ff9, 0x148fd5, 0x1507c2,
|
|
0x168f6d, 0x1783c1, 0x188fd9, 0x120544, 0x13c67c, 0x140713,
|
|
0x151000, 0x160793, 0x170000, 0x189c23, 0x120550, 0x1324e7,
|
|
0x140713, 0x151010, 0x169123, 0x1726e7, 0x18470d, 0x12055c,
|
|
0x13c63a, 0x144702, 0x158d23, 0x162407, 0x17a223, 0x182607,
|
|
0x120568, 0x130793, 0x140270, 0x150413, 0x160000, 0x171463,
|
|
0x1800f7, 0x120574, 0x134789, 0x14c63e, 0x154709, 0x16cc3a,
|
|
0x174702, 0x180793, 0x120580, 0x130270, 0x141463, 0x1500f7,
|
|
0x16478d, 0x17cc3e, 0x180513, 0x12058c, 0x130000, 0x144792,
|
|
0x154581, 0x164485, 0x179782, 0x184018, 0x120598, 0x131775,
|
|
0x14e563, 0x1502e4, 0x162703, 0x170a04, 0x181163, 0x1205a4,
|
|
0x130297, 0x144818, 0x150563, 0x160097, 0x1747a2, 0x18c804,
|
|
0x1205b0, 0x139782, 0x1466b7, 0x150800, 0x16a703, 0x174c46,
|
|
0x189b71, 0x1205bc, 0x136713, 0x140027, 0x15a223, 0x164ce6,
|
|
0x174783, 0x180fd4, 0x1205c8, 0x13c7b9, 0x142683, 0x151004,
|
|
0x164745, 0x179763, 0x1820e6, 0x1205d4, 0x133737, 0x140822,
|
|
0x152683, 0x163007, 0x177645, 0x18167d, 0x1205e0, 0x138ef1,
|
|
0x142023, 0x1530d7, 0x162683, 0x172807, 0x18e693, 0x1205ec,
|
|
0x131006, 0x142023, 0x1528d7, 0x162683, 0x173807, 0x18e693,
|
|
0x1205f8, 0x131006, 0x142023, 0x1538d7, 0x162683, 0x174007,
|
|
0x18e693, 0x120604, 0x131006, 0x142023, 0x1540d7, 0x162683,
|
|
0x174807, 0x18e693, 0x120610, 0x131006, 0x142023, 0x1548d7,
|
|
0x1656b7, 0x170800, 0x18a703, 0x12061c, 0x133486, 0x14830d,
|
|
0x158b05, 0x16cf01, 0x17a703, 0x185c46, 0x120628, 0x137671,
|
|
0x14167d, 0x158f71, 0x166611, 0x17a223, 0x185ce6, 0x120634,
|
|
0x138f51, 0x14a223, 0x155ce6, 0x162703, 0x171084, 0x1846b2,
|
|
0x120640, 0x131c63, 0x1402d7, 0x153737, 0x160822, 0x172683,
|
|
0x182807, 0x12064c, 0x13e693, 0x140016, 0x152023, 0x1628d7,
|
|
0x172683, 0x183807, 0x120658, 0x13e693, 0x140016, 0x152023,
|
|
0x1638d7, 0x172683, 0x184007, 0x120664, 0x13e693, 0x140016,
|
|
0x152023, 0x1640d7, 0x172683, 0x184807, 0x120670, 0x13e693,
|
|
0x140016, 0x152023, 0x1648d7, 0x172703, 0x181004, 0x12067c,
|
|
0x1346b2, 0x149c63, 0x151ae6, 0x160737, 0x170800, 0x184b78,
|
|
0x120688, 0x130693, 0x140ff0, 0x15463d, 0x168b1d, 0x17ce3a,
|
|
0x1852b7, 0x120694, 0x130800, 0x144701, 0x154389, 0x16408d,
|
|
0x174311, 0x180537, 0x1206a0, 0x130820, 0x141593, 0x150077,
|
|
0x1695aa, 0x17418c, 0x184572, 0x1206ac, 0x1305c2, 0x1481c1,
|
|
0x1581a9, 0x167763, 0x1700b5, 0x189533, 0x1206b8, 0x1300e4,
|
|
0x144513, 0x15fff5, 0x168e69, 0x170537, 0x180800, 0x1206c4,
|
|
0x134568, 0x148121, 0x15893d, 0x167463, 0x1702b5, 0x18a583,
|
|
0x1206d0, 0x1306c2, 0x140763, 0x151277, 0x160a63, 0x171217,
|
|
0x1805c2, 0x1206dc, 0x1381c1, 0x14818d, 0x150d63, 0x161097,
|
|
0x178985, 0x180586, 0x1206e8, 0x1395b3, 0x1400b4, 0x15c593,
|
|
0x16fff5, 0x178eed, 0x180705, 0x1206f4, 0x1315e3, 0x14fa67,
|
|
0x1535b7, 0x160822, 0x17a703, 0x183005, 0x120700, 0x13757d,
|
|
0x148a3d, 0x150513, 0x160ff5, 0x178f69, 0x180622, 0x12070c,
|
|
0x138e59, 0x14a023, 0x1530c5, 0x168637, 0x170800, 0x185a38,
|
|
0x120718, 0x1375c1, 0x14f693, 0x150ff6, 0x168593, 0x170ff5,
|
|
0x188f6d, 0x120724, 0x1306a2, 0x148ed9, 0x15da34, 0x164682,
|
|
0x170713, 0x180210, 0x120730, 0x139163, 0x140ee6, 0x154711,
|
|
0x16e391, 0x17471d, 0x182023, 0x12073c, 0x1310e4, 0x142683,
|
|
0x150a04, 0x16471d, 0x179e63, 0x1800e6, 0x120748, 0x136737,
|
|
0x140800, 0x152703, 0x164cc7, 0x170693, 0x184000, 0x120754,
|
|
0x137713, 0x144807, 0x151463, 0x1600d7, 0x172223, 0x180e04,
|
|
0x120760, 0x134018, 0x141163, 0x150497, 0x165703, 0x1700c4,
|
|
0x181793, 0x12076c, 0x130117, 0x14db63, 0x150207, 0x168737,
|
|
0x170800, 0x184778, 0x120778, 0x137713, 0x140807, 0x15e705,
|
|
0x160513, 0x170000, 0x184792, 0x120784, 0x134581, 0x149782,
|
|
0x1547a2, 0x164711, 0x17c818, 0x18c004, 0x120790, 0x130d23,
|
|
0x140094, 0x150ca3, 0x160004, 0x179782, 0x1856b7, 0x12079c,
|
|
0x130800, 0x1442b8, 0x159b71, 0x16c2b8, 0x170513, 0x180000,
|
|
0x1207a8, 0x1347d2, 0x149782, 0x154703, 0x162684, 0x1703e3,
|
|
0x18de07, 0x1207b4, 0x13bbd9, 0x1407b7, 0x150002, 0x168793,
|
|
0x1765c7, 0x18c83e, 0x1207c0, 0x1327b7, 0x140002, 0x158793,
|
|
0x16dae7, 0x17c43e, 0x1847b7, 0x1207cc, 0x130002, 0x148793,
|
|
0x151427, 0x16c23e, 0x1757b7, 0x180002, 0x1207d8, 0x138793,
|
|
0x149867, 0x15b1fd, 0x162683, 0x171504, 0x184709, 0x1207e4,
|
|
0x1399e3, 0x14e2e6, 0x1536b7, 0x160822, 0x17a703, 0x183006,
|
|
0x1207f0, 0x13663d, 0x148f51, 0x15a023, 0x1630e6, 0x17bd39,
|
|
0x18c593, 0x1207fc, 0x130015, 0x14b5dd, 0x158991, 0x1635b3,
|
|
0x1700b0, 0x180589, 0x120808, 0x13bdf9, 0x148991, 0x15b593,
|
|
0x160015, 0x17bfdd, 0x180737, 0x120814, 0x130800, 0x144f28,
|
|
0x15cf89, 0x1647c2, 0x17893d, 0x189782, 0x120820, 0x1347e2,
|
|
0x140713, 0x151000, 0x162223, 0x1710e4, 0x182423, 0x12082c,
|
|
0x1310f4, 0x14474d, 0x15b729, 0x168111, 0x17b7dd, 0x1814e3,
|
|
0x120838, 0x13f097, 0x140737, 0x150800, 0x164770, 0x171713,
|
|
0x180106, 0x120844, 0x135d63, 0x140607, 0x1585b7, 0x160800,
|
|
0x17a683, 0x180d05, 0x120850, 0x1372c5, 0x147313, 0x1500f6,
|
|
0x1612fd, 0x17a703, 0x180d45, 0x12085c, 0x131513, 0x1400c3,
|
|
0x15f6b3, 0x160056, 0x178ec9, 0x18757d, 0x120868, 0x130393,
|
|
0x140ff5, 0x151293, 0x160083, 0x17f6b3, 0x180076, 0x120874,
|
|
0x139b41, 0x148211, 0x15e2b3, 0x160056, 0x171093, 0x180043,
|
|
0x120880, 0x137693, 0x140016, 0x156333, 0x160067, 0x170613,
|
|
0x187ff5, 0x12088c, 0x139713, 0x1400b6, 0x157633, 0x1600c3,
|
|
0x178e59, 0x189513, 0x120898, 0x1300a6, 0x147613, 0x159ff6,
|
|
0x169713, 0x170096, 0x188e49, 0x1208a4, 0x13f293, 0x14f0f2,
|
|
0x158e59, 0x16e2b3, 0x170012, 0x1806a2, 0x1208b0, 0x137613,
|
|
0x14eff6, 0x158e55, 0x16a823, 0x170c55, 0x18aa23, 0x1208bc,
|
|
0x130cc5, 0x1480e3, 0x15e807, 0x1646b7, 0x170822, 0x18a703,
|
|
0x1208c8, 0x13f006, 0x149b61, 0x156713, 0x160027, 0x17a023,
|
|
0x18f0e6, 0x1208d4, 0x13b5ad, 0x140000, 0x150000, 0x160000,
|
|
0x170000, 0x180000, 0x110000, 0x120400, 0x104000, 0x1f0000,
|
|
};
|
|
|
|
static u16 patch_version1 = 0x9f73;
|
|
static u32 init_data1[] = {
|
|
0x1f00a0, 0x1903f3, 0x1f0012, 0x150100, 0x1f00ad, 0x100000,
|
|
0x11e0c6, 0x1f00a0, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb,
|
|
0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1f00ad, 0x110000,
|
|
0x120400, 0x130093, 0x140000, 0x150193, 0x160000, 0x170213,
|
|
0x180000, 0x12040c, 0x130293, 0x140000, 0x150313, 0x160000,
|
|
0x170393, 0x180000, 0x120418, 0x130413, 0x140000, 0x150493,
|
|
0x160000, 0x170513, 0x180000, 0x120424, 0x130593, 0x140000,
|
|
0x150613, 0x160000, 0x170693, 0x180000, 0x120430, 0x130713,
|
|
0x140000, 0x150793, 0x160000, 0x171137, 0x180000, 0x12043c,
|
|
0x13006f, 0x140060, 0x15a001, 0x161111, 0x17cc06, 0x18ca22,
|
|
0x120448, 0x13c826, 0x1417b7, 0x150800, 0x16aa23, 0x179407,
|
|
0x180713, 0x120454, 0x1330f0, 0x1467b7, 0x150800, 0x16a423,
|
|
0x1746e7, 0x18a703, 0x120460, 0x13a587, 0x146685, 0x158f55,
|
|
0x16ac23, 0x17a4e7, 0x1867a9, 0x12046c, 0x135737, 0x140800,
|
|
0x158793, 0x16f737, 0x172023, 0x1874f7, 0x120478, 0x1307b7,
|
|
0x140800, 0x155bf8, 0x165793, 0x170037, 0x18f793, 0x120484,
|
|
0x131f07, 0x147713, 0x1507f7, 0x168fd9, 0x170713, 0x180210,
|
|
0x120490, 0x138763, 0x1400e7, 0x150713, 0x160270, 0x178263,
|
|
0x181ce7, 0x12049c, 0x13a001, 0x141437, 0x150002, 0x160793,
|
|
0x17e564, 0x18c43e, 0x1204a8, 0x1337b7, 0x140002, 0x158793,
|
|
0x166867, 0x17c23e, 0x1847b7, 0x1204b4, 0x130002, 0x148793,
|
|
0x15e9a7, 0x16c63e, 0x1767b7, 0x180800, 0x1204c0, 0x13a703,
|
|
0x146d87, 0x1576c1, 0x168693, 0x170ff6, 0x188f75, 0x1204cc,
|
|
0x1366b5, 0x148693, 0x158006, 0x168f55, 0x17ac23, 0x186ce7,
|
|
0x1204d8, 0x13a703, 0x1465c7, 0x1556b7, 0x160800, 0x177713,
|
|
0x18f0f7, 0x1204e4, 0x136713, 0x140807, 0x15ae23, 0x1664e7,
|
|
0x17a703, 0x185c46, 0x1204f0, 0x130413, 0x140000, 0x159b75,
|
|
0x16a223, 0x175ce6, 0x18a703, 0x1204fc, 0x13f5c7, 0x146691,
|
|
0x158f55, 0x16ae23, 0x17f4e7, 0x180737, 0x120508, 0x130809,
|
|
0x14433c, 0x158fd5, 0x16c33c, 0x170793, 0x180000, 0x120514,
|
|
0x130713, 0x141000, 0x159c23, 0x1624e7, 0x170713, 0x181010,
|
|
0x120520, 0x138d23, 0x142407, 0x159123, 0x1626e7, 0x17a223,
|
|
0x182607, 0x12052c, 0x13c026, 0x144782, 0x154581, 0x164485,
|
|
0x170513, 0x180000, 0x120538, 0x134792, 0x149782, 0x154018,
|
|
0x161775, 0x17e563, 0x1802e4, 0x120544, 0x132703, 0x140a04,
|
|
0x151163, 0x160297, 0x174818, 0x180563, 0x120550, 0x130097,
|
|
0x1447a2, 0x15c804, 0x169782, 0x176637, 0x180800, 0x12055c,
|
|
0x132703, 0x144c46, 0x159b71, 0x166713, 0x170027, 0x182223,
|
|
0x120568, 0x134ce6, 0x144703, 0x150fd4, 0x16c739, 0x172603,
|
|
0x181004, 0x120574, 0x134745, 0x141263, 0x1510e6, 0x163737,
|
|
0x170822, 0x182603, 0x120580, 0x133007, 0x1475c5, 0x1515fd,
|
|
0x168e6d, 0x172023, 0x1830c7, 0x12058c, 0x132603, 0x142807,
|
|
0x156613, 0x161006, 0x172023, 0x1828c7, 0x120598, 0x132603,
|
|
0x143807, 0x156613, 0x161006, 0x172023, 0x1838c7, 0x1205a4,
|
|
0x132603, 0x144007, 0x156613, 0x161006, 0x172023, 0x1840c7,
|
|
0x1205b0, 0x132603, 0x144807, 0x156613, 0x161006, 0x172023,
|
|
0x1848c7, 0x1205bc, 0x135637, 0x140800, 0x152703, 0x163486,
|
|
0x17830d, 0x188b05, 0x1205c8, 0x13cf01, 0x142703, 0x155c46,
|
|
0x1675f1, 0x1715fd, 0x188f6d, 0x1205d4, 0x136591, 0x142223,
|
|
0x155ce6, 0x168f4d, 0x172223, 0x185ce6, 0x1205e0, 0x132603,
|
|
0x140a04, 0x15471d, 0x161e63, 0x1700e6, 0x186737, 0x1205ec,
|
|
0x130800, 0x142703, 0x154cc7, 0x160613, 0x174000, 0x187713,
|
|
0x1205f8, 0x134807, 0x141463, 0x1500c7, 0x162223, 0x170e04,
|
|
0x184018, 0x120604, 0x131263, 0x140497, 0x155703, 0x1600c4,
|
|
0x171793, 0x180117, 0x120610, 0x13dc63, 0x140207, 0x158737,
|
|
0x160800, 0x174778, 0x187713, 0x12061c, 0x130807, 0x14e70d,
|
|
0x154782, 0x164581, 0x170513, 0x180000, 0x120628, 0x134792,
|
|
0x149782, 0x1547a2, 0x164711, 0x17c818, 0x18c004, 0x120634,
|
|
0x130d23, 0x140094, 0x150ca3, 0x160004, 0x179782, 0x185637,
|
|
0x120640, 0x130800, 0x144238, 0x159b71, 0x16c238, 0x174782,
|
|
0x180513, 0x12064c, 0x130000, 0x1447b2, 0x159782, 0x164703,
|
|
0x172684, 0x1803e3, 0x120658, 0x13ee07, 0x14bdd1, 0x152437,
|
|
0x160002, 0x170793, 0x18dae4, 0x120664, 0x13c43e, 0x1447b7,
|
|
0x150002, 0x168793, 0x171427, 0x18c23e, 0x120670, 0x1357b7,
|
|
0x140002, 0x158793, 0x169867, 0x17b589, 0x182603, 0x12067c,
|
|
0x131504, 0x144709, 0x151ee3, 0x16f2e6, 0x173637, 0x180822,
|
|
0x120688, 0x132703, 0x143006, 0x1565bd, 0x168f4d, 0x172023,
|
|
0x1830e6, 0x120694, 0x13b725, 0x140000, 0x150000, 0x160000,
|
|
0x170000, 0x180000, 0x110000, 0x120400, 0x104000, 0x1f0000,
|
|
};
|
|
|
|
static u16 patch_version2 = 0x2e9c;
|
|
static u32 init_data2[] = {
|
|
0x1f00a0, 0x1903f3, 0x1f0012, 0x150100, 0x1f00ad, 0x100000,
|
|
0x11e0c6, 0x1f0102, 0x199000, 0x1f00a0, 0x1903fb, 0x1903fb,
|
|
0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb, 0x1903fb,
|
|
0x1f00ad, 0x110000, 0x121000, 0x13937c, 0x140120, 0x15675e,
|
|
0x16fca8, 0x1706b7, 0x180800, 0x12100c, 0x135af8, 0x145793,
|
|
0x150037, 0x16f793, 0x171f07, 0x187713, 0x121018, 0x1307f7,
|
|
0x148fd9, 0x150713, 0x1606a0, 0x179b63, 0x1808e7, 0x121024,
|
|
0x13cd19, 0x141121, 0x15c822, 0x16ca06, 0x17c626, 0x184789,
|
|
0x121030, 0x13842e, 0x140963, 0x152cf5, 0x1640d2, 0x174442,
|
|
0x1844b2, 0x12103c, 0x134501, 0x140161, 0x158082, 0x1617b7,
|
|
0x170800, 0x18aa23, 0x121048, 0x139407, 0x1467b7, 0x150800,
|
|
0x16a703, 0x17a587, 0x186605, 0x121054, 0x138f51, 0x14ac23,
|
|
0x15a4e7, 0x16670d, 0x170713, 0x18e9c7, 0x121060, 0x135637,
|
|
0x140800, 0x152023, 0x1674e6, 0x174ab8, 0x186713, 0x12106c,
|
|
0x130407, 0x14cab8, 0x15a703, 0x164d47, 0x1776fd, 0x188693,
|
|
0x121078, 0x1303f6, 0x148f75, 0x156713, 0x162807, 0x17aa23,
|
|
0x184ce7, 0x121084, 0x13a703, 0x147587, 0x157713, 0x16e1f7,
|
|
0x176713, 0x180607, 0x121090, 0x13ac23, 0x1474e7, 0x15a703,
|
|
0x164f47, 0x177713, 0x18f0f7, 0x12109c, 0x136713, 0x140107,
|
|
0x15aa23, 0x164ee7, 0x17a703, 0x18fc07, 0x1210a8, 0x139b5d,
|
|
0x14a023, 0x15fce7, 0x160713, 0x170300, 0x18a223, 0x1210b4,
|
|
0x13a6e7, 0x144501, 0x158082, 0x166489, 0x179023, 0x180004,
|
|
0x1210c0, 0x134505, 0x142ebd, 0x1557fd, 0x16c49c, 0x17c4dc,
|
|
0x184783, 0x1210cc, 0x130ec4, 0x149363, 0x152407, 0x16b795,
|
|
0x1787b7, 0x180800, 0x1210d8, 0x13a583, 0x140dc7, 0x15a783,
|
|
0x160e07, 0x178b91, 0x188063, 0x1210e4, 0x131807, 0x14d793,
|
|
0x150085, 0x1681b9, 0x178bbd, 0x188985, 0x1210f0, 0x1386b7,
|
|
0x140800, 0x15a703, 0x160d06, 0x17833e, 0x189513, 0x1210fc,
|
|
0x1300c7, 0x1477c5, 0x1517fd, 0x168f7d, 0x178f49, 0x18757d,
|
|
0x121108, 0x130293, 0x140ff5, 0x15a603, 0x160d46, 0x171793,
|
|
0x180083, 0x121114, 0x137733, 0x140057, 0x158f5d, 0x167713,
|
|
0x17f0f7, 0x181793, 0x121120, 0x130043, 0x148f5d, 0x157793,
|
|
0x16ff06, 0x170513, 0x187ff5, 0x12112c, 0x13e7b3, 0x140067,
|
|
0x159613, 0x1600b5, 0x178fe9, 0x188fd1, 0x121138, 0x139513,
|
|
0x1400a5, 0x15f793, 0x169ff7, 0x179613, 0x180095, 0x121144,
|
|
0x138fc9, 0x148fd1, 0x1505a2, 0x16f793, 0x17eff7, 0x188fcd,
|
|
0x121150, 0x13a823, 0x140ce6, 0x15aa23, 0x160cf6, 0x172783,
|
|
0x180f04, 0x12115c, 0x134719, 0x148563, 0x1500e7, 0x16472d,
|
|
0x179263, 0x1810e7, 0x121168, 0x130493, 0x141104, 0x154701,
|
|
0x164781, 0x17d683, 0x180104, 0x121174, 0x13e2b5, 0x1446a1,
|
|
0x154701, 0x16853e, 0x17c436, 0x18c23a, 0x121180, 0x13c03e,
|
|
0x142ca9, 0x1546a2, 0x164712, 0x174782, 0x1816fd, 0x12118c,
|
|
0x13972a, 0x14f6f5, 0x150637, 0x160820, 0x175693, 0x184037,
|
|
0x121198, 0x139713, 0x140077, 0x159732, 0x164310, 0x17d703,
|
|
0x180004, 0x1211a4, 0x139963, 0x1422e6, 0x159593, 0x160017,
|
|
0x176709, 0x18972e, 0x1211b0, 0x135703, 0x140087, 0x157e63,
|
|
0x1600e6, 0x17d703, 0x180184, 0x1211bc, 0x139023, 0x1400d4,
|
|
0x159693, 0x160017, 0x179423, 0x1800e4, 0x1211c8, 0x136709,
|
|
0x149736, 0x151423, 0x1600c7, 0x17d703, 0x180184, 0x1211d4,
|
|
0x133713, 0x140017, 0x150785, 0x164691, 0x170489, 0x1899e3,
|
|
0x1211e0, 0x13f8d7, 0x1447b5, 0x151f63, 0x161807, 0x176785,
|
|
0x1897a2, 0x1211ec, 0x13a703, 0x14a687, 0x154791, 0x160b63,
|
|
0x1718f7, 0x186489, 0x1211f8, 0x13d783, 0x140004, 0x159de3,
|
|
0x16e207, 0x172703, 0x180f04, 0x121204, 0x134789, 0x1418e3,
|
|
0x15e2f7, 0x164505, 0x172c15, 0x185637, 0x121210, 0x130800,
|
|
0x1446b7, 0x150822, 0x164238, 0x17a783, 0x18f806, 0x12121c,
|
|
0x133537, 0x140822, 0x1575c1, 0x16f793, 0x178ff7, 0x18e793,
|
|
0x121228, 0x133007, 0x14a023, 0x15f8f6, 0x162683, 0x173805,
|
|
0x188593, 0x121234, 0x130ff5, 0x14d793, 0x150086, 0x168b85,
|
|
0x17e793, 0x180767, 0x121240, 0x138eed, 0x1407a2, 0x158fd5,
|
|
0x162023, 0x1738f5, 0x187793, 0x12124c, 0x13ffd7, 0x14c23c,
|
|
0x15e793, 0x160027, 0x17c23c, 0x1847c1, 0x121258, 0x139023,
|
|
0x1400f4, 0x154501, 0x1622cd, 0x17bbd9, 0x184585, 0x121264,
|
|
0x134791, 0x14b569, 0x15476d, 0x169fe3, 0x17f6e7, 0x180737,
|
|
0x121270, 0x130002, 0x144481, 0x150713, 0x160a67, 0x178793,
|
|
0x184b84, 0x12127c, 0x130786, 0x1497a2, 0x15d683, 0x160ee7,
|
|
0x178526, 0x180485, 0x121288, 0x13e693, 0x140026, 0x159723,
|
|
0x160ed7, 0x179702, 0x180737, 0x121294, 0x130002, 0x144791,
|
|
0x150713, 0x160a67, 0x179ee3, 0x18fcf4, 0x1212a0, 0x130493,
|
|
0x141000, 0x154501, 0x1614fd, 0x172a15, 0x18fced, 0x1212ac,
|
|
0x134785, 0x148526, 0x15c03e, 0x16222d, 0x17470d, 0x184782,
|
|
0x1212b8, 0x135363, 0x1400a7, 0x154781, 0x160485, 0x174711,
|
|
0x1896e3, 0x1212c4, 0x13fee4, 0x14c38d, 0x156789, 0x164749,
|
|
0x179023, 0x1800e7, 0x1212d0, 0x1347c5, 0x142c23, 0x150ef4,
|
|
0x160793, 0x171000, 0x182a23, 0x1212dc, 0x130ef4, 0x1445d1,
|
|
0x150513, 0x160ec4, 0x172a15, 0x18b709, 0x1212e8, 0x136705,
|
|
0x149722, 0x155783, 0x16a5a7, 0x1746a1, 0x180785, 0x1212f4,
|
|
0x1307c2, 0x1483c1, 0x15f963, 0x1602f6, 0x171d23, 0x18a407,
|
|
0x121300, 0x132823, 0x140e04, 0x154783, 0x160ec4, 0x1789e3,
|
|
0x18da07, 0x12130c, 0x132783, 0x140f04, 0x1585e3, 0x16da07,
|
|
0x172783, 0x180f04, 0x121318, 0x138ee3, 0x14da07, 0x154741,
|
|
0x169de3, 0x17e2e7, 0x1847ed, 0x121324, 0x132823, 0x140ef4,
|
|
0x15bd05, 0x1606b7, 0x170002, 0x181d23, 0x121330, 0x13a4f7,
|
|
0x144481, 0x158693, 0x160a66, 0x178793, 0x184b84, 0x12133c,
|
|
0x130786, 0x1497a2, 0x15d703, 0x160ee7, 0x178526, 0x189b75,
|
|
0x121348, 0x139723, 0x140ee7, 0x159682, 0x160737, 0x170820,
|
|
0x189793, 0x121354, 0x130074, 0x140713, 0x152007, 0x1697ba,
|
|
0x17a023, 0x180007, 0x121360, 0x130737, 0x140002, 0x150485,
|
|
0x164791, 0x170693, 0x180a67, 0x12136c, 0x1396e3, 0x14fcf4,
|
|
0x150737, 0x160828, 0x172783, 0x184807, 0x121378, 0x13e793,
|
|
0x140207, 0x152023, 0x1648f7, 0x1747b9, 0x182823, 0x121384,
|
|
0x130ef4, 0x14b58d, 0x156709, 0x165683, 0x170007, 0x1847c9,
|
|
0x121390, 0x1393e3, 0x14e6f6, 0x1547b7, 0x160800, 0x17a783,
|
|
0x180c87, 0x12139c, 0x130693, 0x141000, 0x1507c2, 0x1683c1,
|
|
0x17f663, 0x1802f6, 0x1213a8, 0x135783, 0x140027, 0x150785,
|
|
0x1607c2, 0x1783c1, 0x181123, 0x1213b4, 0x1300f7, 0x144725,
|
|
0x157fe3, 0x16c6f7, 0x1766b7, 0x180800, 0x1213c0, 0x13a783,
|
|
0x14f5c6, 0x157779, 0x16177d, 0x178ff9, 0x18ae23, 0x1213cc,
|
|
0x13f4f6, 0x14b1a5, 0x151123, 0x160007, 0x17b18d, 0x18c1e3,
|
|
0x1213d8, 0x13dee6, 0x14bbdd, 0x150737, 0x160830, 0x172783,
|
|
0x181807, 0x1213e4, 0x132703, 0x142007, 0x154685, 0x160263,
|
|
0x1702d5, 0x18c763, 0x1213f0, 0x1300a6, 0x148bfd, 0x15c111,
|
|
0x164781, 0x17853e, 0x188082, 0x1213fc, 0x134689, 0x140b63,
|
|
0x1500d5, 0x16478d, 0x1719e3, 0x18fef5, 0x121408, 0x135793,
|
|
0x140047, 0x15a011, 0x168395, 0x178bfd, 0x18b7dd, 0x121414,
|
|
0x1383a9, 0x14bfed, 0x151141, 0x16c422, 0x17c606, 0x1847d1,
|
|
0x121420, 0x13842a, 0x149a63, 0x1500f5, 0x164508, 0x1707b7,
|
|
0x180002, 0x12142c, 0x13c02e, 0x148793, 0x156687, 0x169782,
|
|
0x174582, 0x18c04c, 0x121438, 0x1340b2, 0x144422, 0x150141,
|
|
0x168082, 0x17ed09, 0x184781, 0x121444, 0x134737, 0x140822,
|
|
0x152023, 0x16d0f7, 0x172023, 0x18d8f7, 0x121450, 0x132023,
|
|
0x14e0f7, 0x152023, 0x16e8f7, 0x178082, 0x186785, 0x12145c,
|
|
0x133737, 0x140822, 0x158693, 0x16fff7, 0x172023, 0x1830d7,
|
|
0x121468, 0x132023, 0x145007, 0x152023, 0x165807, 0x172023,
|
|
0x186007, 0x121474, 0x132023, 0x146807, 0x158793, 0x16c007,
|
|
0x17b7e1, 0x180000, 0x1f00a0, 0x1903f3, 0x1903fb, 0x1f0000,
|
|
};
|
|
|
|
int jl2xxx_patch_static_op_set(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jl2xxx_pre_init(phydev, init_data0, ARRAY_SIZE(init_data0),
|
|
patch_fw_versions0,
|
|
ARRAY_SIZE(patch_fw_versions0), patch_version0);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jl2xxx_pre_init(phydev, init_data1, ARRAY_SIZE(init_data1),
|
|
patch_fw_versions1,
|
|
ARRAY_SIZE(patch_fw_versions1), patch_version1);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jl2xxx_pre_init(phydev, init_data2, ARRAY_SIZE(init_data2),
|
|
patch_fw_versions2,
|
|
ARRAY_SIZE(patch_fw_versions2), patch_version2);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if (JLSEMI_PHY_WOL)
|
|
int jl1xxx_wol_dynamic_op_get(struct phy_device *phydev)
|
|
{
|
|
return jlsemi_fetch_bit(phydev, JL1XXX_PAGE129,
|
|
JL1XXX_WOL_CTRL_REG, JL1XXX_WOL_DIS);
|
|
}
|
|
|
|
int jl2xxx_wol_dynamic_op_get(struct phy_device *phydev)
|
|
{
|
|
return jlsemi_fetch_bit(phydev, JL2XXX_WOL_CTRL_PAGE,
|
|
JL2XXX_WOL_CTRL_REG, JL2XXX_WOL_EN);
|
|
}
|
|
|
|
static int jl1xxx_wol_static_op_set(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jl1xxx_wol_dynamic_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int jl1xxx_intr_ack_event(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if (priv->intr.enable & JL1XXX_INTR_STATIC_OP_EN) {
|
|
err = phy_read(phydev, JL1XXX_INTR_STATUS_REG);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl1xxx_intr_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
int ret = 0;
|
|
|
|
if (priv->intr.enable & JL1XXX_INTR_LINK_CHANGE_EN)
|
|
ret |= JL1XXX_INTR_LINK;
|
|
if (priv->intr.enable & JL1XXX_INTR_AN_ERR_EN)
|
|
ret |= JL1XXX_INTR_AN_ERR;
|
|
|
|
err = jlsemi_set_bits(phydev, JL1XXX_PAGE7,
|
|
JL1XXX_INTR_REG, ret);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if (JLSEMI_PHY_WOL)
|
|
static int jl2xxx_wol_static_op_set(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jl2xxx_wol_dynamic_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl1xxx_wol_dynamic_op_set(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jl1xxx_wol_cfg_rmii(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jl1xxx_wol_enable(phydev, true);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jl1xxx_wol_store_mac_addr(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
if (jl1xxx_wol_receive_check(phydev)) {
|
|
err = jl1xxx_wol_clear(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_wol_dynamic_op_set(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jl2xxx_wol_enable(phydev, true);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jl2xxx_wol_clear(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jl2xxx_wol_active_low_polarity(phydev, true);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jl2xxx_store_mac_addr(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
int jl2xxx_intr_ack_event(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jlsemi_read_paged(phydev, JL2XXX_PAGE2627,
|
|
JL2XXX_INTR_STATUS_REG);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_intr_static_op_set(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
int ret = 0;
|
|
|
|
if (priv->intr.enable & JL2XXX_INTR_LINK_CHANGE_EN)
|
|
ret |= JL2XXX_INTR_LINK_CHANGE;
|
|
if (priv->intr.enable & JL2XXX_INTR_AN_ERR_EN)
|
|
ret |= JL2XXX_INTR_AN_ERR;
|
|
if (priv->intr.enable & JL2XXX_INTR_AN_COMPLETE_EN)
|
|
ret |= JL2XXX_INTR_AN_COMPLETE;
|
|
if (priv->intr.enable & JL2XXX_INTR_AN_PAGE_RECE)
|
|
ret |= JL2XXX_INTR_AN_PAGE;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE2626,
|
|
JL2XXX_INTR_CTRL_REG, ret);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE158,
|
|
JL2XXX_INTR_PIN_REG,
|
|
JL2XXX_INTR_PIN_EN);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE160,
|
|
JL2XXX_PIN_EN_REG,
|
|
JL2XXX_PIN_OUTPUT);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl1xxx_operation_args_get(struct phy_device *phydev)
|
|
{
|
|
jl1xxx_led_operation_args(phydev);
|
|
jl1xxx_wol_operation_args(phydev);
|
|
jl1xxx_intr_operation_args(phydev);
|
|
jl1xxx_mdi_operation_args(phydev);
|
|
jl1xxx_rmii_operation_args(phydev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_operation_args_get(struct phy_device *phydev)
|
|
{
|
|
jl2xxx_led_operation_args(phydev);
|
|
jl2xxx_fld_operation_args(phydev);
|
|
jl2xxx_wol_operation_args(phydev);
|
|
jl2xxx_intr_operation_args(phydev);
|
|
jl2xxx_downshift_operation_args(phydev);
|
|
jl2xxx_rgmii_operation_args(phydev);
|
|
jl2xxx_patch_operation_args(phydev);
|
|
jl2xxx_clk_operation_args(phydev);
|
|
jl2xxx_work_mode_operation_args(phydev);
|
|
jl2xxx_lpbk_operation_args(phydev);
|
|
jl2xxx_slew_rate_operation_args(phydev);
|
|
jl2xxx_rxc_out_operation_args(phydev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl1xxx_static_op_init(struct phy_device *phydev)
|
|
{
|
|
struct jl1xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if (priv->led.enable & JL1XXX_LED_STATIC_OP_EN) {
|
|
err = jl1xxx_led_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
#if (JLSEMI_PHY_WOL)
|
|
if (priv->wol.enable & JL1XXX_WOL_STATIC_OP_EN) {
|
|
err = jl1xxx_wol_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
if (priv->intr.enable & JL1XXX_INTR_STATIC_OP_EN) {
|
|
err = jl1xxx_intr_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->mdi.enable & JL1XXX_MDI_STATIC_OP_EN) {
|
|
err = jl1xxx_mdi_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->rmii.enable & JL1XXX_RMII_STATIC_OP_EN) {
|
|
err = jl1xxx_rmii_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_static_op_init(struct phy_device *phydev)
|
|
{
|
|
struct jl2xxx_priv *priv = phydev->priv;
|
|
int err;
|
|
|
|
if (priv->patch.enable & JL2XXX_PATCH_STATIC_OP_EN) {
|
|
err = jl2xxx_patch_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->led.enable & JL2XXX_LED_STATIC_OP_EN) {
|
|
err = jl2xxx_led_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->fld.enable & JL2XXX_FLD_STATIC_OP_EN) {
|
|
err = jl2xxx_fld_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
#if (JLSEMI_PHY_WOL)
|
|
if (priv->wol.enable & JL2XXX_WOL_STATIC_OP_EN) {
|
|
err = jl2xxx_wol_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
if (priv->intr.enable & JL2XXX_INTR_STATIC_OP_EN) {
|
|
err = jl2xxx_intr_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->downshift.enable & JL2XXX_DSFT_STATIC_OP_EN) {
|
|
err = jl2xxx_downshift_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->rgmii.enable & JL2XXX_RGMII_STATIC_OP_EN) {
|
|
err = jl2xxx_rgmii_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->clk.enable & JL2XXX_CLK_STATIC_OP_EN) {
|
|
err = jl2xxx_clk_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->work_mode.enable & JL2XXX_WORK_MODE_STATIC_OP_EN) {
|
|
err = jl2xxx_work_mode_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->lpbk.enable & JL2XXX_LPBK_STATIC_OP_EN) {
|
|
err = jl2xxx_lpbk_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->slew_rate.enable & JL2XXX_SLEW_RATE_STATIC_OP_EN) {
|
|
err = jl2xxx_slew_rate_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
if (priv->rxc_out.enable & JL2XXX_RXC_OUT_STATIC_OP_EN) {
|
|
err = jl2xxx_rxc_out_static_op_set(phydev);
|
|
if (err < 0)
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jl2xxx_pre_init(struct phy_device *phydev,
|
|
u32 *init_data, u16 data_len,
|
|
u16 *patch_fw_versions, u16 versions_len,
|
|
u16 patch_version)
|
|
{
|
|
int i, j;
|
|
int regaddr, val;
|
|
bool patch_ok = false;
|
|
|
|
val = jlsemi_read_paged(phydev, JL2XXX_PAGE0, JL2XXX_PHY_INFO_REG);
|
|
for (i = 0; i < versions_len; i++) {
|
|
if (val == patch_fw_versions[i])
|
|
patch_ok |= true;
|
|
}
|
|
|
|
if (!patch_ok)
|
|
return 0;
|
|
|
|
for (i = 0; i < data_len; i++) {
|
|
regaddr = ((init_data[i] >> 16) & 0xff);
|
|
val = (init_data[i] & 0xffff);
|
|
phy_write(phydev, regaddr, val);
|
|
if (regaddr == 0x18) {
|
|
phy_write(phydev, 0x10, 0x8006);
|
|
for (j = 0; j < 8; j++) {
|
|
if (phy_read(phydev, 0x10) == 0)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/* Wait load patch complete */
|
|
msleep(20);
|
|
|
|
val = jlsemi_read_paged(phydev, JL2XXX_PAGE174, JL2XXX_PATCH_REG);
|
|
|
|
if (val != patch_version)
|
|
JLSEMI_PHY_MSG(KERN_ERR
|
|
"%s: patch version is not match\n", __func__);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int jlsemi_soft_reset(struct phy_device *phydev)
|
|
{
|
|
int err;
|
|
|
|
err = jlsemi_set_bits(phydev, JL2XXX_PAGE0,
|
|
JL2XXX_BMCR_REG, JL2XXX_SOFT_RESET);
|
|
if (err < 0)
|
|
return err;
|
|
/* Wait soft reset complete*/
|
|
msleep(600);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/********************** Convenience function for phy **********************/
|
|
|
|
/**
|
|
* jlsemi_write_page() - write the page register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @page: page values
|
|
*/
|
|
int jlsemi_write_page(struct phy_device *phydev, int page)
|
|
{
|
|
return phy_write(phydev, JLSEMI_PAGE31, page);
|
|
}
|
|
|
|
/**
|
|
* jlsemi_read_page() - write the page register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
*
|
|
* Return: get page values at present
|
|
*/
|
|
int jlsemi_read_page(struct phy_device *phydev)
|
|
{
|
|
return phy_read(phydev, JLSEMI_PAGE31);
|
|
}
|
|
|
|
/**
|
|
* __jlsemi_save_page() - save the page value
|
|
*@phydev: a pointer to a &struct phy_device
|
|
*
|
|
* Return: save page value
|
|
*/
|
|
static inline int __jlsemi_save_page(struct phy_device *phydev)
|
|
{
|
|
return jlsemi_read_page(phydev);
|
|
}
|
|
|
|
/**
|
|
* __jlsemi_select_page() - restore the page register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @page: the page
|
|
*
|
|
* Return:
|
|
* @oldpgae: this is last page value
|
|
* @ret: if page is change it will return new page value
|
|
*/
|
|
static inline int __jlsemi_select_page(struct phy_device *phydev, int page)
|
|
{
|
|
int ret, oldpage;
|
|
|
|
oldpage = ret = __jlsemi_save_page(phydev);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (oldpage != page) {
|
|
ret = jlsemi_write_page(phydev, page);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
return oldpage;
|
|
}
|
|
|
|
/**
|
|
* __jlsemi_restore_page() - restore the page register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @oldpage: the old page, return value from __jlsemi_save_page() or
|
|
* __jlsemi_select_page()
|
|
* @ret: operation's return code
|
|
*
|
|
* Returns:
|
|
* @oldpage if it was a negative value, otherwise
|
|
* @ret if it was a negative errno value, otherwise
|
|
* phy_write_page()'s negative value if it were in error, otherwise
|
|
* @ret
|
|
*/
|
|
static inline int __jlsemi_restore_page(struct phy_device *phydev,
|
|
int oldpage, int ret)
|
|
{
|
|
int r;
|
|
|
|
if (oldpage >= 0) {
|
|
r = jlsemi_write_page(phydev, oldpage);
|
|
|
|
/* Propagate the operation return code if the page write
|
|
* was successful.
|
|
*/
|
|
if (ret >= 0 && r < 0)
|
|
ret = r;
|
|
} else {
|
|
/* Propagate the phy page selection error code */
|
|
ret = oldpage;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* __jlsemi_modify_reg() - Convenience function for modifying a PHY register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @regnum: register number
|
|
* @mask: bit mask of bits to clear
|
|
* @set: bit mask of bits to set
|
|
*
|
|
* Returns negative errno, 0 if there was no change, and 1 in case of change
|
|
*/
|
|
static inline int __jlsemi_modify_reg(struct phy_device *phydev,
|
|
u32 regnum, u16 mask, u16 set)
|
|
{
|
|
int newval, ret;
|
|
|
|
ret = phy_read(phydev, regnum);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
newval = (ret & ~mask) | set;
|
|
if (newval == ret)
|
|
return 0;
|
|
|
|
ret = phy_write(phydev, regnum, newval);
|
|
|
|
return ret < 0 ? ret : 1;
|
|
}
|
|
|
|
/**
|
|
* jlsemi_modify_paged_reg() - Function for modifying a paged register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @page: the page for the phy
|
|
* @regnum: register number
|
|
* @mask: bit mask of bits to clear
|
|
* @set: bit mask of bits to set
|
|
*
|
|
* Returns negative errno, 0 if there was no change, and 1 in case of change
|
|
*/
|
|
int jlsemi_modify_paged_reg(struct phy_device *phydev,
|
|
int page, u32 regnum,
|
|
u16 mask, u16 set)
|
|
{
|
|
int ret = 0, oldpage;
|
|
|
|
oldpage = __jlsemi_select_page(phydev, page);
|
|
if (oldpage >= 0)
|
|
ret = __jlsemi_modify_reg(phydev, regnum, mask, set);
|
|
|
|
return __jlsemi_restore_page(phydev, oldpage, ret);
|
|
}
|
|
|
|
/**
|
|
* jlsemi_set_bits() - Convenience function for setting bits in a PHY register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @page: the page for the phy
|
|
* @regnum: register number to write
|
|
* @val: bits to set
|
|
*/
|
|
int jlsemi_set_bits(struct phy_device *phydev,
|
|
int page, u32 regnum, u16 val)
|
|
{
|
|
return jlsemi_modify_paged_reg(phydev, page, regnum, 0, val);
|
|
}
|
|
|
|
/**
|
|
* jlsemi_clear_bits - Convenience function for clearing bits in a PHY register
|
|
* @phydev: the phy_device struct
|
|
* @page: the page for the phy
|
|
* @regnum: register number to write
|
|
* @val: bits to clear
|
|
*/
|
|
int jlsemi_clear_bits(struct phy_device *phydev,
|
|
int page, u32 regnum, u16 val)
|
|
{
|
|
return jlsemi_modify_paged_reg(phydev, page, regnum, val, 0);
|
|
}
|
|
|
|
/**
|
|
* jlsemi_fetch_bit() - Convenience function for setting bits in a PHY register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @page: the page for the phy
|
|
* @regnum: register number to write
|
|
* @val: bit to get
|
|
*
|
|
* Note:
|
|
* you only get one bit at meanwhile
|
|
*
|
|
*/
|
|
int jlsemi_fetch_bit(struct phy_device *phydev,
|
|
int page, u32 regnum, u16 val)
|
|
{
|
|
int ret = 0, oldpage;
|
|
|
|
oldpage = __jlsemi_select_page(phydev, page);
|
|
if (oldpage >= 0) {
|
|
ret = phy_read(phydev, regnum);
|
|
if (ret < 0)
|
|
return ret;
|
|
ret = ((ret & val) == val) ? 1 : 0;
|
|
}
|
|
|
|
return __jlsemi_restore_page(phydev, oldpage, ret);
|
|
}
|
|
|
|
/**
|
|
* jlsemi_read_paged() - Convenience function for reading a paged register
|
|
* @phydev: a pointer to a &struct phy_device
|
|
* @page: the page for the phy
|
|
* @regnum: register number
|
|
*
|
|
* Same rules as for phy_read().
|
|
*/
|
|
int jlsemi_read_paged(struct phy_device *phydev, int page, u32 regnum)
|
|
{
|
|
int ret = 0, oldpage;
|
|
|
|
oldpage = __jlsemi_select_page(phydev, page);
|
|
if (oldpage >= 0)
|
|
ret = phy_read(phydev, regnum);
|
|
|
|
return __jlsemi_restore_page(phydev, oldpage, ret);
|
|
}
|
|
|
|
#if (KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE)
|
|
int jlsemi_drivers_register(struct phy_driver *phydrvs, int size)
|
|
{
|
|
int i, j;
|
|
int ret;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
ret = phy_driver_register(&phydrvs[i]);
|
|
if (ret)
|
|
goto err;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err:
|
|
for (j = 0; j < i; j++)
|
|
phy_driver_unregister(&phydrvs[j]);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void jlsemi_drivers_unregister(struct phy_driver *phydrvs, int size)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++)
|
|
phy_driver_unregister(&phydrvs[i]);
|
|
}
|
|
#else
|
|
#endif
|