Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: fec: add C45 MDIO read/write support

IEEE 802.3ae clause 45 defines a modified MDIO protocol that uses a two
staged access model in order to increase the address space.

This patch adds support for C45 MDIO read and write accesses, which are
used whenever the MII_ADDR_C45 flag in the regnum argument is set.
In case it is not set, C22 accesses are used as before.

Signed-off-by: Marco Hartmann <marco.hartmann@nxp.com>
Acked-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Marco Hartmann and committed by
David S. Miller
d3ee8ec7 c2a5b91e

+64 -6
+64 -6
drivers/net/ethernet/freescale/fec_main.c
··· 208 208 209 209 /* FEC MII MMFR bits definition */ 210 210 #define FEC_MMFR_ST (1 << 30) 211 + #define FEC_MMFR_ST_C45 (0) 211 212 #define FEC_MMFR_OP_READ (2 << 28) 213 + #define FEC_MMFR_OP_READ_C45 (3 << 28) 212 214 #define FEC_MMFR_OP_WRITE (1 << 28) 215 + #define FEC_MMFR_OP_ADDR_WRITE (0) 213 216 #define FEC_MMFR_PA(v) ((v & 0x1f) << 23) 214 217 #define FEC_MMFR_RA(v) ((v & 0x1f) << 18) 215 218 #define FEC_MMFR_TA (2 << 16) ··· 1770 1767 struct fec_enet_private *fep = bus->priv; 1771 1768 struct device *dev = &fep->pdev->dev; 1772 1769 unsigned long time_left; 1773 - int ret = 0; 1770 + int ret = 0, frame_start, frame_addr, frame_op; 1771 + bool is_c45 = !!(regnum & MII_ADDR_C45); 1774 1772 1775 1773 ret = pm_runtime_get_sync(dev); 1776 1774 if (ret < 0) ··· 1779 1775 1780 1776 reinit_completion(&fep->mdio_done); 1781 1777 1778 + if (is_c45) { 1779 + frame_start = FEC_MMFR_ST_C45; 1780 + 1781 + /* write address */ 1782 + frame_addr = (regnum >> 16); 1783 + writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | 1784 + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | 1785 + FEC_MMFR_TA | (regnum & 0xFFFF), 1786 + fep->hwp + FEC_MII_DATA); 1787 + 1788 + /* wait for end of transfer */ 1789 + time_left = wait_for_completion_timeout(&fep->mdio_done, 1790 + usecs_to_jiffies(FEC_MII_TIMEOUT)); 1791 + if (time_left == 0) { 1792 + netdev_err(fep->netdev, "MDIO address write timeout\n"); 1793 + ret = -ETIMEDOUT; 1794 + goto out; 1795 + } 1796 + 1797 + frame_op = FEC_MMFR_OP_READ_C45; 1798 + 1799 + } else { 1800 + /* C22 read */ 1801 + frame_op = FEC_MMFR_OP_READ; 1802 + frame_start = FEC_MMFR_ST; 1803 + frame_addr = regnum; 1804 + } 1805 + 1782 1806 /* start a read op */ 1783 - writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | 1784 - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | 1807 + writel(frame_start | frame_op | 1808 + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | 1785 1809 FEC_MMFR_TA, fep->hwp + FEC_MII_DATA); 1786 1810 1787 1811 /* wait for end of transfer */ ··· 1836 1804 struct fec_enet_private *fep = bus->priv; 1837 1805 struct device *dev = &fep->pdev->dev; 1838 1806 unsigned long time_left; 1839 - int ret; 1807 + int ret, frame_start, frame_addr; 1808 + bool is_c45 = !!(regnum & MII_ADDR_C45); 1840 1809 1841 1810 ret = pm_runtime_get_sync(dev); 1842 1811 if (ret < 0) ··· 1847 1814 1848 1815 reinit_completion(&fep->mdio_done); 1849 1816 1817 + if (is_c45) { 1818 + frame_start = FEC_MMFR_ST_C45; 1819 + 1820 + /* write address */ 1821 + frame_addr = (regnum >> 16); 1822 + writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | 1823 + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | 1824 + FEC_MMFR_TA | (regnum & 0xFFFF), 1825 + fep->hwp + FEC_MII_DATA); 1826 + 1827 + /* wait for end of transfer */ 1828 + time_left = wait_for_completion_timeout(&fep->mdio_done, 1829 + usecs_to_jiffies(FEC_MII_TIMEOUT)); 1830 + if (time_left == 0) { 1831 + netdev_err(fep->netdev, "MDIO address write timeout\n"); 1832 + ret = -ETIMEDOUT; 1833 + goto out; 1834 + } 1835 + } else { 1836 + /* C22 write */ 1837 + frame_start = FEC_MMFR_ST; 1838 + frame_addr = regnum; 1839 + } 1840 + 1850 1841 /* start a write op */ 1851 - writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | 1852 - FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | 1842 + writel(frame_start | FEC_MMFR_OP_WRITE | 1843 + FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | 1853 1844 FEC_MMFR_TA | FEC_MMFR_DATA(value), 1854 1845 fep->hwp + FEC_MII_DATA); 1855 1846 ··· 1885 1828 ret = -ETIMEDOUT; 1886 1829 } 1887 1830 1831 + out: 1888 1832 pm_runtime_mark_last_busy(dev); 1889 1833 pm_runtime_put_autosuspend(dev); 1890 1834