cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

icplus.c (15269B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Driver for ICPlus PHYs
      4 *
      5 * Copyright (c) 2007 Freescale Semiconductor, Inc.
      6 */
      7#include <linux/kernel.h>
      8#include <linux/string.h>
      9#include <linux/errno.h>
     10#include <linux/unistd.h>
     11#include <linux/interrupt.h>
     12#include <linux/init.h>
     13#include <linux/delay.h>
     14#include <linux/netdevice.h>
     15#include <linux/etherdevice.h>
     16#include <linux/skbuff.h>
     17#include <linux/spinlock.h>
     18#include <linux/mm.h>
     19#include <linux/module.h>
     20#include <linux/mii.h>
     21#include <linux/ethtool.h>
     22#include <linux/phy.h>
     23#include <linux/property.h>
     24
     25#include <asm/io.h>
     26#include <asm/irq.h>
     27#include <linux/uaccess.h>
     28
     29MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IP101G/IC1001 PHY drivers");
     30MODULE_AUTHOR("Michael Barkowski");
     31MODULE_LICENSE("GPL");
     32
     33/* IP101A/G - IP1001 */
     34#define IP10XX_SPEC_CTRL_STATUS		16	/* Spec. Control Register */
     35#define IP1001_RXPHASE_SEL		BIT(0)	/* Add delay on RX_CLK */
     36#define IP1001_TXPHASE_SEL		BIT(1)	/* Add delay on TX_CLK */
     37#define IP1001_SPEC_CTRL_STATUS_2	20	/* IP1001 Spec. Control Reg 2 */
     38#define IP1001_APS_ON			11	/* IP1001 APS Mode  bit */
     39#define IP101A_G_APS_ON			BIT(1)	/* IP101A/G APS Mode bit */
     40#define IP101A_G_AUTO_MDIX_DIS		BIT(11)
     41#define IP101A_G_IRQ_CONF_STATUS	0x11	/* Conf Info IRQ & Status Reg */
     42#define	IP101A_G_IRQ_PIN_USED		BIT(15) /* INTR pin used */
     43#define IP101A_G_IRQ_ALL_MASK		BIT(11) /* IRQ's inactive */
     44#define IP101A_G_IRQ_SPEED_CHANGE	BIT(2)
     45#define IP101A_G_IRQ_DUPLEX_CHANGE	BIT(1)
     46#define IP101A_G_IRQ_LINK_CHANGE	BIT(0)
     47#define IP101A_G_PHY_STATUS		18
     48#define IP101A_G_MDIX			BIT(9)
     49#define IP101A_G_PHY_SPEC_CTRL		30
     50#define IP101A_G_FORCE_MDIX		BIT(3)
     51
     52#define IP101G_PAGE_CONTROL				0x14
     53#define IP101G_PAGE_CONTROL_MASK			GENMASK(4, 0)
     54#define IP101G_DIGITAL_IO_SPEC_CTRL			0x1d
     55#define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32		BIT(2)
     56
     57#define IP101G_DEFAULT_PAGE			16
     58
     59#define IP101G_P1_CNT_CTRL		17
     60#define CNT_CTRL_RX_EN			BIT(13)
     61#define IP101G_P8_CNT_CTRL		17
     62#define CNT_CTRL_RDCLR_EN		BIT(15)
     63#define IP101G_CNT_REG			18
     64
     65#define IP175C_PHY_ID 0x02430d80
     66#define IP1001_PHY_ID 0x02430d90
     67#define IP101A_PHY_ID 0x02430c54
     68
     69/* The 32-pin IP101GR package can re-configure the mode of the RXER/INTR_32 pin
     70 * (pin number 21). The hardware default is RXER (receive error) mode. But it
     71 * can be configured to interrupt mode manually.
     72 */
     73enum ip101gr_sel_intr32 {
     74	IP101GR_SEL_INTR32_KEEP,
     75	IP101GR_SEL_INTR32_INTR,
     76	IP101GR_SEL_INTR32_RXER,
     77};
     78
     79struct ip101g_hw_stat {
     80	const char *name;
     81	int page;
     82};
     83
     84static struct ip101g_hw_stat ip101g_hw_stats[] = {
     85	{ "phy_crc_errors", 1 },
     86	{ "phy_symbol_errors", 11, },
     87};
     88
     89struct ip101a_g_phy_priv {
     90	enum ip101gr_sel_intr32 sel_intr32;
     91	u64 stats[ARRAY_SIZE(ip101g_hw_stats)];
     92};
     93
     94static int ip175c_config_init(struct phy_device *phydev)
     95{
     96	int err, i;
     97	static int full_reset_performed;
     98
     99	if (full_reset_performed == 0) {
    100
    101		/* master reset */
    102		err = mdiobus_write(phydev->mdio.bus, 30, 0, 0x175c);
    103		if (err < 0)
    104			return err;
    105
    106		/* ensure no bus delays overlap reset period */
    107		err = mdiobus_read(phydev->mdio.bus, 30, 0);
    108
    109		/* data sheet specifies reset period is 2 msec */
    110		mdelay(2);
    111
    112		/* enable IP175C mode */
    113		err = mdiobus_write(phydev->mdio.bus, 29, 31, 0x175c);
    114		if (err < 0)
    115			return err;
    116
    117		/* Set MII0 speed and duplex (in PHY mode) */
    118		err = mdiobus_write(phydev->mdio.bus, 29, 22, 0x420);
    119		if (err < 0)
    120			return err;
    121
    122		/* reset switch ports */
    123		for (i = 0; i < 5; i++) {
    124			err = mdiobus_write(phydev->mdio.bus, i,
    125					    MII_BMCR, BMCR_RESET);
    126			if (err < 0)
    127				return err;
    128		}
    129
    130		for (i = 0; i < 5; i++)
    131			err = mdiobus_read(phydev->mdio.bus, i, MII_BMCR);
    132
    133		mdelay(2);
    134
    135		full_reset_performed = 1;
    136	}
    137
    138	if (phydev->mdio.addr != 4) {
    139		phydev->state = PHY_RUNNING;
    140		phydev->speed = SPEED_100;
    141		phydev->duplex = DUPLEX_FULL;
    142		phydev->link = 1;
    143		netif_carrier_on(phydev->attached_dev);
    144	}
    145
    146	return 0;
    147}
    148
    149static int ip1001_config_init(struct phy_device *phydev)
    150{
    151	int c;
    152
    153	/* Enable Auto Power Saving mode */
    154	c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2);
    155	if (c < 0)
    156		return c;
    157	c |= IP1001_APS_ON;
    158	c = phy_write(phydev, IP1001_SPEC_CTRL_STATUS_2, c);
    159	if (c < 0)
    160		return c;
    161
    162	if (phy_interface_is_rgmii(phydev)) {
    163
    164		c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
    165		if (c < 0)
    166			return c;
    167
    168		c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
    169
    170		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
    171			c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
    172		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
    173			c |= IP1001_RXPHASE_SEL;
    174		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
    175			c |= IP1001_TXPHASE_SEL;
    176
    177		c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
    178		if (c < 0)
    179			return c;
    180	}
    181
    182	return 0;
    183}
    184
    185static int ip175c_read_status(struct phy_device *phydev)
    186{
    187	if (phydev->mdio.addr == 4) /* WAN port */
    188		genphy_read_status(phydev);
    189	else
    190		/* Don't need to read status for switch ports */
    191		phydev->irq = PHY_MAC_INTERRUPT;
    192
    193	return 0;
    194}
    195
    196static int ip175c_config_aneg(struct phy_device *phydev)
    197{
    198	if (phydev->mdio.addr == 4) /* WAN port */
    199		genphy_config_aneg(phydev);
    200
    201	return 0;
    202}
    203
    204static int ip101a_g_probe(struct phy_device *phydev)
    205{
    206	struct device *dev = &phydev->mdio.dev;
    207	struct ip101a_g_phy_priv *priv;
    208
    209	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    210	if (!priv)
    211		return -ENOMEM;
    212
    213	/* Both functions (RX error and interrupt status) are sharing the same
    214	 * pin on the 32-pin IP101GR, so this is an exclusive choice.
    215	 */
    216	if (device_property_read_bool(dev, "icplus,select-rx-error") &&
    217	    device_property_read_bool(dev, "icplus,select-interrupt")) {
    218		dev_err(dev,
    219			"RXER and INTR mode cannot be selected together\n");
    220		return -EINVAL;
    221	}
    222
    223	if (device_property_read_bool(dev, "icplus,select-rx-error"))
    224		priv->sel_intr32 = IP101GR_SEL_INTR32_RXER;
    225	else if (device_property_read_bool(dev, "icplus,select-interrupt"))
    226		priv->sel_intr32 = IP101GR_SEL_INTR32_INTR;
    227	else
    228		priv->sel_intr32 = IP101GR_SEL_INTR32_KEEP;
    229
    230	phydev->priv = priv;
    231
    232	return 0;
    233}
    234
    235static int ip101a_g_config_intr_pin(struct phy_device *phydev)
    236{
    237	struct ip101a_g_phy_priv *priv = phydev->priv;
    238	int oldpage, err = 0;
    239
    240	oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
    241	if (oldpage < 0)
    242		goto out;
    243
    244	/* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */
    245	switch (priv->sel_intr32) {
    246	case IP101GR_SEL_INTR32_RXER:
    247		err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
    248				   IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0);
    249		if (err < 0)
    250			goto out;
    251		break;
    252
    253	case IP101GR_SEL_INTR32_INTR:
    254		err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
    255				   IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,
    256				   IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);
    257		if (err < 0)
    258			goto out;
    259		break;
    260
    261	default:
    262		/* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not
    263		 * documented on IP101A and it's not clear whether this would
    264		 * cause problems.
    265		 * For the 32-pin IP101GR we simply keep the SEL_INTR32
    266		 * configuration as set by the bootloader when not configured
    267		 * to one of the special functions.
    268		 */
    269		break;
    270	}
    271
    272out:
    273	return phy_restore_page(phydev, oldpage, err);
    274}
    275
    276static int ip101a_config_init(struct phy_device *phydev)
    277{
    278	int ret;
    279
    280	/* Enable Auto Power Saving mode */
    281	ret = phy_set_bits(phydev, IP10XX_SPEC_CTRL_STATUS, IP101A_G_APS_ON);
    282	if (ret)
    283		return ret;
    284
    285	return ip101a_g_config_intr_pin(phydev);
    286}
    287
    288static int ip101g_config_init(struct phy_device *phydev)
    289{
    290	int ret;
    291
    292	/* Enable the PHY counters */
    293	ret = phy_modify_paged(phydev, 1, IP101G_P1_CNT_CTRL,
    294			       CNT_CTRL_RX_EN, CNT_CTRL_RX_EN);
    295	if (ret)
    296		return ret;
    297
    298	/* Clear error counters on read */
    299	ret = phy_modify_paged(phydev, 8, IP101G_P8_CNT_CTRL,
    300			       CNT_CTRL_RDCLR_EN, CNT_CTRL_RDCLR_EN);
    301	if (ret)
    302		return ret;
    303
    304	return ip101a_g_config_intr_pin(phydev);
    305}
    306
    307static int ip101a_g_read_status(struct phy_device *phydev)
    308{
    309	int oldpage, ret, stat1, stat2;
    310
    311	ret = genphy_read_status(phydev);
    312	if (ret)
    313		return ret;
    314
    315	oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
    316	if (oldpage < 0)
    317		goto out;
    318
    319	ret = __phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
    320	if (ret < 0)
    321		goto out;
    322	stat1 = ret;
    323
    324	ret = __phy_read(phydev, IP101A_G_PHY_SPEC_CTRL);
    325	if (ret < 0)
    326		goto out;
    327	stat2 = ret;
    328
    329	if (stat1 & IP101A_G_AUTO_MDIX_DIS) {
    330		if (stat2 & IP101A_G_FORCE_MDIX)
    331			phydev->mdix_ctrl = ETH_TP_MDI_X;
    332		else
    333			phydev->mdix_ctrl = ETH_TP_MDI;
    334	} else {
    335		phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
    336	}
    337
    338	if (stat2 & IP101A_G_MDIX)
    339		phydev->mdix = ETH_TP_MDI_X;
    340	else
    341		phydev->mdix = ETH_TP_MDI;
    342
    343	ret = 0;
    344
    345out:
    346	return phy_restore_page(phydev, oldpage, ret);
    347}
    348
    349static int ip101a_g_config_mdix(struct phy_device *phydev)
    350{
    351	u16 ctrl = 0, ctrl2 = 0;
    352	int oldpage;
    353	int ret = 0;
    354
    355	switch (phydev->mdix_ctrl) {
    356	case ETH_TP_MDI:
    357		ctrl = IP101A_G_AUTO_MDIX_DIS;
    358		break;
    359	case ETH_TP_MDI_X:
    360		ctrl = IP101A_G_AUTO_MDIX_DIS;
    361		ctrl2 = IP101A_G_FORCE_MDIX;
    362		break;
    363	case ETH_TP_MDI_AUTO:
    364		break;
    365	default:
    366		return 0;
    367	}
    368
    369	oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
    370	if (oldpage < 0)
    371		goto out;
    372
    373	ret = __phy_modify(phydev, IP10XX_SPEC_CTRL_STATUS,
    374			   IP101A_G_AUTO_MDIX_DIS, ctrl);
    375	if (ret)
    376		goto out;
    377
    378	ret = __phy_modify(phydev, IP101A_G_PHY_SPEC_CTRL,
    379			   IP101A_G_FORCE_MDIX, ctrl2);
    380
    381out:
    382	return phy_restore_page(phydev, oldpage, ret);
    383}
    384
    385static int ip101a_g_config_aneg(struct phy_device *phydev)
    386{
    387	int ret;
    388
    389	ret = ip101a_g_config_mdix(phydev);
    390	if (ret)
    391		return ret;
    392
    393	return genphy_config_aneg(phydev);
    394}
    395
    396static int ip101a_g_ack_interrupt(struct phy_device *phydev)
    397{
    398	int err;
    399
    400	err = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
    401			     IP101A_G_IRQ_CONF_STATUS);
    402	if (err < 0)
    403		return err;
    404
    405	return 0;
    406}
    407
    408static int ip101a_g_config_intr(struct phy_device *phydev)
    409{
    410	u16 val;
    411	int err;
    412
    413	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
    414		err = ip101a_g_ack_interrupt(phydev);
    415		if (err)
    416			return err;
    417
    418		/* INTR pin used: Speed/link/duplex will cause an interrupt */
    419		val = IP101A_G_IRQ_PIN_USED;
    420		err = phy_write_paged(phydev, IP101G_DEFAULT_PAGE,
    421				      IP101A_G_IRQ_CONF_STATUS, val);
    422	} else {
    423		val = IP101A_G_IRQ_ALL_MASK;
    424		err = phy_write_paged(phydev, IP101G_DEFAULT_PAGE,
    425				      IP101A_G_IRQ_CONF_STATUS, val);
    426		if (err)
    427			return err;
    428
    429		err = ip101a_g_ack_interrupt(phydev);
    430	}
    431
    432	return err;
    433}
    434
    435static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev)
    436{
    437	int irq_status;
    438
    439	irq_status = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
    440				    IP101A_G_IRQ_CONF_STATUS);
    441	if (irq_status < 0) {
    442		phy_error(phydev);
    443		return IRQ_NONE;
    444	}
    445
    446	if (!(irq_status & (IP101A_G_IRQ_SPEED_CHANGE |
    447			    IP101A_G_IRQ_DUPLEX_CHANGE |
    448			    IP101A_G_IRQ_LINK_CHANGE)))
    449		return IRQ_NONE;
    450
    451	phy_trigger_machine(phydev);
    452
    453	return IRQ_HANDLED;
    454}
    455
    456/* The IP101A doesn't really have a page register. We just pretend to have one
    457 * so we can use the paged versions of the callbacks of the IP101G.
    458 */
    459static int ip101a_read_page(struct phy_device *phydev)
    460{
    461	return IP101G_DEFAULT_PAGE;
    462}
    463
    464static int ip101a_write_page(struct phy_device *phydev, int page)
    465{
    466	WARN_ONCE(page != IP101G_DEFAULT_PAGE, "wrong page selected\n");
    467
    468	return 0;
    469}
    470
    471static int ip101g_read_page(struct phy_device *phydev)
    472{
    473	return __phy_read(phydev, IP101G_PAGE_CONTROL);
    474}
    475
    476static int ip101g_write_page(struct phy_device *phydev, int page)
    477{
    478	return __phy_write(phydev, IP101G_PAGE_CONTROL, page);
    479}
    480
    481static int ip101a_g_has_page_register(struct phy_device *phydev)
    482{
    483	int oldval, val, ret;
    484
    485	oldval = phy_read(phydev, IP101G_PAGE_CONTROL);
    486	if (oldval < 0)
    487		return oldval;
    488
    489	ret = phy_write(phydev, IP101G_PAGE_CONTROL, 0xffff);
    490	if (ret)
    491		return ret;
    492
    493	val = phy_read(phydev, IP101G_PAGE_CONTROL);
    494	if (val < 0)
    495		return val;
    496
    497	ret = phy_write(phydev, IP101G_PAGE_CONTROL, oldval);
    498	if (ret)
    499		return ret;
    500
    501	return val == IP101G_PAGE_CONTROL_MASK;
    502}
    503
    504static int ip101a_g_match_phy_device(struct phy_device *phydev, bool ip101a)
    505{
    506	int ret;
    507
    508	if (phydev->phy_id != IP101A_PHY_ID)
    509		return 0;
    510
    511	/* The IP101A and the IP101G share the same PHY identifier.The IP101G
    512	 * seems to be a successor of the IP101A and implements more functions.
    513	 * Amongst other things there is a page select register, which is not
    514	 * available on the IP101A. Use this to distinguish these two.
    515	 */
    516	ret = ip101a_g_has_page_register(phydev);
    517	if (ret < 0)
    518		return ret;
    519
    520	return ip101a == !ret;
    521}
    522
    523static int ip101a_match_phy_device(struct phy_device *phydev)
    524{
    525	return ip101a_g_match_phy_device(phydev, true);
    526}
    527
    528static int ip101g_match_phy_device(struct phy_device *phydev)
    529{
    530	return ip101a_g_match_phy_device(phydev, false);
    531}
    532
    533static int ip101g_get_sset_count(struct phy_device *phydev)
    534{
    535	return ARRAY_SIZE(ip101g_hw_stats);
    536}
    537
    538static void ip101g_get_strings(struct phy_device *phydev, u8 *data)
    539{
    540	int i;
    541
    542	for (i = 0; i < ARRAY_SIZE(ip101g_hw_stats); i++)
    543		strscpy(data + i * ETH_GSTRING_LEN,
    544			ip101g_hw_stats[i].name, ETH_GSTRING_LEN);
    545}
    546
    547static u64 ip101g_get_stat(struct phy_device *phydev, int i)
    548{
    549	struct ip101g_hw_stat stat = ip101g_hw_stats[i];
    550	struct ip101a_g_phy_priv *priv = phydev->priv;
    551	int val;
    552	u64 ret;
    553
    554	val = phy_read_paged(phydev, stat.page, IP101G_CNT_REG);
    555	if (val < 0) {
    556		ret = U64_MAX;
    557	} else {
    558		priv->stats[i] += val;
    559		ret = priv->stats[i];
    560	}
    561
    562	return ret;
    563}
    564
    565static void ip101g_get_stats(struct phy_device *phydev,
    566			     struct ethtool_stats *stats, u64 *data)
    567{
    568	int i;
    569
    570	for (i = 0; i < ARRAY_SIZE(ip101g_hw_stats); i++)
    571		data[i] = ip101g_get_stat(phydev, i);
    572}
    573
    574static struct phy_driver icplus_driver[] = {
    575{
    576	PHY_ID_MATCH_MODEL(IP175C_PHY_ID),
    577	.name		= "ICPlus IP175C",
    578	/* PHY_BASIC_FEATURES */
    579	.config_init	= ip175c_config_init,
    580	.config_aneg	= ip175c_config_aneg,
    581	.read_status	= ip175c_read_status,
    582	.suspend	= genphy_suspend,
    583	.resume		= genphy_resume,
    584}, {
    585	PHY_ID_MATCH_MODEL(IP1001_PHY_ID),
    586	.name		= "ICPlus IP1001",
    587	/* PHY_GBIT_FEATURES */
    588	.config_init	= ip1001_config_init,
    589	.soft_reset	= genphy_soft_reset,
    590	.suspend	= genphy_suspend,
    591	.resume		= genphy_resume,
    592}, {
    593	.name		= "ICPlus IP101A",
    594	.match_phy_device = ip101a_match_phy_device,
    595	.probe		= ip101a_g_probe,
    596	.read_page	= ip101a_read_page,
    597	.write_page	= ip101a_write_page,
    598	.config_intr	= ip101a_g_config_intr,
    599	.handle_interrupt = ip101a_g_handle_interrupt,
    600	.config_init	= ip101a_config_init,
    601	.config_aneg	= ip101a_g_config_aneg,
    602	.read_status	= ip101a_g_read_status,
    603	.soft_reset	= genphy_soft_reset,
    604	.suspend	= genphy_suspend,
    605	.resume		= genphy_resume,
    606}, {
    607	.name		= "ICPlus IP101G",
    608	.match_phy_device = ip101g_match_phy_device,
    609	.probe		= ip101a_g_probe,
    610	.read_page	= ip101g_read_page,
    611	.write_page	= ip101g_write_page,
    612	.config_intr	= ip101a_g_config_intr,
    613	.handle_interrupt = ip101a_g_handle_interrupt,
    614	.config_init	= ip101g_config_init,
    615	.config_aneg	= ip101a_g_config_aneg,
    616	.read_status	= ip101a_g_read_status,
    617	.soft_reset	= genphy_soft_reset,
    618	.get_sset_count = ip101g_get_sset_count,
    619	.get_strings	= ip101g_get_strings,
    620	.get_stats	= ip101g_get_stats,
    621	.suspend	= genphy_suspend,
    622	.resume		= genphy_resume,
    623} };
    624
    625module_phy_driver(icplus_driver);
    626
    627static struct mdio_device_id __maybe_unused icplus_tbl[] = {
    628	{ PHY_ID_MATCH_MODEL(IP175C_PHY_ID) },
    629	{ PHY_ID_MATCH_MODEL(IP1001_PHY_ID) },
    630	{ PHY_ID_MATCH_EXACT(IP101A_PHY_ID) },
    631	{ }
    632};
    633
    634MODULE_DEVICE_TABLE(mdio, icplus_tbl);