brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 60aa45b Raw
211 lines · c
1// SPDX-License-Identifier: GPL-2.02/* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */3#include "cphy.h"4#include "elmer0.h"5#include "suni1x10gexp_regs.h"6 7/* Port Reset */8static int my3126_reset(struct cphy *cphy, int wait)9{10	/*11	 * This can be done through registers.  It is not required since12	 * a full chip reset is used.13	 */14	return 0;15}16 17static int my3126_interrupt_enable(struct cphy *cphy)18{19	schedule_delayed_work(&cphy->phy_update, HZ/30);20	t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo);21	return 0;22}23 24static int my3126_interrupt_disable(struct cphy *cphy)25{26	cancel_delayed_work_sync(&cphy->phy_update);27	return 0;28}29 30static int my3126_interrupt_clear(struct cphy *cphy)31{32	return 0;33}34 35#define OFFSET(REG_ADDR)    (REG_ADDR << 2)36 37static int my3126_interrupt_handler(struct cphy *cphy)38{39	u32 val;40	u16 val16;41	u16 status;42	u32 act_count;43	adapter_t *adapter;44	adapter = cphy->adapter;45 46	if (cphy->count == 50) {47		cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);48		val16 = (u16) val;49		status = cphy->bmsr ^ val16;50 51		if (status & MDIO_STAT1_LSTATUS)52			t1_link_changed(adapter, 0);53		cphy->bmsr = val16;54 55		/* We have only enabled link change interrupts so it56		   must be that57		 */58		cphy->count = 0;59	}60 61	t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL),62		SUNI1x10GEXP_BITMSK_MSTAT_SNAP);63	t1_tpi_read(adapter,64		OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count);65	t1_tpi_read(adapter,66		OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val);67	act_count += val;68 69	/* Populate elmer_gpo with the register value */70	t1_tpi_read(adapter, A_ELMER0_GPO, &val);71	cphy->elmer_gpo = val;72 73	if ( (val & (1 << 8)) || (val & (1 << 19)) ||74	     (cphy->act_count == act_count) || cphy->act_on ) {75		if (is_T2(adapter))76			val |= (1 << 9);77		else if (t1_is_T1B(adapter))78			val |= (1 << 20);79		cphy->act_on = 0;80	} else {81		if (is_T2(adapter))82			val &= ~(1 << 9);83		else if (t1_is_T1B(adapter))84			val &= ~(1 << 20);85		cphy->act_on = 1;86	}87 88	t1_tpi_write(adapter, A_ELMER0_GPO, val);89 90	cphy->elmer_gpo = val;91	cphy->act_count = act_count;92	cphy->count++;93 94	return cphy_cause_link_change;95}96 97static void my3126_poll(struct work_struct *work)98{99	struct cphy *cphy = container_of(work, struct cphy, phy_update.work);100 101	my3126_interrupt_handler(cphy);102}103 104static int my3126_set_loopback(struct cphy *cphy, int on)105{106	return 0;107}108 109/* To check the activity LED */110static int my3126_get_link_status(struct cphy *cphy,111			int *link_ok, int *speed, int *duplex, int *fc)112{113	u32 val;114	u16 val16;115	adapter_t *adapter;116 117	adapter = cphy->adapter;118	cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val);119	val16 = (u16) val;120 121	/* Populate elmer_gpo with the register value */122	t1_tpi_read(adapter, A_ELMER0_GPO, &val);123	cphy->elmer_gpo = val;124 125	*link_ok = (val16 & MDIO_STAT1_LSTATUS);126 127	if (*link_ok) {128		/* Turn on the LED. */129		if (is_T2(adapter))130			 val &= ~(1 << 8);131		else if (t1_is_T1B(adapter))132			 val &= ~(1 << 19);133	} else {134		/* Turn off the LED. */135		if (is_T2(adapter))136			 val |= (1 << 8);137		else if (t1_is_T1B(adapter))138			 val |= (1 << 19);139	}140 141	t1_tpi_write(adapter, A_ELMER0_GPO, val);142	cphy->elmer_gpo = val;143	*speed = SPEED_10000;144	*duplex = DUPLEX_FULL;145 146	/* need to add flow control */147	if (fc)148		*fc = PAUSE_RX | PAUSE_TX;149 150	return 0;151}152 153static void my3126_destroy(struct cphy *cphy)154{155	kfree(cphy);156}157 158static const struct cphy_ops my3126_ops = {159	.destroy		= my3126_destroy,160	.reset			= my3126_reset,161	.interrupt_enable	= my3126_interrupt_enable,162	.interrupt_disable	= my3126_interrupt_disable,163	.interrupt_clear	= my3126_interrupt_clear,164	.interrupt_handler	= my3126_interrupt_handler,165	.get_link_status	= my3126_get_link_status,166	.set_loopback		= my3126_set_loopback,167	.mmds			= (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS |168				   MDIO_DEVS_PHYXS),169};170 171static struct cphy *my3126_phy_create(struct net_device *dev,172			int phy_addr, const struct mdio_ops *mdio_ops)173{174	struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL);175 176	if (!cphy)177		return NULL;178 179	cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops);180	INIT_DELAYED_WORK(&cphy->phy_update, my3126_poll);181	cphy->bmsr = 0;182 183	return cphy;184}185 186/* Chip Reset */187static int my3126_phy_reset(adapter_t * adapter)188{189	u32 val;190 191	t1_tpi_read(adapter, A_ELMER0_GPO, &val);192	val &= ~4;193	t1_tpi_write(adapter, A_ELMER0_GPO, val);194	msleep(100);195 196	t1_tpi_write(adapter, A_ELMER0_GPO, val | 4);197	msleep(1000);198 199	/* Now lets enable the Laser. Delay 100us */200	t1_tpi_read(adapter, A_ELMER0_GPO, &val);201	val |= 0x8000;202	t1_tpi_write(adapter, A_ELMER0_GPO, val);203	udelay(100);204	return 0;205}206 207const struct gphy t1_my3126_ops = {208	.create = my3126_phy_create,209	.reset = my3126_phy_reset210};211