blob: e3c37d9045f119548772b59183a234f28f4f521b [file] [log] [blame]
Ioana Ciornei799a4432020-03-18 16:47:36 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2020 NXP
4 */
5
Ioana Ciornei799a4432020-03-18 16:47:36 +02006#include <dm.h>
7#include <errno.h>
8#include <miiphy.h>
9#include <asm/io.h>
10#include <fsl_memac.h>
11
12#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
13#define memac_out_32(a, v) out_le32(a, v)
14#define memac_clrbits_32(a, v) clrbits_le32(a, v)
15#define memac_setbits_32(a, v) setbits_le32(a, v)
16#else
17#define memac_out_32(a, v) out_be32(a, v)
18#define memac_clrbits_32(a, v) clrbits_be32(a, v)
19#define memac_setbits_32(a, v) setbits_be32(a, v)
20#endif
21
22static u32 memac_in_32(u32 *reg)
23{
24#ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
25 return in_le32(reg);
26#else
27 return in_be32(reg);
28#endif
29}
30
31struct fsl_ls_mdio_priv {
32 void *regs_base;
33};
34
35static u32 fsl_ls_mdio_setup_operation(struct udevice *dev, int addr, int devad,
36 int reg)
37{
38 struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
39 struct memac_mdio_controller *regs;
40 u32 mdio_ctl;
41 u32 c45 = 1;
42
43 regs = (struct memac_mdio_controller *)(priv->regs_base);
44 if (devad == MDIO_DEVAD_NONE) {
45 c45 = 0; /* clause 22 */
46 devad = reg & 0x1f;
47 memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
48 } else {
49 memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
50 }
51
52 /* Wait till the bus is free */
53 while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
54 ;
55
56 /* Set the Port and Device Addrs */
57 mdio_ctl = MDIO_CTL_PORT_ADDR(addr) | MDIO_CTL_DEV_ADDR(devad);
58 memac_out_32(&regs->mdio_ctl, mdio_ctl);
59
60 /* Set the register address */
61 if (c45)
62 memac_out_32(&regs->mdio_addr, reg & 0xffff);
63
64 /* Wait till the bus is free */
65 while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
66 ;
67
68 return mdio_ctl;
69}
70
71static int dm_fsl_ls_mdio_read(struct udevice *dev, int addr,
72 int devad, int reg)
73{
74 struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
75 struct memac_mdio_controller *regs;
76 u32 mdio_ctl;
77
78 regs = (struct memac_mdio_controller *)(priv->regs_base);
79 mdio_ctl = fsl_ls_mdio_setup_operation(dev, addr, devad, reg);
80
81 /* Initiate the read */
82 mdio_ctl |= MDIO_CTL_READ;
83 memac_out_32(&regs->mdio_ctl, mdio_ctl);
84
85 /* Wait till the MDIO write is complete */
Markus Koch9c878992022-01-11 19:22:54 +010086 while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
Ioana Ciornei799a4432020-03-18 16:47:36 +020087 ;
88
89 /* Return all Fs if nothing was there */
90 if (memac_in_32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
91 return 0xffff;
92
93 return memac_in_32(&regs->mdio_data) & 0xffff;
94}
95
96static int dm_fsl_ls_mdio_write(struct udevice *dev, int addr, int devad,
97 int reg, u16 val)
98{
99 struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
100 struct memac_mdio_controller *regs;
101
102 regs = (struct memac_mdio_controller *)(priv->regs_base);
103 fsl_ls_mdio_setup_operation(dev, addr, devad, reg);
104
105 /* Write the value to the register */
106 memac_out_32(&regs->mdio_data, MDIO_DATA(val));
107
108 /* Wait till the MDIO write is complete */
Markus Koch9c878992022-01-11 19:22:54 +0100109 while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
Ioana Ciornei799a4432020-03-18 16:47:36 +0200110 ;
111
112 return 0;
113}
114
115static const struct mdio_ops fsl_ls_mdio_ops = {
116 .read = dm_fsl_ls_mdio_read,
117 .write = dm_fsl_ls_mdio_write,
118};
119
120static int fsl_ls_mdio_probe(struct udevice *dev)
121{
122 struct fsl_ls_mdio_priv *priv = dev_get_priv(dev);
123 struct memac_mdio_controller *regs;
124
125 priv->regs_base = dev_read_addr_ptr(dev);
Ioana Ciorneifb4296e2023-01-05 17:09:48 +0200126 if (!priv->regs_base)
127 return -ENODEV;
128
Ioana Ciornei799a4432020-03-18 16:47:36 +0200129 regs = (struct memac_mdio_controller *)(priv->regs_base);
130
131 memac_setbits_32(&regs->mdio_stat,
132 MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
133
134 return 0;
135}
136
137static const struct udevice_id fsl_ls_mdio_of_ids[] = {
138 { .compatible = "fsl,ls-mdio" },
139};
140
141U_BOOT_DRIVER(fsl_ls_mdio) = {
142 .name = "fsl_ls_mdio",
143 .id = UCLASS_MDIO,
144 .of_match = fsl_ls_mdio_of_ids,
145 .probe = fsl_ls_mdio_probe,
146 .ops = &fsl_ls_mdio_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700147 .priv_auto = sizeof(struct fsl_ls_mdio_priv),
Ioana Ciornei799a4432020-03-18 16:47:36 +0200148};