File Index
Files and directories
Sign in
FILE

air_en8811h.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/phy/air_en8811h.c C
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Driver for the Airoha EN8811H 2.5 Gigabit PHY.
   4 *
   5 * Limitations of the EN8811H:
   6 * - Only full duplex supported
   7 * - Forced speed (AN off) is not supported by hardware (100Mbps)
   8 *
   9 * Source originated from airoha's en8811h.c and en8811h.h v1.2.1
  10 *
  11 * Copyright (C) 2023 Airoha Technology Corp.
  12 */
  13
  14#include <linux/clk.h>
  15#include <linux/clk-provider.h>
  16#include <linux/phy.h>
  17#include <linux/firmware.h>
  18#include <linux/property.h>
  19#include <linux/wordpart.h>
  20#include <linux/unaligned.h>
  21
  22#define EN8811H_PHY_ID		0x03a2a411
  23
  24#define EN8811H_MD32_DM		"airoha/EthMD32.dm.bin"
  25#define EN8811H_MD32_DSP	"airoha/EthMD32.DSP.bin"
  26
  27#define AIR_FW_ADDR_DM	0x00000000
  28#define AIR_FW_ADDR_DSP	0x00100000
  29
  30/* MII Registers */
  31#define AIR_AUX_CTRL_STATUS		0x1d
  32#define   AIR_AUX_CTRL_STATUS_SPEED_MASK	GENMASK(4, 2)
  33#define   AIR_AUX_CTRL_STATUS_SPEED_100		0x4
  34#define   AIR_AUX_CTRL_STATUS_SPEED_1000	0x8
  35#define   AIR_AUX_CTRL_STATUS_SPEED_2500	0xc
  36
  37#define AIR_EXT_PAGE_ACCESS		0x1f
  38#define   AIR_PHY_PAGE_STANDARD			0x0000
  39#define   AIR_PHY_PAGE_EXTENDED_4		0x0004
  40
  41/* MII Registers Page 4*/
  42#define AIR_BPBUS_MODE			0x10
  43#define   AIR_BPBUS_MODE_ADDR_FIXED		0x0000
  44#define   AIR_BPBUS_MODE_ADDR_INCR		BIT(15)
  45#define AIR_BPBUS_WR_ADDR_HIGH		0x11
  46#define AIR_BPBUS_WR_ADDR_LOW		0x12
  47#define AIR_BPBUS_WR_DATA_HIGH		0x13
  48#define AIR_BPBUS_WR_DATA_LOW		0x14
  49#define AIR_BPBUS_RD_ADDR_HIGH		0x15
  50#define AIR_BPBUS_RD_ADDR_LOW		0x16
  51#define AIR_BPBUS_RD_DATA_HIGH		0x17
  52#define AIR_BPBUS_RD_DATA_LOW		0x18
  53
  54/* Registers on MDIO_MMD_VEND1 */
  55#define EN8811H_PHY_FW_STATUS		0x8009
  56#define   EN8811H_PHY_READY			0x02
  57
  58#define AIR_PHY_MCU_CMD_1		0x800c
  59#define AIR_PHY_MCU_CMD_1_MODE1			0x0
  60#define AIR_PHY_MCU_CMD_2		0x800d
  61#define AIR_PHY_MCU_CMD_2_MODE1			0x0
  62#define AIR_PHY_MCU_CMD_3		0x800e
  63#define AIR_PHY_MCU_CMD_3_MODE1			0x1101
  64#define AIR_PHY_MCU_CMD_3_DOCMD			0x1100
  65#define AIR_PHY_MCU_CMD_4		0x800f
  66#define AIR_PHY_MCU_CMD_4_MODE1			0x0002
  67#define AIR_PHY_MCU_CMD_4_INTCLR		0x00e4
  68
  69/* Registers on MDIO_MMD_VEND2 */
  70#define AIR_PHY_LED_BCR			0x021
  71#define   AIR_PHY_LED_BCR_MODE_MASK		GENMASK(1, 0)
  72#define   AIR_PHY_LED_BCR_TIME_TEST		BIT(2)
  73#define   AIR_PHY_LED_BCR_CLK_EN		BIT(3)
  74#define   AIR_PHY_LED_BCR_EXT_CTRL		BIT(15)
  75
  76#define AIR_PHY_LED_DUR_ON		0x022
  77
  78#define AIR_PHY_LED_DUR_BLINK		0x023
  79
  80#define AIR_PHY_LED_ON(i)	       (0x024 + ((i) * 2))
  81#define   AIR_PHY_LED_ON_MASK			(GENMASK(6, 0) | BIT(8))
  82#define   AIR_PHY_LED_ON_LINK1000		BIT(0)
  83#define   AIR_PHY_LED_ON_LINK100		BIT(1)
  84#define   AIR_PHY_LED_ON_LINK10			BIT(2)
  85#define   AIR_PHY_LED_ON_LINKDOWN		BIT(3)
  86#define   AIR_PHY_LED_ON_FDX			BIT(4) /* Full duplex */
  87#define   AIR_PHY_LED_ON_HDX			BIT(5) /* Half duplex */
  88#define   AIR_PHY_LED_ON_FORCE_ON		BIT(6)
  89#define   AIR_PHY_LED_ON_LINK2500		BIT(8)
  90#define   AIR_PHY_LED_ON_POLARITY		BIT(14)
  91#define   AIR_PHY_LED_ON_ENABLE			BIT(15)
  92
  93#define AIR_PHY_LED_BLINK(i)	       (0x025 + ((i) * 2))
  94#define   AIR_PHY_LED_BLINK_1000TX		BIT(0)
  95#define   AIR_PHY_LED_BLINK_1000RX		BIT(1)
  96#define   AIR_PHY_LED_BLINK_100TX		BIT(2)
  97#define   AIR_PHY_LED_BLINK_100RX		BIT(3)
  98#define   AIR_PHY_LED_BLINK_10TX		BIT(4)
  99#define   AIR_PHY_LED_BLINK_10RX		BIT(5)
 100#define   AIR_PHY_LED_BLINK_COLLISION		BIT(6)
 101#define   AIR_PHY_LED_BLINK_RX_CRC_ERR		BIT(7)
 102#define   AIR_PHY_LED_BLINK_RX_IDLE_ERR		BIT(8)
 103#define   AIR_PHY_LED_BLINK_FORCE_BLINK		BIT(9)
 104#define   AIR_PHY_LED_BLINK_2500TX		BIT(10)
 105#define   AIR_PHY_LED_BLINK_2500RX		BIT(11)
 106
 107/* Registers on BUCKPBUS */
 108#define EN8811H_2P5G_LPA		0x3b30
 109#define   EN8811H_2P5G_LPA_2P5G			BIT(0)
 110
 111#define EN8811H_FW_VERSION		0x3b3c
 112
 113#define EN8811H_POLARITY		0xca0f8
 114#define   EN8811H_POLARITY_TX_NORMAL		BIT(0)
 115#define   EN8811H_POLARITY_RX_REVERSE		BIT(1)
 116
 117#define EN8811H_GPIO_OUTPUT		0xcf8b8
 118#define   EN8811H_GPIO_OUTPUT_345		(BIT(3) | BIT(4) | BIT(5))
 119
 120#define EN8811H_HWTRAP1			0xcf914
 121#define   EN8811H_HWTRAP1_CKO			BIT(12)
 122#define EN8811H_CLK_CGM			0xcf958
 123#define   EN8811H_CLK_CGM_CKO			BIT(26)
 124
 125#define EN8811H_FW_CTRL_1		0x0f0018
 126#define   EN8811H_FW_CTRL_1_START		0x0
 127#define   EN8811H_FW_CTRL_1_FINISH		0x1
 128#define EN8811H_FW_CTRL_2		0x800000
 129#define EN8811H_FW_CTRL_2_LOADING		BIT(11)
 130
 131/* Led definitions */
 132#define EN8811H_LED_COUNT	3
 133
 134/* Default LED setup:
 135 * GPIO5 <-> LED0  On: Link detected, blink Rx/Tx
 136 * GPIO4 <-> LED1  On: Link detected at 2500 or 1000 Mbps
 137 * GPIO3 <-> LED2  On: Link detected at 2500 or  100 Mbps
 138 */
 139#define AIR_DEFAULT_TRIGGER_LED0 (BIT(TRIGGER_NETDEV_LINK)      | \
 140				  BIT(TRIGGER_NETDEV_RX)        | \
 141				  BIT(TRIGGER_NETDEV_TX))
 142#define AIR_DEFAULT_TRIGGER_LED1 (BIT(TRIGGER_NETDEV_LINK_2500) | \
 143				  BIT(TRIGGER_NETDEV_LINK_1000))
 144#define AIR_DEFAULT_TRIGGER_LED2 (BIT(TRIGGER_NETDEV_LINK_2500) | \
 145				  BIT(TRIGGER_NETDEV_LINK_100))
 146
 147struct led {
 148	unsigned long rules;
 149	unsigned long state;
 150};
 151
 152#define clk_hw_to_en8811h_priv(_hw)			\
 153	container_of(_hw, struct en8811h_priv, hw)
 154
 155struct en8811h_priv {
 156	u32			firmware_version;
 157	bool			mcu_needs_restart;
 158	struct led		led[EN8811H_LED_COUNT];
 159	struct clk_hw		hw;
 160	struct phy_device	*phydev;
 161	unsigned int		cko_is_enabled;
 162};
 163
 164enum {
 165	AIR_PHY_LED_STATE_FORCE_ON,
 166	AIR_PHY_LED_STATE_FORCE_BLINK,
 167};
 168
 169enum {
 170	AIR_PHY_LED_DUR_BLINK_32MS,
 171	AIR_PHY_LED_DUR_BLINK_64MS,
 172	AIR_PHY_LED_DUR_BLINK_128MS,
 173	AIR_PHY_LED_DUR_BLINK_256MS,
 174	AIR_PHY_LED_DUR_BLINK_512MS,
 175	AIR_PHY_LED_DUR_BLINK_1024MS,
 176};
 177
 178enum {
 179	AIR_LED_DISABLE,
 180	AIR_LED_ENABLE,
 181};
 182
 183enum {
 184	AIR_ACTIVE_LOW,
 185	AIR_ACTIVE_HIGH,
 186};
 187
 188enum {
 189	AIR_LED_MODE_DISABLE,
 190	AIR_LED_MODE_USER_DEFINE,
 191};
 192
 193#define AIR_PHY_LED_DUR_UNIT	1024
 194#define AIR_PHY_LED_DUR (AIR_PHY_LED_DUR_UNIT << AIR_PHY_LED_DUR_BLINK_64MS)
 195
 196static const unsigned long en8811h_led_trig = BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
 197					      BIT(TRIGGER_NETDEV_LINK)        |
 198					      BIT(TRIGGER_NETDEV_LINK_10)     |
 199					      BIT(TRIGGER_NETDEV_LINK_100)    |
 200					      BIT(TRIGGER_NETDEV_LINK_1000)   |
 201					      BIT(TRIGGER_NETDEV_LINK_2500)   |
 202					      BIT(TRIGGER_NETDEV_RX)          |
 203					      BIT(TRIGGER_NETDEV_TX);
 204
 205static int air_phy_read_page(struct phy_device *phydev)
 206{
 207	return __phy_read(phydev, AIR_EXT_PAGE_ACCESS);
 208}
 209
 210static int air_phy_write_page(struct phy_device *phydev, int page)
 211{
 212	return __phy_write(phydev, AIR_EXT_PAGE_ACCESS, page);
 213}
 214
 215static int __air_buckpbus_reg_write(struct phy_device *phydev,
 216				    u32 pbus_address, u32 pbus_data)
 217{
 218	int ret;
 219
 220	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
 221	if (ret < 0)
 222		return ret;
 223
 224	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH,
 225			  upper_16_bits(pbus_address));
 226	if (ret < 0)
 227		return ret;
 228
 229	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW,
 230			  lower_16_bits(pbus_address));
 231	if (ret < 0)
 232		return ret;
 233
 234	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH,
 235			  upper_16_bits(pbus_data));
 236	if (ret < 0)
 237		return ret;
 238
 239	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW,
 240			  lower_16_bits(pbus_data));
 241	if (ret < 0)
 242		return ret;
 243
 244	return 0;
 245}
 246
 247static int air_buckpbus_reg_write(struct phy_device *phydev,
 248				  u32 pbus_address, u32 pbus_data)
 249{
 250	int saved_page;
 251	int ret = 0;
 252
 253	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
 254
 255	if (saved_page >= 0) {
 256		ret = __air_buckpbus_reg_write(phydev, pbus_address,
 257					       pbus_data);
 258		if (ret < 0)
 259			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
 260				   pbus_address, ret);
 261	}
 262
 263	return phy_restore_page(phydev, saved_page, ret);
 264}
 265
 266static int __air_buckpbus_reg_read(struct phy_device *phydev,
 267				   u32 pbus_address, u32 *pbus_data)
 268{
 269	int pbus_data_low, pbus_data_high;
 270	int ret;
 271
 272	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
 273	if (ret < 0)
 274		return ret;
 275
 276	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH,
 277			  upper_16_bits(pbus_address));
 278	if (ret < 0)
 279		return ret;
 280
 281	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW,
 282			  lower_16_bits(pbus_address));
 283	if (ret < 0)
 284		return ret;
 285
 286	pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH);
 287	if (pbus_data_high < 0)
 288		return pbus_data_high;
 289
 290	pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW);
 291	if (pbus_data_low < 0)
 292		return pbus_data_low;
 293
 294	*pbus_data = pbus_data_low | (pbus_data_high << 16);
 295	return 0;
 296}
 297
 298static int air_buckpbus_reg_read(struct phy_device *phydev,
 299				 u32 pbus_address, u32 *pbus_data)
 300{
 301	int saved_page;
 302	int ret = 0;
 303
 304	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
 305
 306	if (saved_page >= 0) {
 307		ret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data);
 308		if (ret < 0)
 309			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
 310				   pbus_address, ret);
 311	}
 312
 313	return phy_restore_page(phydev, saved_page, ret);
 314}
 315
 316static int __air_buckpbus_reg_modify(struct phy_device *phydev,
 317				     u32 pbus_address, u32 mask, u32 set)
 318{
 319	int pbus_data_low, pbus_data_high;
 320	u32 pbus_data_old, pbus_data_new;
 321	int ret;
 322
 323	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_FIXED);
 324	if (ret < 0)
 325		return ret;
 326
 327	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_HIGH,
 328			  upper_16_bits(pbus_address));
 329	if (ret < 0)
 330		return ret;
 331
 332	ret = __phy_write(phydev, AIR_BPBUS_RD_ADDR_LOW,
 333			  lower_16_bits(pbus_address));
 334	if (ret < 0)
 335		return ret;
 336
 337	pbus_data_high = __phy_read(phydev, AIR_BPBUS_RD_DATA_HIGH);
 338	if (pbus_data_high < 0)
 339		return pbus_data_high;
 340
 341	pbus_data_low = __phy_read(phydev, AIR_BPBUS_RD_DATA_LOW);
 342	if (pbus_data_low < 0)
 343		return pbus_data_low;
 344
 345	pbus_data_old = pbus_data_low | (pbus_data_high << 16);
 346	pbus_data_new = (pbus_data_old & ~mask) | set;
 347	if (pbus_data_new == pbus_data_old)
 348		return 0;
 349
 350	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH,
 351			  upper_16_bits(pbus_address));
 352	if (ret < 0)
 353		return ret;
 354
 355	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW,
 356			  lower_16_bits(pbus_address));
 357	if (ret < 0)
 358		return ret;
 359
 360	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH,
 361			  upper_16_bits(pbus_data_new));
 362	if (ret < 0)
 363		return ret;
 364
 365	ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW,
 366			  lower_16_bits(pbus_data_new));
 367	if (ret < 0)
 368		return ret;
 369
 370	return 0;
 371}
 372
 373static int air_buckpbus_reg_modify(struct phy_device *phydev,
 374				   u32 pbus_address, u32 mask, u32 set)
 375{
 376	int saved_page;
 377	int ret = 0;
 378
 379	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
 380
 381	if (saved_page >= 0) {
 382		ret = __air_buckpbus_reg_modify(phydev, pbus_address, mask,
 383						set);
 384		if (ret < 0)
 385			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
 386				   pbus_address, ret);
 387	}
 388
 389	return phy_restore_page(phydev, saved_page, ret);
 390}
 391
 392static int __air_write_buf(struct phy_device *phydev, u32 address,
 393			   const struct firmware *fw)
 394{
 395	unsigned int offset;
 396	int ret;
 397	u16 val;
 398
 399	ret = __phy_write(phydev, AIR_BPBUS_MODE, AIR_BPBUS_MODE_ADDR_INCR);
 400	if (ret < 0)
 401		return ret;
 402
 403	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_HIGH,
 404			  upper_16_bits(address));
 405	if (ret < 0)
 406		return ret;
 407
 408	ret = __phy_write(phydev, AIR_BPBUS_WR_ADDR_LOW,
 409			  lower_16_bits(address));
 410	if (ret < 0)
 411		return ret;
 412
 413	for (offset = 0; offset < fw->size; offset += 4) {
 414		val = get_unaligned_le16(&fw->data[offset + 2]);
 415		ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_HIGH, val);
 416		if (ret < 0)
 417			return ret;
 418
 419		val = get_unaligned_le16(&fw->data[offset]);
 420		ret = __phy_write(phydev, AIR_BPBUS_WR_DATA_LOW, val);
 421		if (ret < 0)
 422			return ret;
 423	}
 424
 425	return 0;
 426}
 427
 428static int air_write_buf(struct phy_device *phydev, u32 address,
 429			 const struct firmware *fw)
 430{
 431	int saved_page;
 432	int ret = 0;
 433
 434	saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
 435
 436	if (saved_page >= 0) {
 437		ret = __air_write_buf(phydev, address, fw);
 438		if (ret < 0)
 439			phydev_err(phydev, "%s 0x%08x failed: %d\n", __func__,
 440				   address, ret);
 441	}
 442
 443	return phy_restore_page(phydev, saved_page, ret);
 444}
 445
 446static int en8811h_wait_mcu_ready(struct phy_device *phydev)
 447{
 448	int ret, reg_value;
 449
 450	/* Because of mdio-lock, may have to wait for multiple loads */
 451	ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
 452					EN8811H_PHY_FW_STATUS, reg_value,
 453					reg_value == EN8811H_PHY_READY,
 454					20000, 7500000, true);
 455	if (ret) {
 456		phydev_err(phydev, "MCU not ready: 0x%x\n", reg_value);
 457		return -ENODEV;
 458	}
 459
 460	return 0;
 461}
 462
 463static int en8811h_load_firmware(struct phy_device *phydev)
 464{
 465	struct en8811h_priv *priv = phydev->priv;
 466	struct device *dev = &phydev->mdio.dev;
 467	const struct firmware *fw1, *fw2;
 468	int ret;
 469
 470	ret = request_firmware_direct(&fw1, EN8811H_MD32_DM, dev);
 471	if (ret < 0)
 472		return ret;
 473
 474	ret = request_firmware_direct(&fw2, EN8811H_MD32_DSP, dev);
 475	if (ret < 0)
 476		goto en8811h_load_firmware_rel1;
 477
 478	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
 479				     EN8811H_FW_CTRL_1_START);
 480	if (ret < 0)
 481		goto en8811h_load_firmware_out;
 482
 483	ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
 484				      EN8811H_FW_CTRL_2_LOADING,
 485				      EN8811H_FW_CTRL_2_LOADING);
 486	if (ret < 0)
 487		goto en8811h_load_firmware_out;
 488
 489	ret = air_write_buf(phydev, AIR_FW_ADDR_DM,  fw1);
 490	if (ret < 0)
 491		goto en8811h_load_firmware_out;
 492
 493	ret = air_write_buf(phydev, AIR_FW_ADDR_DSP, fw2);
 494	if (ret < 0)
 495		goto en8811h_load_firmware_out;
 496
 497	ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
 498				      EN8811H_FW_CTRL_2_LOADING, 0);
 499	if (ret < 0)
 500		goto en8811h_load_firmware_out;
 501
 502	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
 503				     EN8811H_FW_CTRL_1_FINISH);
 504	if (ret < 0)
 505		goto en8811h_load_firmware_out;
 506
 507	ret = en8811h_wait_mcu_ready(phydev);
 508
 509	air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION,
 510			      &priv->firmware_version);
 511	phydev_info(phydev, "MD32 firmware version: %08x\n",
 512		    priv->firmware_version);
 513
 514en8811h_load_firmware_out:
 515	release_firmware(fw2);
 516
 517en8811h_load_firmware_rel1:
 518	release_firmware(fw1);
 519
 520	if (ret < 0)
 521		phydev_err(phydev, "Load firmware failed: %d\n", ret);
 522
 523	return ret;
 524}
 525
 526static int en8811h_restart_mcu(struct phy_device *phydev)
 527{
 528	int ret;
 529
 530	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
 531				     EN8811H_FW_CTRL_1_START);
 532	if (ret < 0)
 533		return ret;
 534
 535	ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
 536				     EN8811H_FW_CTRL_1_FINISH);
 537	if (ret < 0)
 538		return ret;
 539
 540	return en8811h_wait_mcu_ready(phydev);
 541}
 542
 543static int air_hw_led_on_set(struct phy_device *phydev, u8 index, bool on)
 544{
 545	struct en8811h_priv *priv = phydev->priv;
 546	bool changed;
 547
 548	if (index >= EN8811H_LED_COUNT)
 549		return -EINVAL;
 550
 551	if (on)
 552		changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_ON,
 553					    &priv->led[index].state);
 554	else
 555		changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_ON,
 556					       &priv->led[index].state);
 557
 558	changed |= (priv->led[index].rules != 0);
 559
 560	/* clear netdev trigger rules in case LED_OFF has been set */
 561	if (!on)
 562		priv->led[index].rules = 0;
 563
 564	if (changed)
 565		return phy_modify_mmd(phydev, MDIO_MMD_VEND2,
 566				      AIR_PHY_LED_ON(index),
 567				      AIR_PHY_LED_ON_MASK,
 568				      on ? AIR_PHY_LED_ON_FORCE_ON : 0);
 569
 570	return 0;
 571}
 572
 573static int air_hw_led_blink_set(struct phy_device *phydev, u8 index,
 574				bool blinking)
 575{
 576	struct en8811h_priv *priv = phydev->priv;
 577	bool changed;
 578
 579	if (index >= EN8811H_LED_COUNT)
 580		return -EINVAL;
 581
 582	if (blinking)
 583		changed = !test_and_set_bit(AIR_PHY_LED_STATE_FORCE_BLINK,
 584					    &priv->led[index].state);
 585	else
 586		changed = !!test_and_clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK,
 587					       &priv->led[index].state);
 588
 589	changed |= (priv->led[index].rules != 0);
 590
 591	if (changed)
 592		return phy_write_mmd(phydev, MDIO_MMD_VEND2,
 593				     AIR_PHY_LED_BLINK(index),
 594				     blinking ?
 595				     AIR_PHY_LED_BLINK_FORCE_BLINK : 0);
 596	else
 597		return 0;
 598}
 599
 600static int air_led_blink_set(struct phy_device *phydev, u8 index,
 601			     unsigned long *delay_on,
 602			     unsigned long *delay_off)
 603{
 604	struct en8811h_priv *priv = phydev->priv;
 605	bool blinking = false;
 606	int err;
 607
 608	if (index >= EN8811H_LED_COUNT)
 609		return -EINVAL;
 610
 611	if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
 612		blinking = true;
 613		*delay_on = 50;
 614		*delay_off = 50;
 615	}
 616
 617	err = air_hw_led_blink_set(phydev, index, blinking);
 618	if (err)
 619		return err;
 620
 621	/* led-blink set, so switch led-on off */
 622	err = air_hw_led_on_set(phydev, index, false);
 623	if (err)
 624		return err;
 625
 626	/* hw-control is off*/
 627	if (!!test_bit(AIR_PHY_LED_STATE_FORCE_BLINK, &priv->led[index].state))
 628		priv->led[index].rules = 0;
 629
 630	return 0;
 631}
 632
 633static int air_led_brightness_set(struct phy_device *phydev, u8 index,
 634				  enum led_brightness value)
 635{
 636	struct en8811h_priv *priv = phydev->priv;
 637	int err;
 638
 639	if (index >= EN8811H_LED_COUNT)
 640		return -EINVAL;
 641
 642	/* led-on set, so switch led-blink off */
 643	err = air_hw_led_blink_set(phydev, index, false);
 644	if (err)
 645		return err;
 646
 647	err = air_hw_led_on_set(phydev, index, (value != LED_OFF));
 648	if (err)
 649		return err;
 650
 651	/* hw-control is off */
 652	if (!!test_bit(AIR_PHY_LED_STATE_FORCE_ON, &priv->led[index].state))
 653		priv->led[index].rules = 0;
 654
 655	return 0;
 656}
 657
 658static int air_led_hw_control_get(struct phy_device *phydev, u8 index,
 659				  unsigned long *rules)
 660{
 661	struct en8811h_priv *priv = phydev->priv;
 662
 663	if (index >= EN8811H_LED_COUNT)
 664		return -EINVAL;
 665
 666	*rules = priv->led[index].rules;
 667
 668	return 0;
 669};
 670
 671static int air_led_hw_control_set(struct phy_device *phydev, u8 index,
 672				  unsigned long rules)
 673{
 674	struct en8811h_priv *priv = phydev->priv;
 675	u16 on = 0, blink = 0;
 676	int ret;
 677
 678	if (index >= EN8811H_LED_COUNT)
 679		return -EINVAL;
 680
 681	priv->led[index].rules = rules;
 682
 683	if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
 684		on |= AIR_PHY_LED_ON_FDX;
 685
 686	if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
 687		on |= AIR_PHY_LED_ON_LINK10;
 688
 689	if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
 690		on |= AIR_PHY_LED_ON_LINK100;
 691
 692	if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
 693		on |= AIR_PHY_LED_ON_LINK1000;
 694
 695	if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
 696		on |= AIR_PHY_LED_ON_LINK2500;
 697
 698	if (rules & BIT(TRIGGER_NETDEV_RX)) {
 699		blink |= AIR_PHY_LED_BLINK_10RX   |
 700			 AIR_PHY_LED_BLINK_100RX  |
 701			 AIR_PHY_LED_BLINK_1000RX |
 702			 AIR_PHY_LED_BLINK_2500RX;
 703	}
 704
 705	if (rules & BIT(TRIGGER_NETDEV_TX)) {
 706		blink |= AIR_PHY_LED_BLINK_10TX   |
 707			 AIR_PHY_LED_BLINK_100TX  |
 708			 AIR_PHY_LED_BLINK_1000TX |
 709			 AIR_PHY_LED_BLINK_2500TX;
 710	}
 711
 712	if (blink || on) {
 713		/* switch hw-control on, so led-on and led-blink are off */
 714		clear_bit(AIR_PHY_LED_STATE_FORCE_ON,
 715			  &priv->led[index].state);
 716		clear_bit(AIR_PHY_LED_STATE_FORCE_BLINK,
 717			  &priv->led[index].state);
 718	} else {
 719		priv->led[index].rules = 0;
 720	}
 721
 722	ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index),
 723			     AIR_PHY_LED_ON_MASK, on);
 724
 725	if (ret < 0)
 726		return ret;
 727
 728	return phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BLINK(index),
 729			     blink);
 730};
 731
 732static int air_led_init(struct phy_device *phydev, u8 index, u8 state, u8 pol)
 733{
 734	int val = 0;
 735	int err;
 736
 737	if (index >= EN8811H_LED_COUNT)
 738		return -EINVAL;
 739
 740	if (state == AIR_LED_ENABLE)
 741		val |= AIR_PHY_LED_ON_ENABLE;
 742	else
 743		val &= ~AIR_PHY_LED_ON_ENABLE;
 744
 745	if (pol == AIR_ACTIVE_HIGH)
 746		val |= AIR_PHY_LED_ON_POLARITY;
 747	else
 748		val &= ~AIR_PHY_LED_ON_POLARITY;
 749
 750	err = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_ON(index),
 751			     AIR_PHY_LED_ON_ENABLE |
 752			     AIR_PHY_LED_ON_POLARITY, val);
 753
 754	if (err < 0)
 755		return err;
 756
 757	return 0;
 758}
 759
 760static int air_leds_init(struct phy_device *phydev, int num, int dur, int mode)
 761{
 762	struct en8811h_priv *priv = phydev->priv;
 763	int ret, i;
 764
 765	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_BLINK,
 766			    dur);
 767	if (ret < 0)
 768		return ret;
 769
 770	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_DUR_ON,
 771			    dur >> 1);
 772	if (ret < 0)
 773		return ret;
 774
 775	switch (mode) {
 776	case AIR_LED_MODE_DISABLE:
 777		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR,
 778				     AIR_PHY_LED_BCR_EXT_CTRL |
 779				     AIR_PHY_LED_BCR_MODE_MASK, 0);
 780		if (ret < 0)
 781			return ret;
 782		break;
 783	case AIR_LED_MODE_USER_DEFINE:
 784		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, AIR_PHY_LED_BCR,
 785				     AIR_PHY_LED_BCR_EXT_CTRL |
 786				     AIR_PHY_LED_BCR_CLK_EN,
 787				     AIR_PHY_LED_BCR_EXT_CTRL |
 788				     AIR_PHY_LED_BCR_CLK_EN);
 789		if (ret < 0)
 790			return ret;
 791		break;
 792	default:
 793		phydev_err(phydev, "LED mode %d is not supported\n", mode);
 794		return -EINVAL;
 795	}
 796
 797	for (i = 0; i < num; ++i) {
 798		ret = air_led_init(phydev, i, AIR_LED_ENABLE, AIR_ACTIVE_HIGH);
 799		if (ret < 0) {
 800			phydev_err(phydev, "LED%d init failed: %d\n", i, ret);
 801			return ret;
 802		}
 803		air_led_hw_control_set(phydev, i, priv->led[i].rules);
 804	}
 805
 806	return 0;
 807}
 808
 809static int en8811h_led_hw_is_supported(struct phy_device *phydev, u8 index,
 810				       unsigned long rules)
 811{
 812	if (index >= EN8811H_LED_COUNT)
 813		return -EINVAL;
 814
 815	/* All combinations of the supported triggers are allowed */
 816	if (rules & ~en8811h_led_trig)
 817		return -EOPNOTSUPP;
 818
 819	return 0;
 820};
 821
 822static unsigned long en8811h_clk_recalc_rate(struct clk_hw *hw,
 823					     unsigned long parent)
 824{
 825	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 826	struct phy_device *phydev = priv->phydev;
 827	u32 pbus_value;
 828	int ret;
 829
 830	ret = air_buckpbus_reg_read(phydev, EN8811H_HWTRAP1, &pbus_value);
 831	if (ret < 0)
 832		return ret;
 833
 834	return (pbus_value & EN8811H_HWTRAP1_CKO) ? 50000000 : 25000000;
 835}
 836
 837static int en8811h_clk_enable(struct clk_hw *hw)
 838{
 839	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 840	struct phy_device *phydev = priv->phydev;
 841
 842	return air_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM,
 843				       EN8811H_CLK_CGM_CKO,
 844				       EN8811H_CLK_CGM_CKO);
 845}
 846
 847static void en8811h_clk_disable(struct clk_hw *hw)
 848{
 849	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 850	struct phy_device *phydev = priv->phydev;
 851
 852	air_buckpbus_reg_modify(phydev, EN8811H_CLK_CGM,
 853				EN8811H_CLK_CGM_CKO, 0);
 854}
 855
 856static int en8811h_clk_is_enabled(struct clk_hw *hw)
 857{
 858	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 859	struct phy_device *phydev = priv->phydev;
 860	u32 pbus_value;
 861	int ret;
 862
 863	ret = air_buckpbus_reg_read(phydev, EN8811H_CLK_CGM, &pbus_value);
 864	if (ret < 0)
 865		return ret;
 866
 867	return (pbus_value & EN8811H_CLK_CGM_CKO);
 868}
 869
 870static int en8811h_clk_save_context(struct clk_hw *hw)
 871{
 872	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 873
 874	priv->cko_is_enabled = en8811h_clk_is_enabled(hw);
 875
 876	return 0;
 877}
 878
 879static void en8811h_clk_restore_context(struct clk_hw *hw)
 880{
 881	struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw);
 882
 883	if (!priv->cko_is_enabled)
 884		en8811h_clk_disable(hw);
 885}
 886
 887static const struct clk_ops en8811h_clk_ops = {
 888	.recalc_rate		= en8811h_clk_recalc_rate,
 889	.enable			= en8811h_clk_enable,
 890	.disable		= en8811h_clk_disable,
 891	.is_enabled		= en8811h_clk_is_enabled,
 892	.save_context		= en8811h_clk_save_context,
 893	.restore_context	= en8811h_clk_restore_context,
 894};
 895
 896static int en8811h_clk_provider_setup(struct device *dev, struct clk_hw *hw)
 897{
 898	struct clk_init_data init;
 899	int ret;
 900
 901	if (!IS_ENABLED(CONFIG_COMMON_CLK))
 902		return 0;
 903
 904	init.name = devm_kasprintf(dev, GFP_KERNEL, "%s-cko",
 905				   fwnode_get_name(dev_fwnode(dev)));
 906	if (!init.name)
 907		return -ENOMEM;
 908
 909	init.ops = &en8811h_clk_ops;
 910	init.flags = 0;
 911	init.num_parents = 0;
 912	hw->init = &init;
 913
 914	ret = devm_clk_hw_register(dev, hw);
 915	if (ret)
 916		return ret;
 917
 918	return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
 919}
 920
 921static int en8811h_probe(struct phy_device *phydev)
 922{
 923	struct en8811h_priv *priv;
 924	int ret;
 925
 926	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct en8811h_priv),
 927			    GFP_KERNEL);
 928	if (!priv)
 929		return -ENOMEM;
 930	phydev->priv = priv;
 931
 932	ret = en8811h_load_firmware(phydev);
 933	if (ret < 0)
 934		return ret;
 935
 936	/* mcu has just restarted after firmware load */
 937	priv->mcu_needs_restart = false;
 938
 939	priv->led[0].rules = AIR_DEFAULT_TRIGGER_LED0;
 940	priv->led[1].rules = AIR_DEFAULT_TRIGGER_LED1;
 941	priv->led[2].rules = AIR_DEFAULT_TRIGGER_LED2;
 942
 943	/* MDIO_DEVS1/2 empty, so set mmds_present bits here */
 944	phydev->c45_ids.mmds_present |= MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
 945
 946	ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR,
 947			    AIR_LED_MODE_DISABLE);
 948	if (ret < 0) {
 949		phydev_err(phydev, "Failed to disable leds: %d\n", ret);
 950		return ret;
 951	}
 952
 953	priv->phydev = phydev;
 954	/* Co-Clock Output */
 955	ret = en8811h_clk_provider_setup(&phydev->mdio.dev, &priv->hw);
 956	if (ret)
 957		return ret;
 958
 959	/* Configure led gpio pins as output */
 960	ret = air_buckpbus_reg_modify(phydev, EN8811H_GPIO_OUTPUT,
 961				      EN8811H_GPIO_OUTPUT_345,
 962				      EN8811H_GPIO_OUTPUT_345);
 963	if (ret < 0)
 964		return ret;
 965
 966	return 0;
 967}
 968
 969static int en8811h_config_init(struct phy_device *phydev)
 970{
 971	struct en8811h_priv *priv = phydev->priv;
 972	struct device *dev = &phydev->mdio.dev;
 973	u32 pbus_value;
 974	int ret;
 975
 976	/* If restart happened in .probe(), no need to restart now */
 977	if (priv->mcu_needs_restart) {
 978		ret = en8811h_restart_mcu(phydev);
 979		if (ret < 0)
 980			return ret;
 981	} else {
 982		/* Next calls to .config_init() mcu needs to restart */
 983		priv->mcu_needs_restart = true;
 984	}
 985
 986	/* Select mode 1, the only mode supported.
 987	 * Configures the SerDes for 2500Base-X with rate adaptation
 988	 */
 989	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_1,
 990			    AIR_PHY_MCU_CMD_1_MODE1);
 991	if (ret < 0)
 992		return ret;
 993	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_2,
 994			    AIR_PHY_MCU_CMD_2_MODE1);
 995	if (ret < 0)
 996		return ret;
 997	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_3,
 998			    AIR_PHY_MCU_CMD_3_MODE1);
 999	if (ret < 0)
1000		return ret;
1001	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_4,
1002			    AIR_PHY_MCU_CMD_4_MODE1);
1003	if (ret < 0)
1004		return ret;
1005
1006	/* Serdes polarity */
1007	pbus_value = 0;
1008	if (device_property_read_bool(dev, "airoha,pnswap-rx"))
1009		pbus_value |=  EN8811H_POLARITY_RX_REVERSE;
1010	else
1011		pbus_value &= ~EN8811H_POLARITY_RX_REVERSE;
1012	if (device_property_read_bool(dev, "airoha,pnswap-tx"))
1013		pbus_value &= ~EN8811H_POLARITY_TX_NORMAL;
1014	else
1015		pbus_value |=  EN8811H_POLARITY_TX_NORMAL;
1016	ret = air_buckpbus_reg_modify(phydev, EN8811H_POLARITY,
1017				      EN8811H_POLARITY_RX_REVERSE |
1018				      EN8811H_POLARITY_TX_NORMAL, pbus_value);
1019	if (ret < 0)
1020		return ret;
1021
1022	ret = air_leds_init(phydev, EN8811H_LED_COUNT, AIR_PHY_LED_DUR,
1023			    AIR_LED_MODE_USER_DEFINE);
1024	if (ret < 0) {
1025		phydev_err(phydev, "Failed to initialize leds: %d\n", ret);
1026		return ret;
1027	}
1028
1029	return 0;
1030}
1031
1032static int en8811h_get_features(struct phy_device *phydev)
1033{
1034	linkmode_set_bit_array(phy_basic_ports_array,
1035			       ARRAY_SIZE(phy_basic_ports_array),
1036			       phydev->supported);
1037
1038	return genphy_c45_pma_read_abilities(phydev);
1039}
1040
1041static int en8811h_get_rate_matching(struct phy_device *phydev,
1042				     phy_interface_t iface)
1043{
1044	return RATE_MATCH_PAUSE;
1045}
1046
1047static int en8811h_config_aneg(struct phy_device *phydev)
1048{
1049	bool changed = false;
1050	int ret;
1051	u32 adv;
1052
1053	if (phydev->autoneg == AUTONEG_DISABLE) {
1054		phydev_warn(phydev, "Disabling autoneg is not supported\n");
1055		return -EINVAL;
1056	}
1057
1058	adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising);
1059
1060	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
1061				     MDIO_AN_10GBT_CTRL_ADV2_5G, adv);
1062	if (ret < 0)
1063		return ret;
1064	if (ret > 0)
1065		changed = true;
1066
1067	return __genphy_config_aneg(phydev, changed);
1068}
1069
1070static int en8811h_read_status(struct phy_device *phydev)
1071{
1072	struct en8811h_priv *priv = phydev->priv;
1073	u32 pbus_value;
1074	int ret, val;
1075
1076	ret = genphy_update_link(phydev);
1077	if (ret)
1078		return ret;
1079
1080	phydev->master_slave_get = MASTER_SLAVE_CFG_UNSUPPORTED;
1081	phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED;
1082	phydev->speed = SPEED_UNKNOWN;
1083	phydev->duplex = DUPLEX_UNKNOWN;
1084	phydev->pause = 0;
1085	phydev->asym_pause = 0;
1086	phydev->rate_matching = RATE_MATCH_PAUSE;
1087
1088	ret = genphy_read_master_slave(phydev);
1089	if (ret < 0)
1090		return ret;
1091
1092	ret = genphy_read_lpa(phydev);
1093	if (ret < 0)
1094		return ret;
1095
1096	/* Get link partner 2.5GBASE-T ability from vendor register */
1097	ret = air_buckpbus_reg_read(phydev, EN8811H_2P5G_LPA, &pbus_value);
1098	if (ret < 0)
1099		return ret;
1100	linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
1101			 phydev->lp_advertising,
1102			 pbus_value & EN8811H_2P5G_LPA_2P5G);
1103
1104	if (phydev->autoneg_complete)
1105		phy_resolve_aneg_pause(phydev);
1106
1107	if (!phydev->link)
1108		return 0;
1109
1110	/* Get real speed from vendor register */
1111	val = phy_read(phydev, AIR_AUX_CTRL_STATUS);
1112	if (val < 0)
1113		return val;
1114	switch (val & AIR_AUX_CTRL_STATUS_SPEED_MASK) {
1115	case AIR_AUX_CTRL_STATUS_SPEED_2500:
1116		phydev->speed = SPEED_2500;
1117		break;
1118	case AIR_AUX_CTRL_STATUS_SPEED_1000:
1119		phydev->speed = SPEED_1000;
1120		break;
1121	case AIR_AUX_CTRL_STATUS_SPEED_100:
1122		phydev->speed = SPEED_100;
1123		break;
1124	}
1125
1126	/* Firmware before version 24011202 has no vendor register 2P5G_LPA.
1127	 * Assume link partner advertised it if connected at 2500Mbps.
1128	 */
1129	if (priv->firmware_version < 0x24011202) {
1130		linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
1131				 phydev->lp_advertising,
1132				 phydev->speed == SPEED_2500);
1133	}
1134
1135	/* Only supports full duplex */
1136	phydev->duplex = DUPLEX_FULL;
1137
1138	return 0;
1139}
1140
1141static int en8811h_clear_intr(struct phy_device *phydev)
1142{
1143	int ret;
1144
1145	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_3,
1146			    AIR_PHY_MCU_CMD_3_DOCMD);
1147	if (ret < 0)
1148		return ret;
1149
1150	ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AIR_PHY_MCU_CMD_4,
1151			    AIR_PHY_MCU_CMD_4_INTCLR);
1152	if (ret < 0)
1153		return ret;
1154
1155	return 0;
1156}
1157
1158static irqreturn_t en8811h_handle_interrupt(struct phy_device *phydev)
1159{
1160	int ret;
1161
1162	ret = en8811h_clear_intr(phydev);
1163	if (ret < 0) {
1164		phy_error(phydev);
1165		return IRQ_NONE;
1166	}
1167
1168	phy_trigger_machine(phydev);
1169
1170	return IRQ_HANDLED;
1171}
1172
1173static int en8811h_resume(struct phy_device *phydev)
1174{
1175	clk_restore_context();
1176
1177	return genphy_resume(phydev);
1178}
1179
1180static int en8811h_suspend(struct phy_device *phydev)
1181{
1182	clk_save_context();
1183
1184	return genphy_suspend(phydev);
1185}
1186
1187static struct phy_driver en8811h_driver[] = {
1188{
1189	PHY_ID_MATCH_MODEL(EN8811H_PHY_ID),
1190	.name			= "Airoha EN8811H",
1191	.probe			= en8811h_probe,
1192	.get_features		= en8811h_get_features,
1193	.config_init		= en8811h_config_init,
1194	.get_rate_matching	= en8811h_get_rate_matching,
1195	.config_aneg		= en8811h_config_aneg,
1196	.read_status		= en8811h_read_status,
1197	.resume			= en8811h_resume,
1198	.suspend		= en8811h_suspend,
1199	.config_intr		= en8811h_clear_intr,
1200	.handle_interrupt	= en8811h_handle_interrupt,
1201	.led_hw_is_supported	= en8811h_led_hw_is_supported,
1202	.read_page		= air_phy_read_page,
1203	.write_page		= air_phy_write_page,
1204	.led_blink_set		= air_led_blink_set,
1205	.led_brightness_set	= air_led_brightness_set,
1206	.led_hw_control_set	= air_led_hw_control_set,
1207	.led_hw_control_get	= air_led_hw_control_get,
1208} };
1209
1210module_phy_driver(en8811h_driver);
1211
1212static const struct mdio_device_id __maybe_unused en8811h_tbl[] = {
1213	{ PHY_ID_MATCH_MODEL(EN8811H_PHY_ID) },
1214	{ }
1215};
1216
1217MODULE_DEVICE_TABLE(mdio, en8811h_tbl);
1218MODULE_FIRMWARE(EN8811H_MD32_DM);
1219MODULE_FIRMWARE(EN8811H_MD32_DSP);
1220
1221MODULE_DESCRIPTION("Airoha EN8811H PHY drivers");
1222MODULE_AUTHOR("Airoha");
1223MODULE_AUTHOR("Eric Woudstra <ericwouds@gmail.com>");
1224MODULE_LICENSE("GPL");
~/ Read-only file preview.