Commit b67f5502 authored by Colin Foster's avatar Colin Foster Committed by Jakub Kicinski
Browse files

net: mscc: ocelot: expose ocelot_reset routine



Resetting the switch core is the same whether it is done internally or
externally. Move this routine to the ocelot library so it can be used by
other drivers.

Signed-off-by: default avatarColin Foster <colin.foster@in-advantage.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Reviewed-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> # regression
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent beb9a74e
Loading
Loading
Loading
Loading
+46 −2
Original line number Diff line number Diff line
@@ -6,12 +6,16 @@
 */
#include <linux/dsa/ocelot.h>
#include <linux/if_bridge.h>
#include <linux/iopoll.h>
#include <soc/mscc/ocelot_vcap.h>
#include "ocelot.h"
#include "ocelot_vcap.h"

#define TABLE_UPDATE_SLEEP_US	10
#define TABLE_UPDATE_TIMEOUT_US	100000
#define MEM_INIT_SLEEP_US	1000
#define MEM_INIT_TIMEOUT_US	100000

#define OCELOT_RSV_VLAN_RANGE_START 4000

struct ocelot_mact_entry {
@@ -2713,6 +2717,46 @@ static void ocelot_detect_features(struct ocelot *ocelot)
	ocelot->num_frame_refs = QSYS_MMGT_EQ_CTRL_FP_FREE_CNT(eq_ctrl);
}

static int ocelot_mem_init_status(struct ocelot *ocelot)
{
	unsigned int val;
	int err;

	err = regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
				&val);

	return err ?: val;
}

int ocelot_reset(struct ocelot *ocelot)
{
	int err;
	u32 val;

	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
	if (err)
		return err;

	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
	if (err)
		return err;

	/* MEM_INIT is a self-clearing bit. Wait for it to be cleared (should be
	 * 100us) before enabling the switch core.
	 */
	err = readx_poll_timeout(ocelot_mem_init_status, ocelot, val, !val,
				 MEM_INIT_SLEEP_US, MEM_INIT_TIMEOUT_US);
	if (err)
		return err;

	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
	if (err)
		return err;

	return regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
}
EXPORT_SYMBOL(ocelot_reset);

int ocelot_init(struct ocelot *ocelot)
{
	int i, ret;
+1 −43
Original line number Diff line number Diff line
@@ -6,7 +6,6 @@
 */
#include <linux/dsa/ocelot.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_net.h>
#include <linux/netdevice.h>
@@ -17,6 +16,7 @@
#include <linux/skbuff.h>
#include <net/switchdev.h>

#include <soc/mscc/ocelot.h>
#include <soc/mscc/ocelot_vcap.h>
#include <soc/mscc/ocelot_hsio.h>
#include <soc/mscc/vsc7514_regs.h>
@@ -26,9 +26,6 @@
#define VSC7514_VCAP_POLICER_BASE			128
#define VSC7514_VCAP_POLICER_MAX			191

#define MEM_INIT_SLEEP_US				1000
#define MEM_INIT_TIMEOUT_US				100000

static const u32 *ocelot_regmap[TARGET_MAX] = {
	[ANA] = vsc7514_ana_regmap,
	[QS] = vsc7514_qs_regmap,
@@ -132,45 +129,6 @@ static const struct of_device_id mscc_ocelot_match[] = {
};
MODULE_DEVICE_TABLE(of, mscc_ocelot_match);

static int ocelot_mem_init_status(struct ocelot *ocelot)
{
	unsigned int val;
	int err;

	err = regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
				&val);

	return err ?: val;
}

static int ocelot_reset(struct ocelot *ocelot)
{
	int err;
	u32 val;

	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
	if (err)
		return err;

	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
	if (err)
		return err;

	/* MEM_INIT is a self-clearing bit. Wait for it to be cleared (should be
	 * 100us) before enabling the switch core.
	 */
	err = readx_poll_timeout(ocelot_mem_init_status, ocelot, val, !val,
				 MEM_INIT_SLEEP_US, MEM_INIT_TIMEOUT_US);
	if (err)
		return err;

	err = regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
	if (err)
		return err;

	return regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
}

static const struct ocelot_ops ocelot_ops = {
	.reset			= ocelot_reset,
	.wm_enc			= ocelot_wm_enc,
+1 −0
Original line number Diff line number Diff line
@@ -967,6 +967,7 @@ void ocelot_ptp_rx_timestamp(struct ocelot *ocelot, struct sk_buff *skb,
int ocelot_regfields_init(struct ocelot *ocelot,
			  const struct reg_field *const regfields);
struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res);
int ocelot_reset(struct ocelot *ocelot);
int ocelot_init(struct ocelot *ocelot);
void ocelot_deinit(struct ocelot *ocelot);
void ocelot_init_port(struct ocelot *ocelot, int port);