mirror of
https://github.com/LuckfoxTECH/luckfox-pico.git
synced 2026-01-19 09:52:31 +01:00
project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp: Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem. sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately. sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades. sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for fastboot. Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
#define RK630_PHY_ID 0x00441400
|
||||
@@ -71,6 +72,39 @@
|
||||
#define T22_TX_LEVEL_100M 0x2d
|
||||
#define T22_TX_LEVEL_10M 0x32
|
||||
|
||||
/* Long network cable parameters */
|
||||
#define RX_DETECT_SCHEDULE_TIME 500 /* ms */
|
||||
#define RX_DETECT_INIT_WAIT_TIME 2000 /* ms */
|
||||
|
||||
#define RX_DETECT_MAX_COUNT (5000 / RX_DETECT_SCHEDULE_TIME)
|
||||
#define ALL_RX_DETECT_MAX_COUNT (2 * RX_DETECT_MAX_COUNT)
|
||||
|
||||
#define LINKED_MAX_COUNT (10000 / RX_DETECT_SCHEDULE_TIME)
|
||||
#define ALL_LINKED_MAX_COUNT (2 * LINKED_MAX_COUNT)
|
||||
|
||||
#define RX_PACKET_RECEIVED_COUNTS 3 /* packets */
|
||||
#define RX_PACKET_RECEIVED_LOST 15 /* percent */
|
||||
|
||||
#define RX_SIGNAL_DETECT_TEMP 85000
|
||||
|
||||
struct rk630_phy_switched {
|
||||
/* record state */
|
||||
bool config;
|
||||
bool config_mode_10M;
|
||||
bool finished;
|
||||
|
||||
/* detected process */
|
||||
unsigned int detected_count;
|
||||
bool config_rx_signal;
|
||||
int old_link;
|
||||
|
||||
/* linked process */
|
||||
unsigned int linked_count;
|
||||
int rx_pkt_cnt;
|
||||
int rx_crc_err_cnt;
|
||||
int lost_percent;
|
||||
};
|
||||
|
||||
struct rk630_phy_priv {
|
||||
struct phy_device *phydev;
|
||||
bool ieee;
|
||||
@@ -78,6 +112,13 @@ struct rk630_phy_priv {
|
||||
struct wake_lock wol_wake_lock;
|
||||
int tx_level_100M;
|
||||
int tx_level_10M;
|
||||
|
||||
struct rk630_phy_switched switched;
|
||||
/* mutex protect variables between notify thread and delayed work */
|
||||
struct mutex lock;
|
||||
struct delayed_work service_task;
|
||||
struct thermal_zone_device *tz;
|
||||
bool disable_switch;
|
||||
};
|
||||
|
||||
static void rk630_phy_t22_get_tx_level_from_efuse(struct phy_device *phydev)
|
||||
@@ -160,19 +201,49 @@ static void rk630_phy_ieee_set(struct phy_device *phydev, bool enable)
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0000);
|
||||
}
|
||||
|
||||
static void rk630_phy_set_uaps(struct phy_device *phydev)
|
||||
static void rk630_phy_set_aps(struct phy_device *phydev, bool enable)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
/* Switch to page 1 */
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0100);
|
||||
value = phy_read(phydev, REG_PAGE1_APS_CTRL);
|
||||
if (enable)
|
||||
value |= BIT(15);
|
||||
else
|
||||
value &= ~BIT(15);
|
||||
phy_write(phydev, REG_PAGE1_APS_CTRL, value);
|
||||
/* Switch to page 0 */
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0000);
|
||||
}
|
||||
|
||||
static void rk630_phy_set_uaps(struct phy_device *phydev, bool enable)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
/* Switch to page 1 */
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0100);
|
||||
value = phy_read(phydev, REG_PAGE1_UAPS_CONFIGURE);
|
||||
value |= BIT(15);
|
||||
if (enable)
|
||||
value |= BIT(15);
|
||||
else
|
||||
value &= ~BIT(15);
|
||||
phy_write(phydev, REG_PAGE1_UAPS_CONFIGURE, value);
|
||||
/* Switch to page 0 */
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0000);
|
||||
}
|
||||
|
||||
static bool rk630_phy_rx_signal_detected(struct phy_device *phydev)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
/* Switch to page 0 */
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0000);
|
||||
value = phy_read(phydev, 25);
|
||||
|
||||
return (value & BIT(15)) ? false : true;
|
||||
}
|
||||
|
||||
static void rk630_phy_s40_config_init(struct phy_device *phydev)
|
||||
{
|
||||
phy_write(phydev, 0, phy_read(phydev, 0) & ~BIT(13));
|
||||
@@ -210,8 +281,8 @@ static void rk630_phy_t22_config_init(struct phy_device *phydev)
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0100);
|
||||
/* Enable offset clock */
|
||||
phy_write(phydev, 0x10, 0xfbfe);
|
||||
/* Disable APS */
|
||||
phy_write(phydev, REG_PAGE1_APS_CTRL, 0x4824);
|
||||
/* Disable APS & Rx detected time 2s, default is 4s */
|
||||
phy_write(phydev, REG_PAGE1_APS_CTRL, 0x4822);
|
||||
/* Switch to page 2 */
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0200);
|
||||
/* PHYAFE TRX optimization */
|
||||
@@ -223,7 +294,15 @@ static void rk630_phy_t22_config_init(struct phy_device *phydev)
|
||||
/* PHYAFE Gain optimization */
|
||||
phy_write(phydev, REG_PAGE6_GAIN_ANONTROL, 0x0400);
|
||||
/* PHYAFE EQ optimization */
|
||||
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088);
|
||||
|
||||
if (priv->disable_switch) {
|
||||
/* Rx detected default threshold 160 mv */
|
||||
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x1088);
|
||||
} else {
|
||||
/* Rx detected threshold 260 mv */
|
||||
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, 0x10c8);
|
||||
priv->switched.config_rx_signal = true;
|
||||
}
|
||||
|
||||
if (priv->tx_level_100M <= 0 || priv->tx_level_10M <= 0)
|
||||
rk630_phy_t22_get_tx_level_from_efuse(phydev);
|
||||
@@ -268,10 +347,12 @@ static int rk630_phy_config_init(struct phy_device *phydev)
|
||||
* Ultra Auto-Power Saving Mode (UAPS) is designed to
|
||||
* save power when cable is not plugged into PHY.
|
||||
*/
|
||||
rk630_phy_set_uaps(phydev);
|
||||
rk630_phy_set_uaps(phydev, true);
|
||||
break;
|
||||
case PHY_ADDR_T22:
|
||||
rk630_phy_t22_config_init(phydev);
|
||||
rk630_phy_set_aps(phydev, false);
|
||||
rk630_phy_set_uaps(phydev, false);
|
||||
break;
|
||||
default:
|
||||
phydev_err(phydev, "Unsupported address for current phy: %d\n",
|
||||
@@ -284,6 +365,305 @@ static int rk630_phy_config_init(struct phy_device *phydev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* config0(default) and config1(0x555e) switched for 100/10M speed */
|
||||
static bool rk630_phy_switch_config(struct phy_device *phydev, bool config)
|
||||
{
|
||||
struct rk630_phy_priv *priv = phydev->priv;
|
||||
|
||||
if (priv->switched.config != config) {
|
||||
int val;
|
||||
|
||||
val = config ? 0x555e : 0x5540;
|
||||
phy_write(priv->phydev, REG_PAGE_SEL, 0x0600);
|
||||
phy_write(priv->phydev, REG_PAGE6_ADC_ANONTROL, val);
|
||||
phy_write(priv->phydev, REG_PAGE_SEL, 0x0000);
|
||||
priv->switched.config = config;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 10M speed configuration */
|
||||
static void rk630_phy_10m_switch_config(struct phy_device *phydev, bool config)
|
||||
{
|
||||
struct rk630_phy_priv *priv = phydev->priv;
|
||||
unsigned int val;
|
||||
|
||||
if (config == priv->switched.config_mode_10M)
|
||||
return;
|
||||
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0600);
|
||||
val = phy_read(phydev, REG_PAGE6_AFE_TX_CTRL);
|
||||
val &= ~GENMASK(14, 13);
|
||||
if (config && !priv->switched.config_mode_10M)
|
||||
val |= BIT(13);
|
||||
|
||||
priv->switched.config_mode_10M = config;
|
||||
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, val);
|
||||
phy_write(priv->phydev, REG_PAGE_SEL, 0x0000);
|
||||
}
|
||||
|
||||
static void rk630_phy_switch_rx_signal_config(struct phy_device *phydev,
|
||||
bool config)
|
||||
{
|
||||
struct rk630_phy_priv *priv = phydev->priv;
|
||||
|
||||
if (priv->switched.config_rx_signal != config) {
|
||||
int val;
|
||||
|
||||
phy_write(priv->phydev, REG_PAGE_SEL, 0x0600);
|
||||
val = phy_read(phydev, REG_PAGE6_AFE_TX_CTRL);
|
||||
val &= ~GENMASK(7, 6);
|
||||
if (config)
|
||||
val |= GENMASK(7, 6);
|
||||
else
|
||||
val |= BIT(7);
|
||||
phy_write(phydev, REG_PAGE6_AFE_TX_CTRL, val);
|
||||
phy_write(priv->phydev, REG_PAGE_SEL, 0x0000);
|
||||
|
||||
priv->switched.config_rx_signal = config;
|
||||
}
|
||||
}
|
||||
|
||||
static void rk630_phy_packet_statistics(struct phy_device *phydev,
|
||||
int *total_cnt, int *crc_err_cnt)
|
||||
{
|
||||
struct rk630_phy_priv *priv = phydev->priv;
|
||||
|
||||
phy_write(priv->phydev, REG_PAGE_SEL, 0x0900);
|
||||
*total_cnt = phy_read(priv->phydev, 0x1b) << 16;
|
||||
*total_cnt |= phy_read(priv->phydev, 0x1c);
|
||||
*crc_err_cnt = phy_read(priv->phydev, 0x1d) << 16;
|
||||
*crc_err_cnt |= phy_read(priv->phydev, 0x1e);
|
||||
phy_write(phydev, REG_PAGE_SEL, 0x0000);
|
||||
}
|
||||
|
||||
static bool rk630_phy_switch_config_by_packets(struct phy_device *phydev)
|
||||
{
|
||||
struct rk630_phy_priv *priv = phydev->priv;
|
||||
int rx_pkt_cnt, rx_crc_err_cnt;
|
||||
int total_cnt, total_crc_err_cnt;
|
||||
int lost_percent;
|
||||
|
||||
rk630_phy_packet_statistics(phydev, &total_cnt, &total_crc_err_cnt);
|
||||
|
||||
rx_pkt_cnt = total_cnt - priv->switched.rx_pkt_cnt;
|
||||
rx_crc_err_cnt = total_crc_err_cnt - priv->switched.rx_crc_err_cnt;
|
||||
|
||||
priv->switched.rx_pkt_cnt = total_cnt;
|
||||
priv->switched.rx_crc_err_cnt = total_crc_err_cnt;
|
||||
|
||||
/* less than the minimal received packets during some time */
|
||||
if (rx_pkt_cnt < RX_PACKET_RECEIVED_COUNTS)
|
||||
return true;
|
||||
|
||||
/* Percents packets lost is not good during some time */
|
||||
lost_percent = (rx_crc_err_cnt * 100 / rx_pkt_cnt) > RX_PACKET_RECEIVED_LOST;
|
||||
|
||||
/* Just compare with config0's packet lost, update config if it is better
|
||||
* than config0.
|
||||
*/
|
||||
if (((rx_crc_err_cnt * 100 / rx_pkt_cnt) > RX_PACKET_RECEIVED_LOST) &&
|
||||
lost_percent > priv->switched.lost_percent) {
|
||||
/* Only save config0 lost percent */
|
||||
if (!priv->switched.config)
|
||||
priv->switched.lost_percent = lost_percent;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Only save config0 lost percent */
|
||||
if (!priv->switched.config)
|
||||
priv->switched.lost_percent = lost_percent;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rk630_phy_service_task(struct work_struct *work)
|
||||
{
|
||||
struct rk630_phy_priv *priv = container_of(work, struct rk630_phy_priv,
|
||||
service_task.work);
|
||||
unsigned int delay_time;
|
||||
int ret, temp;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
if (priv->disable_switch) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!priv->phydev->link) {
|
||||
bool signal_detected;
|
||||
|
||||
signal_detected = rk630_phy_rx_signal_detected(priv->phydev);
|
||||
|
||||
/* Read signal */
|
||||
if (!signal_detected) {
|
||||
/* Slow schedule work for 2 * SCHEDULE_TIME, if no signal */
|
||||
priv->switched.detected_count = 0;
|
||||
priv->switched.lost_percent = 0;
|
||||
priv->switched.finished = false;
|
||||
priv->switched.linked_count = 0;
|
||||
delay_time = 2 * RX_DETECT_SCHEDULE_TIME;
|
||||
/* Goto default config if no rj45 signal plugin */
|
||||
rk630_phy_switch_config(priv->phydev, false);
|
||||
|
||||
/* Also go to 10M default config */
|
||||
rk630_phy_10m_switch_config(priv->phydev, false);
|
||||
} else {
|
||||
priv->switched.detected_count++;
|
||||
/* Fast schedule work for 1 * SCHEDULE_TIME, if signal
|
||||
* detected.
|
||||
*/
|
||||
delay_time = RX_DETECT_SCHEDULE_TIME;
|
||||
if (priv->switched.detected_count == RX_DETECT_MAX_COUNT &&
|
||||
!priv->switched.finished) {
|
||||
/* After it, there is no link, Might be a long cable,
|
||||
* config1 switched to get better performance during
|
||||
* some time.
|
||||
*/
|
||||
rk630_phy_switch_config(priv->phydev, true);
|
||||
} else if (priv->switched.detected_count == ALL_RX_DETECT_MAX_COUNT &&
|
||||
!priv->switched.finished) {
|
||||
/* After another detect, we lost the last chance,
|
||||
* go back to default config0.
|
||||
*/
|
||||
rk630_phy_switch_config(priv->phydev, false);
|
||||
priv->switched.finished = true;
|
||||
} else if (priv->switched.detected_count > ALL_RX_DETECT_MAX_COUNT ||
|
||||
priv->switched.finished) {
|
||||
/* Slow schedule work for 2 * SCHEDULE_TIME, if
|
||||
* detected finish.
|
||||
*/
|
||||
delay_time = 2 * RX_DETECT_SCHEDULE_TIME;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Detect the packet count and crc error count statistics */
|
||||
priv->switched.linked_count++;
|
||||
/* Fast schedule work for 1 * SCHEDULE_TIME, if linkup detected */
|
||||
delay_time = RX_DETECT_SCHEDULE_TIME;
|
||||
if (priv->switched.linked_count == LINKED_MAX_COUNT &&
|
||||
!priv->switched.finished) {
|
||||
if (rk630_phy_switch_config_by_packets(priv->phydev)) {
|
||||
/* Config1 switched to get better performance */
|
||||
rk630_phy_switch_config(priv->phydev, true);
|
||||
|
||||
/* Also go to 10M default config */
|
||||
if (priv->switched.config && priv->phydev->speed == SPEED_10)
|
||||
rk630_phy_10m_switch_config(priv->phydev, true);
|
||||
}
|
||||
} else if (priv->switched.linked_count == ALL_LINKED_MAX_COUNT &&
|
||||
!priv->switched.finished) {
|
||||
/* If config switched, we lost the last chance, return to
|
||||
* default config0.
|
||||
*/
|
||||
if (rk630_phy_switch_config_by_packets(priv->phydev)) {
|
||||
rk630_phy_switch_config(priv->phydev, false);
|
||||
rk630_phy_10m_switch_config(priv->phydev, false);
|
||||
}
|
||||
priv->switched.finished = true;
|
||||
} else if (priv->switched.linked_count > ALL_LINKED_MAX_COUNT ||
|
||||
priv->switched.finished) {
|
||||
/* Slow schedule work for 2 * SCHEDULE_TIME, if linkup
|
||||
* detected finish.
|
||||
*/
|
||||
delay_time = 2 * RX_DETECT_SCHEDULE_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->tz) {
|
||||
ret = thermal_zone_get_temp(priv->tz, &temp);
|
||||
if (ret || temp == THERMAL_TEMP_INVALID)
|
||||
phydev_err(priv->phydev,
|
||||
"failed to read out thermal zone (%d)\n", ret);
|
||||
else
|
||||
rk630_phy_switch_rx_signal_config(priv->phydev,
|
||||
(temp > RX_SIGNAL_DETECT_TEMP) ? false : true);
|
||||
}
|
||||
|
||||
schedule_delayed_work(&priv->service_task, msecs_to_jiffies(delay_time));
|
||||
mutex_unlock(&priv->lock);
|
||||
}
|
||||
|
||||
static void rk630_phy_link_change_notify(struct phy_device *phydev)
|
||||
{
|
||||
struct rk630_phy_priv *priv = phydev->priv;
|
||||
|
||||
if (phydev->mdio.addr == PHY_ADDR_T22) {
|
||||
mutex_lock(&priv->lock);
|
||||
if (priv->disable_switch) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->switched.old_link && !phydev->link) {
|
||||
priv->switched.old_link = 0;
|
||||
priv->switched.linked_count = 0;
|
||||
schedule_delayed_work(&priv->service_task,
|
||||
msecs_to_jiffies(RX_DETECT_SCHEDULE_TIME));
|
||||
} else if (!priv->switched.old_link && phydev->link) {
|
||||
/* If linked, keep current config, but if the linked is
|
||||
* 10M speed, and config1 has been enabled, also switched
|
||||
* the 10M config.
|
||||
*/
|
||||
if (priv->switched.config && phydev->speed == SPEED_10)
|
||||
rk630_phy_10m_switch_config(phydev, true);
|
||||
|
||||
priv->switched.old_link = 1;
|
||||
priv->switched.detected_count = 0;
|
||||
/* Record base packet statistics to compare later, if linked */
|
||||
if (!priv->switched.linked_count)
|
||||
rk630_phy_packet_statistics(priv->phydev,
|
||||
&priv->switched.rx_pkt_cnt,
|
||||
&priv->switched.rx_crc_err_cnt);
|
||||
schedule_delayed_work(&priv->service_task,
|
||||
msecs_to_jiffies(RX_DETECT_SCHEDULE_TIME));
|
||||
}
|
||||
mutex_unlock(&priv->lock);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t rk630_phy_disable_switch_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct phy_device *phydev = to_phy_device(dev);
|
||||
struct rk630_phy_priv *priv = phydev->priv;
|
||||
int ret;
|
||||
bool disabled;
|
||||
|
||||
ret = kstrtobool(buf, &disabled);
|
||||
if (ret)
|
||||
return count;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
if (disabled) {
|
||||
cancel_delayed_work_sync(&priv->service_task);
|
||||
|
||||
/* Save to default config */
|
||||
rk630_phy_10m_switch_config(priv->phydev, false);
|
||||
rk630_phy_switch_rx_signal_config(priv->phydev, false);
|
||||
rk630_phy_switch_config(priv->phydev, false);
|
||||
|
||||
memset(&priv->switched, 0, sizeof(struct rk630_phy_switched));
|
||||
} else {
|
||||
priv->switched.old_link = phydev->link;
|
||||
/* Rx detected threshold 260 mv */
|
||||
rk630_phy_switch_rx_signal_config(priv->phydev, true);
|
||||
|
||||
schedule_delayed_work(&priv->service_task,
|
||||
msecs_to_jiffies(RX_DETECT_INIT_WAIT_TIME));
|
||||
}
|
||||
priv->disable_switch = disabled;
|
||||
dev_info(dev, "rk630 phy disable switch to %s\n", disabled ? "true" : "false");
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_WO(rk630_phy_disable_switch);
|
||||
|
||||
static irqreturn_t rk630_wol_irq_thread(int irq, void *dev_id)
|
||||
{
|
||||
struct rk630_phy_priv *priv = (struct rk630_phy_priv *)dev_id;
|
||||
@@ -296,6 +676,7 @@ static irqreturn_t rk630_wol_irq_thread(int irq, void *dev_id)
|
||||
static int rk630_phy_probe(struct phy_device *phydev)
|
||||
{
|
||||
struct rk630_phy_priv *priv;
|
||||
const char *tz_name;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
|
||||
@@ -324,6 +705,23 @@ static int rk630_phy_probe(struct phy_device *phydev)
|
||||
enable_irq_wake(priv->wol_irq);
|
||||
}
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
INIT_DELAYED_WORK(&priv->service_task, rk630_phy_service_task);
|
||||
|
||||
priv->disable_switch = of_property_read_bool(phydev->mdio.dev.of_node,
|
||||
"rk630,phy-disable-switch");
|
||||
of_property_read_string(phydev->mdio.dev.of_node, "rockchip,thermal-zone",
|
||||
&tz_name);
|
||||
priv->tz = thermal_zone_get_zone_by_name(tz_name);
|
||||
if (IS_ERR(priv->tz)) {
|
||||
pr_warn("Error getting thermal zone, not yet ready?\n");
|
||||
priv->tz = NULL;
|
||||
}
|
||||
|
||||
ret = device_create_file(&phydev->mdio.dev, &dev_attr_rk630_phy_disable_switch);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->phydev = phydev;
|
||||
|
||||
return 0;
|
||||
@@ -346,6 +744,10 @@ static int rk630_phy_suspend(struct phy_device *phydev)
|
||||
phy_write(phydev, REG_INTERRUPT_MASK, BIT(14));
|
||||
enable_irq(priv->wol_irq);
|
||||
}
|
||||
|
||||
if (!priv->disable_switch)
|
||||
cancel_delayed_work_sync(&priv->service_task);
|
||||
|
||||
return genphy_suspend(phydev);
|
||||
}
|
||||
|
||||
@@ -359,6 +761,10 @@ static int rk630_phy_resume(struct phy_device *phydev)
|
||||
disable_irq(priv->wol_irq);
|
||||
}
|
||||
|
||||
if (!priv->disable_switch)
|
||||
schedule_delayed_work(&priv->service_task,
|
||||
msecs_to_jiffies(RX_DETECT_INIT_WAIT_TIME));
|
||||
|
||||
return genphy_resume(phydev);
|
||||
}
|
||||
|
||||
@@ -369,6 +775,7 @@ static struct phy_driver rk630_phy_driver[] = {
|
||||
.name = "RK630 PHY",
|
||||
.features = PHY_BASIC_FEATURES,
|
||||
.flags = 0,
|
||||
.link_change_notify = rk630_phy_link_change_notify,
|
||||
.probe = rk630_phy_probe,
|
||||
.remove = rk630_phy_remove,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
@@ -385,7 +792,7 @@ static struct mdio_device_id __maybe_unused rk630_phy_tbl[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl);
|
||||
MODULE_DEVICE_TABLE(mdio, rk630_phy_tbl);
|
||||
|
||||
module_phy_driver(rk630_phy_driver);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user