global: Move remaining CONFIG_SYS_* to CFG_SYS_*
[platform/kernel/u-boot.git] / drivers / net / mdio_mux_mmioreg.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2021 BayLibre, SAS
4  * Author: Neil Armstrong <narmstrong@baylibre.com>
5  *
6  * Based on linux/drivers/net/phy/mdio-mux-mmioreg.c :
7  *   Copyright 2012 Freescale Semiconductor, Inc.
8  */
9
10 #include <dm.h>
11 #include <errno.h>
12 #include <log.h>
13 #include <miiphy.h>
14 #include <linux/io.h>
15
16 struct mdio_mux_mmioreg_priv {
17         struct udevice *chip;
18         phys_addr_t phys;
19         unsigned int iosize;
20         unsigned int mask;
21 };
22
23 static int mdio_mux_mmioreg_select(struct udevice *mux, int cur, int sel)
24 {
25         struct mdio_mux_mmioreg_priv *priv = dev_get_priv(mux);
26
27         debug("%s: %x -> %x\n", __func__, (u32)cur, (u32)sel);
28
29         /* if last selection didn't change we're good to go */
30         if (cur == sel)
31                 return 0;
32
33         switch (priv->iosize) {
34         case sizeof(u8): {
35                 u8 x, y;
36
37                 x = ioread8((void *)priv->phys);
38                 y = (x & ~priv->mask) | (u32)sel;
39                 if (x != y) {
40                         iowrite8((x & ~priv->mask) | sel, (void *)priv->phys);
41                         debug("%s: %02x -> %02x\n", __func__, x, y);
42                 }
43
44                 break;
45         }
46         case sizeof(u16): {
47                 u16 x, y;
48
49                 x = ioread16((void *)priv->phys);
50                 y = (x & ~priv->mask) | (u32)sel;
51                 if (x != y) {
52                         iowrite16((x & ~priv->mask) | sel, (void *)priv->phys);
53                         debug("%s: %04x -> %04x\n", __func__, x, y);
54                 }
55
56                 break;
57         }
58         case sizeof(u32): {
59                 u32 x, y;
60
61                 x = ioread32((void *)priv->phys);
62                 y = (x & ~priv->mask) | (u32)sel;
63                 if (x != y) {
64                         iowrite32((x & ~priv->mask) | sel, (void *)priv->phys);
65                         debug("%s: %08x -> %08x\n", __func__, x, y);
66                 }
67
68                 break;
69         }
70         }
71
72         return 0;
73 }
74
75 static const struct mdio_mux_ops mdio_mux_mmioreg_ops = {
76         .select = mdio_mux_mmioreg_select,
77 };
78
79 static int mdio_mux_mmioreg_probe(struct udevice *dev)
80 {
81         struct mdio_mux_mmioreg_priv *priv = dev_get_priv(dev);
82         phys_addr_t reg_base, reg_size;
83         u32 reg_mask;
84         int err;
85
86         reg_base = ofnode_get_addr_size_index(dev_ofnode(dev), 0, &reg_size);
87         if (reg_base == FDT_ADDR_T_NONE)
88                 return -EINVAL;
89
90         if (reg_size != sizeof(u8) &&
91             reg_size != sizeof(u16) &&
92             reg_size != sizeof(u32)) {
93                 printf("%s: only 8/16/32-bit registers are supported\n", __func__);
94                 return -EINVAL;
95         }
96
97         err = dev_read_u32(dev, "mux-mask", &reg_mask);
98         if (err) {
99                 debug("%s: error reading mux-mask property\n", __func__);
100                 return err;
101         }
102
103         if (reg_mask >= BIT(reg_size * 8)) {
104                 printf("%s: mask doesn't fix in register width\n", __func__);
105                 return -EINVAL;
106         }
107
108         priv->phys = reg_base;
109         priv->iosize = reg_size;
110         priv->mask = reg_mask;
111
112         debug("%s: %llx@%lld / %x\n", __func__, reg_base, reg_size, reg_mask);
113
114         return 0;
115 }
116
117 static const struct udevice_id mdio_mux_mmioreg_ids[] = {
118         { .compatible = "mdio-mux-mmioreg" },
119         { }
120 };
121
122 U_BOOT_DRIVER(mdio_mux_mmioreg) = {
123         .name           = "mdio_mux_mmioreg",
124         .id             = UCLASS_MDIO_MUX,
125         .of_match       = mdio_mux_mmioreg_ids,
126         .probe          = mdio_mux_mmioreg_probe,
127         .ops            = &mdio_mux_mmioreg_ops,
128         .priv_auto      = sizeof(struct mdio_mux_mmioreg_priv),
129 };