1 // SPDX-License-Identifier: GPL-2.0+
14 * This driver is used for MDIO muxes driven by writing to a register of an I2C
15 * chip. The board it was developed for uses a mux controlled by on-board FPGA
16 * which in turn is accessed as a chip over I2C.
19 struct mdio_mux_i2creg_priv {
25 static int mdio_mux_i2creg_select(struct udevice *mux, int cur, int sel)
27 struct mdio_mux_i2creg_priv *priv = dev_get_priv(mux);
30 /* if last selection didn't change we're good to go */
34 val_old = dm_i2c_reg_read(priv->chip, priv->reg);
35 val = (val_old & ~priv->mask) | (sel & priv->mask);
36 debug("%s: chip %s, reg %x, val %x => %x\n", __func__, priv->chip->name,
37 priv->reg, val_old, val);
38 dm_i2c_reg_write(priv->chip, priv->reg, val);
43 static const struct mdio_mux_ops mdio_mux_i2creg_ops = {
44 .select = mdio_mux_i2creg_select,
47 static int mdio_mux_i2creg_probe(struct udevice *dev)
49 struct mdio_mux_i2creg_priv *priv = dev_get_priv(dev);
50 ofnode chip_node, bus_node;
51 struct udevice *i2c_bus;
56 /* read the register addr/mask pair */
57 err = dev_read_u32_array(dev, "mux-reg-masks", reg_mask, 2);
59 debug("%s: error reading mux-reg-masks property\n", __func__);
63 /* parent should be an I2C chip, grandparent should be an I2C bus */
64 chip_node = ofnode_get_parent(dev_ofnode(dev));
65 bus_node = ofnode_get_parent(chip_node);
67 err = uclass_get_device_by_ofnode(UCLASS_I2C, bus_node, &i2c_bus);
69 debug("%s: can't find I2C bus for node %s\n", __func__,
70 ofnode_get_name(bus_node));
74 err = ofnode_read_u32(chip_node, "reg", &chip_addr);
76 debug("%s: can't read chip address in %s\n", __func__,
77 ofnode_get_name(chip_node));
81 err = i2c_get_chip(i2c_bus, (uint)chip_addr, 1, &priv->chip);
83 debug("%s: can't find i2c chip device for addr %x\n", __func__,
88 priv->reg = (int)reg_mask[0];
89 priv->mask = (int)reg_mask[1];
91 debug("%s: chip %s, reg %x, mask %x\n", __func__, priv->chip->name,
92 priv->reg, priv->mask);
97 static const struct udevice_id mdio_mux_i2creg_ids[] = {
98 { .compatible = "mdio-mux-i2creg" },
102 U_BOOT_DRIVER(mdio_mux_i2creg) = {
103 .name = "mdio_mux_i2creg",
104 .id = UCLASS_MDIO_MUX,
105 .of_match = mdio_mux_i2creg_ids,
106 .probe = mdio_mux_i2creg_probe,
107 .ops = &mdio_mux_i2creg_ops,
108 .priv_auto = sizeof(struct mdio_mux_i2creg_priv),