From nobody Wed Oct 8 16:06:07 2025 Received: from mail-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 884C9287262; Thu, 26 Jun 2025 21:24:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750973049; cv=none; b=BOrP+d+nYP0R73lPgACTh1TevVHbhMKhvIyOLV2LtZeIhDroJZ2GVELtqaUx6IWbjLWjjs4ayCiJMGS5EXkbeazcAMzmKf3WjhXQtRMsgYc1YlzCJ5DvNbjChjMsVKPyyur2WjWcKQZrYcLFdShUHo5chzM7t/5+YvIUgZ5Mh3Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750973049; c=relaxed/simple; bh=lAAp/Hn1bW80f9Iyh/gDx8RcVdCHjt1SQB9aHf9vHtI=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RIYVB9ChinRU7vgjmglv6mXZI+sG8aky6sBPqASBD7qe4JNSHOFIxGQ3fTiJKGth4XyR6vfnHg+hPFZOdV5LX6/nRSn29zKG5Ao5HXfjZyVVnZ3EIWGajAQhHiTA5jsk36694DOZDtQdEfwhRuoFxk9cu6CFtxPkSy49gruw9v4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KhSR3tUW; arc=none smtp.client-ip=209.85.221.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KhSR3tUW" Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-3a5123c1533so833397f8f.2; Thu, 26 Jun 2025 14:24:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1750973046; x=1751577846; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Q51p0D6joOH4+ZA0xeQSWKxObvqWX7HJjHs05TsGJt0=; b=KhSR3tUWhTAy3p1RSdhyxeWhnuX1/ccK579deVyPxFi50+RRdTOJVK0ldOComTeSMZ Y9iU0UXSri+aqHHroloepP8zKfw6dSUkluOrcEkD8LywyzPKxoukzCnyzdCq/N76jCya GvO0lyaX/U2aHYgzpcTqytJ8DHh1Y7VXP750MVZr354pm7VDMKgT+CI74UGr4IN3Fj74 RpMxtXPNNcTlWT/WEV0ySFHXGZNHIUjPzc13EpfqRNY2Rc+hwXfTQwr33WGqn9AooPJA VQDCfOZ6QKGMmVzVT+0FUkpo1BlcRsc48adijaprvyf2+Y6vyo2644C+HXBPVvrFVCX2 z2jQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1750973046; x=1751577846; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Q51p0D6joOH4+ZA0xeQSWKxObvqWX7HJjHs05TsGJt0=; b=BWpXlFvDPOcetiw/p1jBm01837xg4daoUgXfAenj+dpg2uj5dmdzPyHle3ZpIpb5Tk esdkHCtUSnPT1sOM+1eflWjUsd2tSA2uWxTmbPi0QiQJyNxX5koryYlpb9+WJXPlOV9t VEpeDTTfX8Ga9h6j6ROv0lVVSKuqyVRuDny8rpvBsf53PDnT0k3DjqP+dgwBh0Z5XD6I cNENfH4jjyWeFz3j7pSHktGjKGBH8c5Cl5+KOYa9L60JMTTP7iaI+9rv6ntgYQoOvNIZ WxOGUAs6sxt0N/rmcaSk9dpcRoPd8PvZzqIT5r35EGY08jEfJ5nstCnc9Ry0CJEN/f27 4WDg== X-Forwarded-Encrypted: i=1; AJvYcCUR8c/X6bAgXs06Fg/YvVfEh7lwWEGpobUcXCpGSZyMEYe8xEdPL0paDgZ7Q0ZkSl7wXJukg2gseG0d@vger.kernel.org, AJvYcCVy9VFC3btchb9qpflU6sw+7TZonxFnLYRlQ3D/WiMDHjsEWrLkJlaN2PUIdVlzvsDmlBGQzRsfYewf+ev8@vger.kernel.org, AJvYcCXp6efCbH0nIk/Z5kKhs7KS70bb+DiwvJpbOh0egsRgMRiyeT+3oYGh9PUQz3Xq4sH7BBi/q5lZ@vger.kernel.org X-Gm-Message-State: AOJu0YyeBhvUgf2sasxgiFbDxjY0KYNxHHsegGs7961HaeBHrTxiLNDh DqyskXo7M8Cme9IL9yLjlLL3F7nmj6njbxQSGeixbp+FTyuykrRw+0Mx X-Gm-Gg: ASbGncsAL3iLrnfidygVF932+6NsP23UevMy6Xrf9SuA/iROCU7vtaChVHWdBbMt5cN NVpay5bw0PMLhQQA2U8FrX7vk/yJM8uguTrnP05LtTeUOxinsR6ZnE5X2k44gzEnU1MbME6VrYN AiWcQUavJ3WfGOa2UaeUzz/ZY2uHzB8sIzOxt/8NgjgmP8VjmJahWnc/cx4gbm+Ta7flKaFSp0k /kkFmiZ1Rks110pwkMGdrLNy8zvuOCzHCIDWwZ+eCJRvWTGcNE/WvBqCxTSReb36Mvxrldqsg5X oNEON3E32J8jZ+/jtbvbR0FokkcS+bj9nKJ+yIN4C1gNQAvOrKCMRx56Zeuyy2Pp/TloPSY7g+6 MeWlovfYJxwzcDSB2U2/6R3A9kB/TPOc= X-Google-Smtp-Source: AGHT+IFUAFT5M5Q3CduJ3muQBWpq2XELQIlYzjz6eKJuSYBHtb3xbG2uAtcpXRBZrCMlNM2c6wesvA== X-Received: by 2002:a05:6000:20c6:b0:3a4:da87:3a73 with SMTP id ffacd0b85a97d-3a8fec79a28mr574471f8f.42.1750973045754; Thu, 26 Jun 2025 14:24:05 -0700 (PDT) Received: from localhost.localdomain (93-34-88-225.ip49.fastwebnet.it. [93.34.88.225]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-453835798acsm57186475e9.10.2025.06.26.14.24.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Jun 2025 14:24:05 -0700 (PDT) From: Christian Marangi To: Christian Marangi , Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Vladimir Oltean , Srinivas Kandagatla , Heiner Kallweit , Russell King , "Chester A. Unal" , Daniel Golle , DENG Qingfang , Sean Wang , Simon Horman , Matthias Brugger , AngeloGioacchino Del Regno , linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [net-next PATCH v15 09/12] mfd: an8855: Add support for Airoha AN8855 Switch MFD Date: Thu, 26 Jun 2025 23:23:08 +0200 Message-ID: <20250626212321.28114-10-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250626212321.28114-1-ansuelsmth@gmail.com> References: <20250626212321.28114-1-ansuelsmth@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for Airoha AN8855 Switch MFD that provide support for a DSA switch and a NVMEM provider. Also provide support for the PBUS MDIO to access the internal PHYs address from the switch registers to permit the usage of a single regmap to handle both switch and PHYs. An interesting HW bug wes discovered with the implementation of the MDIO PBUS where the PHY status is not correctly detected if the PBUS is used to read the PHY BMSR. For the only BMSR register, it's required to read the address directly from the MDIO bus. A check and a workaround is implemented to address this in the regmap_read function. Signed-off-by: Christian Marangi --- drivers/mfd/Kconfig | 12 ++ drivers/mfd/Makefile | 1 + drivers/mfd/airoha-an8855.c | 393 ++++++++++++++++++++++++++++++++++++ 3 files changed, 406 insertions(+) create mode 100644 drivers/mfd/airoha-an8855.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6fb3768e3d71..f2bfd6c9fc5f 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -53,6 +53,18 @@ config MFD_ALTERA_SYSMGR using regmap_mmio accesses for ARM32 parts and SMC calls to EL3 for ARM64 parts. =20 +config MFD_AIROHA_AN8855 + tristate "Airoha AN8855 Switch Core" + select MFD_CORE + select MDIO_DEVICE + depends on NETDEVICES && OF + help + Support for the Airoha AN8855 Switch Core. This is an SoC + that provides various peripherals, to count, i2c, an Ethrnet + Switch, a CPU timer, GPIO, eFUSE. + + Currently it provides a DSA switch and a NVMEM provider. + config MFD_ACT8945A tristate "Active-semi ACT8945A" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 79495f9f3457..f541b513f41e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_MFD_88PM860X) +=3D 88pm860x.o obj-$(CONFIG_MFD_88PM800) +=3D 88pm800.o 88pm80x.o obj-$(CONFIG_MFD_88PM805) +=3D 88pm805.o 88pm80x.o obj-$(CONFIG_MFD_88PM886_PMIC) +=3D 88pm886.o +obj-$(CONFIG_MFD_AIROHA_AN8855) +=3D airoha-an8855.o obj-$(CONFIG_MFD_ACT8945A) +=3D act8945a.o obj-$(CONFIG_MFD_SM501) +=3D sm501.o obj-$(CONFIG_ARCH_BCM2835) +=3D bcm2835-pm.o diff --git a/drivers/mfd/airoha-an8855.c b/drivers/mfd/airoha-an8855.c new file mode 100644 index 000000000000..bb03a2436f25 --- /dev/null +++ b/drivers/mfd/airoha-an8855.c @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Core driver for Airoha AN8855 Switch + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register for HW trap status */ +#define AN8855_HWTRAP 0x1000009c + +#define AN8855_CREV 0x10005000 +#define AN8855_ID 0x8855 + +#define AN8855_RG_GPHY_AFE_PWD 0x1028c840 + +/* MII Registers */ +#define AN8855_PHY_SELECT_PAGE 0x1f +#define AN8855_PHY_PAGE GENMASK(2, 0) +#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0) +#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1) +#define AN8855_PHY_PAGE_EXTENDED_4 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4) + +/* MII Registers Page 4 */ +#define AN8855_PBUS_MODE 0x10 +#define AN8855_PBUS_MODE_ADDR_FIXED 0x0 +#define AN8855_PBUS_MODE_ADDR_INCR BIT(15) +#define AN8855_PBUS_WR_ADDR_HIGH 0x11 +#define AN8855_PBUS_WR_ADDR_LOW 0x12 +#define AN8855_PBUS_WR_DATA_HIGH 0x13 +#define AN8855_PBUS_WR_DATA_LOW 0x14 +#define AN8855_PBUS_RD_ADDR_HIGH 0x15 +#define AN8855_PBUS_RD_ADDR_LOW 0x16 +#define AN8855_PBUS_RD_DATA_HIGH 0x17 +#define AN8855_PBUS_RD_DATA_LOW 0x18 + +struct an8855_core_priv { + struct mii_bus *bus; + + unsigned int switch_addr; +}; + +static const struct mfd_cell an8855_core_childs[] =3D { + { + .name =3D "an8855-efuse", + .of_compatible =3D "airoha,an8855-efuse", + }, { + .name =3D "an8855-switch", + .of_compatible =3D "airoha,an8855-switch", + }, { + .name =3D "an8855-mdio", + .of_compatible =3D "airoha,an8855-mdio", + } +}; + +static bool an8855_is_pbus_bmcr_reg(u32 reg) +{ + if ((reg & ~(AN8855_GPHY_PORT | AN8855_ADDR)) !=3D AN8855_GPHY_ACCESS) + return false; + + if ((reg & AN8855_ADDR) !=3D FIELD_PREP_CONST(AN8855_CL22_ADDR, + MII_BMSR)) + return false; + + return true; +} + +/* PHY page is Global for every Switch PHY. + * Configure it to 4 (as Switch PAGE) and keep it that way. + * Page selection doesn't affect the first PHY address from 0x0 to + * 0xf and we use PBUS to access the PHY address. + */ +static int an8855_mii_set_page(struct an8855_core_priv *priv, u8 addr, + u8 page) __must_hold(&priv->bus->mdio_lock) +{ + struct mii_bus *bus =3D priv->bus; + int ret; + + ret =3D __mdiobus_write(bus, addr, AN8855_PHY_SELECT_PAGE, page); + if (ret) + dev_err_ratelimited(&bus->dev, "failed to set mii page\n"); + + return ret; +} + +static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg, + u32 *val) __must_hold(&bus->mdio_lock) +{ + int lo, hi, ret; + + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE, + AN8855_PBUS_MODE_ADDR_FIXED); + if (ret) + goto err; + + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH, + upper_16_bits(reg)); + if (ret) + goto err; + + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW, + lower_16_bits(reg)); + if (ret) + goto err; + + hi =3D __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH); + if (hi < 0) { + ret =3D hi; + goto err; + } + + lo =3D __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW); + if (lo < 0) { + ret =3D lo; + goto err; + } + + *val =3D ((u16)hi << 16) | ((u16)lo & 0xffff); + + return 0; +err: + dev_err_ratelimited(&bus->dev, "failed to read register\n"); + return ret; +} + +static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val) +{ + struct an8855_core_priv *priv =3D ctx; + struct mii_bus *bus =3D priv->bus; + u16 addr =3D priv->switch_addr; + int ret; + + /* Workaround a HW BUG where using only PBUS for + * accessing internal PHY register cause the port status + * to not be correctly detected. It seems BMSR is required + * to go through direct MDIO read or is never refreshed. + * + * A theory about this is that PHY sideband signal is + * checked only with MDIO operation on BMSR and using + * PBUS doesn't trigger the check. + * + * Using interrupt to detect Link Up might be possible + * but it's considered an optional feature for the Switch + * reference (hence there could be devices with the + * interrupt line not connected) + */ + if (an8855_is_pbus_bmcr_reg(reg)) { + addr +=3D FIELD_GET(AN8855_GPHY_PORT, reg); + *val =3D mdiobus_read(bus, addr, MII_BMSR); + return 0; + } + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + ret =3D an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4); + if (ret < 0) + goto exit; + + ret =3D an8855_mii_read32(bus, addr, reg, val); + +exit: + mutex_unlock(&bus->mdio_lock); + + return ret < 0 ? ret : 0; +} + +static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg, + u32 val) __must_hold(&bus->mdio_lock) +{ + int ret; + + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE, + AN8855_PBUS_MODE_ADDR_FIXED); + if (ret) + goto err; + + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH, + upper_16_bits(reg)); + if (ret) + goto err; + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW, + lower_16_bits(reg)); + if (ret) + goto err; + + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH, + upper_16_bits(val)); + if (ret) + goto err; + + ret =3D __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW, + lower_16_bits(val)); + if (ret) + goto err; + + return 0; +err: + dev_err_ratelimited(&bus->dev, + "failed to write an8855 register\n"); + return ret; +} + +static int an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val) +{ + struct an8855_core_priv *priv =3D ctx; + struct mii_bus *bus =3D priv->bus; + u16 addr =3D priv->switch_addr; + int ret; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + ret =3D an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4); + if (ret) + goto exit; + + ret =3D an8855_mii_write32(bus, addr, reg, val); + +exit: + mutex_unlock(&bus->mdio_lock); + + return ret < 0 ? ret : 0; +} + +static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mas= k, + uint32_t write_val) +{ + struct an8855_core_priv *priv =3D ctx; + struct mii_bus *bus =3D priv->bus; + u16 addr =3D priv->switch_addr; + u32 val; + int ret; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + ret =3D an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4); + if (ret) + goto exit; + + ret =3D an8855_mii_read32(bus, addr, reg, &val); + if (ret < 0) + goto exit; + + val &=3D ~mask; + val |=3D write_val; + ret =3D an8855_mii_write32(bus, addr, reg, val); + +exit: + mutex_unlock(&bus->mdio_lock); + + return ret < 0 ? ret : 0; +} + +static const struct regmap_range an8855_readable_ranges[] =3D { + regmap_reg_range(0x10000000, 0x10000fff), /* SCU */ + regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */ + regmap_reg_range(0x10002000, 0x10002fff), /* MCU */ + regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */ + regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */ + regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */ + regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */ + regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */ + regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */ + regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */ + regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */ + regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */ + regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */ + regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */ + regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */ + regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */ + regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */ + regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */ + regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */ + regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */ + regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */ + regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */ + regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */ + regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */ + regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */ + regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */ + regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */ +}; + +static const struct regmap_access_table an8855_readable_table =3D { + .yes_ranges =3D an8855_readable_ranges, + .n_yes_ranges =3D ARRAY_SIZE(an8855_readable_ranges), +}; + +static const struct regmap_config an8855_regmap_config =3D { + .reg_bits =3D 32, + .val_bits =3D 32, + .reg_stride =3D 4, + .max_register =3D 0xbfffffff, + .reg_read =3D an8855_regmap_read, + .reg_write =3D an8855_regmap_write, + .reg_update_bits =3D an8855_regmap_update_bits, + .disable_locking =3D true, + .rd_table =3D &an8855_readable_table, +}; + +static int an8855_read_switch_id(struct device *dev, struct regmap *regmap) +{ + u32 id; + int ret; + + ret =3D regmap_read(regmap, AN8855_CREV, &id); + if (ret) + return ret; + + if (id !=3D AN8855_ID) { + dev_err(dev, "Detected Switch ID %x but %x was expected\n", + id, AN8855_ID); + return -ENODEV; + } + + return 0; +} + +static int an8855_core_probe(struct mdio_device *mdiodev) +{ + struct device *dev =3D &mdiodev->dev; + struct an8855_core_priv *priv; + struct gpio_desc *reset_gpio; + struct regmap *regmap; + u32 val; + int ret; + + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->bus =3D mdiodev->bus; + priv->switch_addr =3D mdiodev->addr; + /* No DMA for mdiobus, mute warning for DMA mask not set */ + dev->dma_mask =3D &dev->coherent_dma_mask; + + regmap =3D devm_regmap_init(dev, NULL, priv, &an8855_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "regmap initialization failed\n"); + + reset_gpio =3D devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(reset_gpio)) + return PTR_ERR(reset_gpio); + + if (reset_gpio) { + usleep_range(100000, 150000); + gpiod_set_value_cansleep(reset_gpio, 0); + usleep_range(100000, 150000); + gpiod_set_value_cansleep(reset_gpio, 1); + + /* Poll HWTRAP reg to wait for Switch to fully Init */ + ret =3D regmap_read_poll_timeout(regmap, AN8855_HWTRAP, val, + val, 20, 200000); + if (ret) + return ret; + } + + ret =3D an8855_read_switch_id(dev, regmap); + if (ret) + return ret; + + /* Release global PHY power down */ + ret =3D regmap_write(regmap, AN8855_RG_GPHY_AFE_PWD, 0x0); + if (ret) + return ret; + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, an8855_core_childs, + ARRAY_SIZE(an8855_core_childs), NULL, 0, + NULL); +} + +static const struct of_device_id an8855_core_of_match[] =3D { + { .compatible =3D "airoha,an8855" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, an8855_core_of_match); + +static struct mdio_driver an8855_core_driver =3D { + .probe =3D an8855_core_probe, + .mdiodrv.driver =3D { + .name =3D "an8855", + .of_match_table =3D an8855_core_of_match, + }, +}; +mdio_module_driver(an8855_core_driver); + +MODULE_AUTHOR("Christian Marangi "); +MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD"); +MODULE_LICENSE("GPL"); --=20 2.48.1