Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: (GPL-2.0 OR MIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Driver for the MDIO interface of Microsemi network switches.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Author: Alexandre Belloni <alexandre.belloni@bootlin.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (c) 2017 Microsemi Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/of_mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define MSCC_MIIM_REG_STATUS		0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define		MSCC_MIIM_STATUS_STAT_PENDING	BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define		MSCC_MIIM_STATUS_STAT_BUSY	BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define MSCC_MIIM_REG_CMD		0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define		MSCC_MIIM_CMD_OPR_WRITE		BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define		MSCC_MIIM_CMD_OPR_READ		BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define		MSCC_MIIM_CMD_WRDATA_SHIFT	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define		MSCC_MIIM_CMD_REGAD_SHIFT	20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define		MSCC_MIIM_CMD_PHYAD_SHIFT	25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define		MSCC_MIIM_CMD_VLD		BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define MSCC_MIIM_REG_DATA		0xC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define		MSCC_MIIM_DATA_ERROR		(BIT(16) | BIT(17))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define MSCC_PHY_REG_PHY_CFG	0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define		PHY_CFG_PHY_ENA		(BIT(0) | BIT(1) | BIT(2) | BIT(3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define		PHY_CFG_PHY_COMMON_RESET BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define		PHY_CFG_PHY_RESET	(BIT(5) | BIT(6) | BIT(7) | BIT(8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define MSCC_PHY_REG_PHY_STATUS	0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) struct mscc_miim_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	void __iomem *phy_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) /* When high resolution timers aren't built-in: we can't use usleep_range() as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * we would sleep way too long. Use udelay() instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define mscc_readl_poll_timeout(addr, val, cond, delay_us, timeout_us)	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) ({									\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	if (!IS_ENABLED(CONFIG_HIGH_RES_TIMERS))			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		readl_poll_timeout_atomic(addr, val, cond, delay_us,	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 					  timeout_us);			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	readl_poll_timeout(addr, val, cond, delay_us, timeout_us);	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) static int mscc_miim_wait_ready(struct mii_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct mscc_miim_dev *miim = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 				       !(val & MSCC_MIIM_STATUS_STAT_BUSY), 50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 				       10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) static int mscc_miim_wait_pending(struct mii_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	struct mscc_miim_dev *miim = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	return mscc_readl_poll_timeout(miim->regs + MSCC_MIIM_REG_STATUS, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 				       !(val & MSCC_MIIM_STATUS_STAT_PENDING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 				       50, 10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static int mscc_miim_read(struct mii_bus *bus, int mii_id, int regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct mscc_miim_dev *miim = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	ret = mscc_miim_wait_pending(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	writel(MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	       (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) | MSCC_MIIM_CMD_OPR_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	       miim->regs + MSCC_MIIM_REG_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	ret = mscc_miim_wait_ready(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	val = readl(miim->regs + MSCC_MIIM_REG_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (val & MSCC_MIIM_DATA_ERROR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	ret = val & 0xFFFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int mscc_miim_write(struct mii_bus *bus, int mii_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			   int regnum, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct mscc_miim_dev *miim = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	ret = mscc_miim_wait_pending(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	writel(MSCC_MIIM_CMD_VLD | (mii_id << MSCC_MIIM_CMD_PHYAD_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	       (regnum << MSCC_MIIM_CMD_REGAD_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	       (value << MSCC_MIIM_CMD_WRDATA_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	       MSCC_MIIM_CMD_OPR_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	       miim->regs + MSCC_MIIM_REG_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int mscc_miim_reset(struct mii_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	struct mscc_miim_dev *miim = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	if (miim->phy_regs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		writel(0, miim->phy_regs + MSCC_PHY_REG_PHY_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		writel(0x1ff, miim->phy_regs + MSCC_PHY_REG_PHY_CFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		mdelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int mscc_miim_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	struct mii_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	struct mscc_miim_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (!bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	bus->name = "mscc_miim";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	bus->read = mscc_miim_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	bus->write = mscc_miim_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	bus->reset = mscc_miim_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	bus->parent = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	dev = bus->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	dev->regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (IS_ERR(dev->regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		dev_err(&pdev->dev, "Unable to map MIIM registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		return PTR_ERR(dev->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		dev->phy_regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		if (IS_ERR(dev->phy_regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			dev_err(&pdev->dev, "Unable to map internal phy registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			return PTR_ERR(dev->phy_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	ret = of_mdiobus_register(bus, pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	platform_set_drvdata(pdev, bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int mscc_miim_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	struct mii_bus *bus = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	mdiobus_unregister(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static const struct of_device_id mscc_miim_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	{ .compatible = "mscc,ocelot-miim" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) MODULE_DEVICE_TABLE(of, mscc_miim_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static struct platform_driver mscc_miim_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	.probe = mscc_miim_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	.remove = mscc_miim_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		.name = "mscc-miim",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		.of_match_table = mscc_miim_match,
^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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) module_platform_driver(mscc_miim_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) MODULE_DESCRIPTION("Microsemi MIIM driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) MODULE_LICENSE("Dual MIT/GPL");