^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Copyright (c) 2015, The Linux Foundation. All rights reserved. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /* Copyright (c) 2020 Sartura Ltd. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of_mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define MDIO_MODE_REG 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define MDIO_ADDR_REG 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define MDIO_DATA_WRITE_REG 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define MDIO_DATA_READ_REG 0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define MDIO_CMD_REG 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define MDIO_CMD_ACCESS_BUSY BIT(16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define MDIO_CMD_ACCESS_START BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MDIO_CMD_ACCESS_CODE_READ 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MDIO_CMD_ACCESS_CODE_WRITE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MDIO_CMD_ACCESS_CODE_C45_ADDR 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MDIO_CMD_ACCESS_CODE_C45_WRITE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MDIO_CMD_ACCESS_CODE_C45_READ 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* 0 = Clause 22, 1 = Clause 45 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MDIO_MODE_C45 BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define IPQ4019_MDIO_TIMEOUT 10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define IPQ4019_MDIO_SLEEP 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct ipq4019_mdio_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) void __iomem *membase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static int ipq4019_mdio_wait_busy(struct mii_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct ipq4019_mdio_data *priv = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned int busy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return readl_poll_timeout(priv->membase + MDIO_CMD_REG, busy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) (busy & MDIO_CMD_ACCESS_BUSY) == 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) IPQ4019_MDIO_SLEEP, IPQ4019_MDIO_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int ipq4019_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct ipq4019_mdio_data *priv = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (ipq4019_mdio_wait_busy(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Clause 45 support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (regnum & MII_ADDR_C45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned int mmd = (regnum >> 16) & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int reg = regnum & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Enter Clause 45 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) data = readl(priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) data |= MDIO_MODE_C45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) writel(data, priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* issue the phy address and mmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) writel((mii_id << 8) | mmd, priv->membase + MDIO_ADDR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* issue reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) writel(reg, priv->membase + MDIO_DATA_WRITE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Enter Clause 22 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) data = readl(priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) data &= ~MDIO_MODE_C45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) writel(data, priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* issue the phy address and reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* issue read command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) writel(cmd, priv->membase + MDIO_CMD_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* Wait read complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (ipq4019_mdio_wait_busy(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (regnum & MII_ADDR_C45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) writel(cmd, priv->membase + MDIO_CMD_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (ipq4019_mdio_wait_busy(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Read and return data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return readl(priv->membase + MDIO_DATA_READ_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int ipq4019_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct ipq4019_mdio_data *priv = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (ipq4019_mdio_wait_busy(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Clause 45 support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (regnum & MII_ADDR_C45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned int mmd = (regnum >> 16) & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned int reg = regnum & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* Enter Clause 45 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) data = readl(priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) data |= MDIO_MODE_C45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) writel(data, priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* issue the phy address and mmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) writel((mii_id << 8) | mmd, priv->membase + MDIO_ADDR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* issue reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) writel(reg, priv->membase + MDIO_DATA_WRITE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) writel(cmd, priv->membase + MDIO_CMD_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (ipq4019_mdio_wait_busy(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* Enter Clause 22 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) data = readl(priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) data &= ~MDIO_MODE_C45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) writel(data, priv->membase + MDIO_MODE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* issue the phy address and reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) writel((mii_id << 8) | regnum, priv->membase + MDIO_ADDR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* issue write data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) writel(value, priv->membase + MDIO_DATA_WRITE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* issue write command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (regnum & MII_ADDR_C45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_C45_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) cmd = MDIO_CMD_ACCESS_START | MDIO_CMD_ACCESS_CODE_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) writel(cmd, priv->membase + MDIO_CMD_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* Wait write complete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (ipq4019_mdio_wait_busy(bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int ipq4019_mdio_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct ipq4019_mdio_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct mii_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (!bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) priv = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) priv->membase = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (IS_ERR(priv->membase))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return PTR_ERR(priv->membase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) bus->name = "ipq4019_mdio";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) bus->read = ipq4019_mdio_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) bus->write = ipq4019_mdio_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) bus->parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) snprintf(bus->id, MII_BUS_ID_SIZE, "%s%d", pdev->name, pdev->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = of_mdiobus_register(bus, pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) platform_set_drvdata(pdev, bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int ipq4019_mdio_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct mii_bus *bus = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) mdiobus_unregister(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static const struct of_device_id ipq4019_mdio_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { .compatible = "qcom,ipq4019-mdio" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) MODULE_DEVICE_TABLE(of, ipq4019_mdio_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) static struct platform_driver ipq4019_mdio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .probe = ipq4019_mdio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .remove = ipq4019_mdio_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .name = "ipq4019-mdio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .of_match_table = ipq4019_mdio_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) module_platform_driver(ipq4019_mdio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) MODULE_DESCRIPTION("ipq4019 MDIO interface driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) MODULE_AUTHOR("Qualcomm Atheros");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) MODULE_LICENSE("Dual BSD/GPL");