diff mbox series

[1/2] power: reset: linkstation-poweroff: prepare for new devices

Message ID 20210624091813.42334-1-paweldembicki@gmail.com
State Accepted
Commit e2f471efe1d607a7aff38ce53ec717cebe4283d6
Headers show
Series [1/2] power: reset: linkstation-poweroff: prepare for new devices | expand

Commit Message

Pawel Dembicki June 24, 2021, 9:18 a.m. UTC
This commit prepare driver for another device support.

New power_off_cfg structure describes two most important things: name of
mdio bus and pointer to register setting function. It allow to add new
device with different mdio bus node and other phy register config.

Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
---
 drivers/power/reset/linkstation-poweroff.c | 35 ++++++++++++++++++----
 1 file changed, 29 insertions(+), 6 deletions(-)

Comments

Sebastian Reichel Aug. 13, 2021, 5:17 p.m. UTC | #1
Hi,

On Thu, Jun 24, 2021 at 11:18:11AM +0200, Pawel Dembicki wrote:
> This commit prepare driver for another device support.

> 

> New power_off_cfg structure describes two most important things: name of

> mdio bus and pointer to register setting function. It allow to add new

> device with different mdio bus node and other phy register config.

> 

> Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>

> ---


Thanks, queued.

-- Sebastian

>  drivers/power/reset/linkstation-poweroff.c | 35 ++++++++++++++++++----

>  1 file changed, 29 insertions(+), 6 deletions(-)

> 

> diff --git a/drivers/power/reset/linkstation-poweroff.c b/drivers/power/reset/linkstation-poweroff.c

> index f1e843df0e16..cb5a32f852c1 100644

> --- a/drivers/power/reset/linkstation-poweroff.c

> +++ b/drivers/power/reset/linkstation-poweroff.c

> @@ -29,11 +29,21 @@

>  #define LED2_FORCE_ON					(0x8 << 8)

>  #define LEDMASK						GENMASK(11,8)

>  

> +struct power_off_cfg {

> +	char *mdio_node_name;

> +	void (*phy_set_reg)(bool restart);

> +};

> +

>  static struct phy_device *phydev;

> +static const struct power_off_cfg *cfg;

>  

> -static void mvphy_reg_intn(u16 data)

> +static void linkstation_mvphy_reg_intn(bool restart)

>  {

>  	int rc = 0, saved_page;

> +	u16 data = 0;

> +

> +	if (restart)

> +		data = MII_88E1318S_PHY_LED_TCR_FORCE_INT;

>  

>  	saved_page = phy_select_page(phydev, MII_MARVELL_LED_PAGE);

>  	if (saved_page < 0)

> @@ -66,11 +76,16 @@ static void mvphy_reg_intn(u16 data)

>  		dev_err(&phydev->mdio.dev, "Write register failed, %d\n", rc);

>  }

>  

> +static const struct power_off_cfg linkstation_power_off_cfg = {

> +	.mdio_node_name = "mdio",

> +	.phy_set_reg = linkstation_mvphy_reg_intn,

> +};

> +

>  static int linkstation_reboot_notifier(struct notifier_block *nb,

>  				       unsigned long action, void *unused)

>  {

>  	if (action == SYS_RESTART)

> -		mvphy_reg_intn(MII_88E1318S_PHY_LED_TCR_FORCE_INT);

> +		cfg->phy_set_reg(true);

>  

>  	return NOTIFY_DONE;

>  }

> @@ -82,14 +97,18 @@ static struct notifier_block linkstation_reboot_nb = {

>  static void linkstation_poweroff(void)

>  {

>  	unregister_reboot_notifier(&linkstation_reboot_nb);

> -	mvphy_reg_intn(0);

> +	cfg->phy_set_reg(false);

>  

>  	kernel_restart("Power off");

>  }

>  

>  static const struct of_device_id ls_poweroff_of_match[] = {

> -	{ .compatible = "buffalo,ls421d" },

> -	{ .compatible = "buffalo,ls421de" },

> +	{ .compatible = "buffalo,ls421d",

> +	  .data = &linkstation_power_off_cfg,

> +	},

> +	{ .compatible = "buffalo,ls421de",

> +	  .data = &linkstation_power_off_cfg,

> +	},

>  	{ },

>  };

>  

> @@ -97,13 +116,17 @@ static int __init linkstation_poweroff_init(void)

>  {

>  	struct mii_bus *bus;

>  	struct device_node *dn;

> +	const struct of_device_id *match;

>  

>  	dn = of_find_matching_node(NULL, ls_poweroff_of_match);

>  	if (!dn)

>  		return -ENODEV;

>  	of_node_put(dn);

>  

> -	dn = of_find_node_by_name(NULL, "mdio");

> +	match = of_match_node(ls_poweroff_of_match, dn);

> +	cfg = match->data;

> +

> +	dn = of_find_node_by_name(NULL, cfg->mdio_node_name);

>  	if (!dn)

>  		return -ENODEV;

>  

> -- 

> 2.25.1

>
Sebastian Reichel Aug. 13, 2021, 5:18 p.m. UTC | #2
Hi,

On Thu, Jun 24, 2021 at 11:18:12AM +0200, Pawel Dembicki wrote:
> This commit introduces support for NETGEAR ReadyNAS Duo v2.

> This device use bit 4 of LED[2:0] Polarity Control Register to indicate

> AC Power loss.

> 

> For more details about AC loss detection in NETGEAR ReadyNAS Duo v2,

> please look at the file:

> RND_5.3.13_WW.src/u-boot/board/mv_feroceon/mv_hal/usibootup/usibootup.c

> from Netgear GPL sources.

> 

> Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>

> ---


Thanks, queued.

-- Sebastian

>  drivers/power/reset/linkstation-poweroff.c | 43 ++++++++++++++++++++++

>  1 file changed, 43 insertions(+)

> 

> diff --git a/drivers/power/reset/linkstation-poweroff.c b/drivers/power/reset/linkstation-poweroff.c

> index cb5a32f852c1..5afe3ef23395 100644

> --- a/drivers/power/reset/linkstation-poweroff.c

> +++ b/drivers/power/reset/linkstation-poweroff.c

> @@ -19,6 +19,7 @@

>  #define MII_MARVELL_PHY_PAGE		22

>  

>  #define MII_PHY_LED_CTRL		16

> +#define MII_PHY_LED_POL_CTRL		17

>  #define MII_88E1318S_PHY_LED_TCR	18

>  #define MII_88E1318S_PHY_WOL_CTRL	16

>  #define MII_M1011_IEVENT		19

> @@ -29,6 +30,8 @@

>  #define LED2_FORCE_ON					(0x8 << 8)

>  #define LEDMASK						GENMASK(11,8)

>  

> +#define MII_88E1318S_PHY_LED_POL_LED2		BIT(4)

> +

>  struct power_off_cfg {

>  	char *mdio_node_name;

>  	void (*phy_set_reg)(bool restart);

> @@ -76,11 +79,48 @@ static void linkstation_mvphy_reg_intn(bool restart)

>  		dev_err(&phydev->mdio.dev, "Write register failed, %d\n", rc);

>  }

>  

> +static void readynas_mvphy_set_reg(bool restart)

> +{

> +	int rc = 0, saved_page;

> +	u16 data = 0;

> +

> +	if (restart)

> +		data = MII_88E1318S_PHY_LED_POL_LED2;

> +

> +	saved_page = phy_select_page(phydev, MII_MARVELL_LED_PAGE);

> +	if (saved_page < 0)

> +		goto err;

> +

> +	/* Set the LED[2].0 Polarity bit to the required state */

> +	__phy_modify(phydev, MII_PHY_LED_POL_CTRL,

> +		     MII_88E1318S_PHY_LED_POL_LED2, data);

> +

> +	if (!data) {

> +

> +		/* If WOL was enabled and a magic packet was received before powering

> +		 * off, we won't be able to wake up by sending another magic packet.

> +		 * Clear WOL status.

> +		 */

> +		__phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_WOL_PAGE);

> +		__phy_set_bits(phydev, MII_88E1318S_PHY_WOL_CTRL,

> +			       MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS);

> +	}

> +err:

> +	rc = phy_restore_page(phydev, saved_page, rc);

> +	if (rc < 0)

> +		dev_err(&phydev->mdio.dev, "Write register failed, %d\n", rc);

> +}

> +

>  static const struct power_off_cfg linkstation_power_off_cfg = {

>  	.mdio_node_name = "mdio",

>  	.phy_set_reg = linkstation_mvphy_reg_intn,

>  };

>  

> +static const struct power_off_cfg readynas_power_off_cfg = {

> +	.mdio_node_name = "mdio-bus",

> +	.phy_set_reg = readynas_mvphy_set_reg,

> +};

> +

>  static int linkstation_reboot_notifier(struct notifier_block *nb,

>  				       unsigned long action, void *unused)

>  {

> @@ -109,6 +149,9 @@ static const struct of_device_id ls_poweroff_of_match[] = {

>  	{ .compatible = "buffalo,ls421de",

>  	  .data = &linkstation_power_off_cfg,

>  	},

> +	{ .compatible = "netgear,readynas-duo-v2",

> +	  .data = &readynas_power_off_cfg,

> +	},

>  	{ },

>  };

>  

> -- 

> 2.25.1

>
diff mbox series

Patch

diff --git a/drivers/power/reset/linkstation-poweroff.c b/drivers/power/reset/linkstation-poweroff.c
index f1e843df0e16..cb5a32f852c1 100644
--- a/drivers/power/reset/linkstation-poweroff.c
+++ b/drivers/power/reset/linkstation-poweroff.c
@@ -29,11 +29,21 @@ 
 #define LED2_FORCE_ON					(0x8 << 8)
 #define LEDMASK						GENMASK(11,8)
 
+struct power_off_cfg {
+	char *mdio_node_name;
+	void (*phy_set_reg)(bool restart);
+};
+
 static struct phy_device *phydev;
+static const struct power_off_cfg *cfg;
 
-static void mvphy_reg_intn(u16 data)
+static void linkstation_mvphy_reg_intn(bool restart)
 {
 	int rc = 0, saved_page;
+	u16 data = 0;
+
+	if (restart)
+		data = MII_88E1318S_PHY_LED_TCR_FORCE_INT;
 
 	saved_page = phy_select_page(phydev, MII_MARVELL_LED_PAGE);
 	if (saved_page < 0)
@@ -66,11 +76,16 @@  static void mvphy_reg_intn(u16 data)
 		dev_err(&phydev->mdio.dev, "Write register failed, %d\n", rc);
 }
 
+static const struct power_off_cfg linkstation_power_off_cfg = {
+	.mdio_node_name = "mdio",
+	.phy_set_reg = linkstation_mvphy_reg_intn,
+};
+
 static int linkstation_reboot_notifier(struct notifier_block *nb,
 				       unsigned long action, void *unused)
 {
 	if (action == SYS_RESTART)
-		mvphy_reg_intn(MII_88E1318S_PHY_LED_TCR_FORCE_INT);
+		cfg->phy_set_reg(true);
 
 	return NOTIFY_DONE;
 }
@@ -82,14 +97,18 @@  static struct notifier_block linkstation_reboot_nb = {
 static void linkstation_poweroff(void)
 {
 	unregister_reboot_notifier(&linkstation_reboot_nb);
-	mvphy_reg_intn(0);
+	cfg->phy_set_reg(false);
 
 	kernel_restart("Power off");
 }
 
 static const struct of_device_id ls_poweroff_of_match[] = {
-	{ .compatible = "buffalo,ls421d" },
-	{ .compatible = "buffalo,ls421de" },
+	{ .compatible = "buffalo,ls421d",
+	  .data = &linkstation_power_off_cfg,
+	},
+	{ .compatible = "buffalo,ls421de",
+	  .data = &linkstation_power_off_cfg,
+	},
 	{ },
 };
 
@@ -97,13 +116,17 @@  static int __init linkstation_poweroff_init(void)
 {
 	struct mii_bus *bus;
 	struct device_node *dn;
+	const struct of_device_id *match;
 
 	dn = of_find_matching_node(NULL, ls_poweroff_of_match);
 	if (!dn)
 		return -ENODEV;
 	of_node_put(dn);
 
-	dn = of_find_node_by_name(NULL, "mdio");
+	match = of_match_node(ls_poweroff_of_match, dn);
+	cfg = match->data;
+
+	dn = of_find_node_by_name(NULL, cfg->mdio_node_name);
 	if (!dn)
 		return -ENODEV;