1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4 */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <i2c.h>
10 #include <max96755f.h>
11 #include <dm/of_access.h>
12 #include <dm/ofnode.h>
13
max96755f_select(struct udevice * mux,struct udevice * bus,uint channel)14 static int max96755f_select(struct udevice *mux, struct udevice *bus,
15 uint channel)
16 {
17 struct max96755f_priv *priv = dev_get_priv(mux);
18 int link_cfg;
19
20 dm_i2c_reg_clrset(priv->dev, 0x0001, DIS_REM_CC,
21 FIELD_PREP(DIS_REM_CC, 0));
22
23 if (!priv->split_mode)
24 return 0;
25
26 link_cfg = dm_i2c_reg_read(priv->dev, 0x0010);
27 if ((link_cfg & LINK_CFG) == SPLITTER_MODE)
28 return 0;
29
30 if (channel == 0 && (link_cfg & LINK_CFG) != LINKA) {
31 dm_i2c_reg_clrset(priv->dev, 0x0010,
32 RESET_ONESHOT | AUTO_LINK | LINK_CFG,
33 FIELD_PREP(RESET_ONESHOT, 1) |
34 FIELD_PREP(AUTO_LINK, 0) |
35 FIELD_PREP(LINK_CFG, LINKA));
36 mdelay(50);
37 } else if (channel == 1 && (link_cfg & LINK_CFG) != LINKB) {
38 dm_i2c_reg_clrset(priv->dev, 0x0010,
39 RESET_ONESHOT | AUTO_LINK | LINK_CFG,
40 FIELD_PREP(RESET_ONESHOT, 1) |
41 FIELD_PREP(AUTO_LINK, 0) |
42 FIELD_PREP(LINK_CFG, LINKB));
43 mdelay(50);
44 }
45
46 return 0;
47 }
48
max96755f_deselect(struct udevice * mux,struct udevice * bus,uint channel)49 static int max96755f_deselect(struct udevice *mux, struct udevice *bus,
50 uint channel)
51 {
52 struct max96755f_priv *priv = dev_get_priv(mux);
53
54 dm_i2c_reg_clrset(priv->dev, 0x0001, DIS_REM_CC,
55 FIELD_PREP(DIS_REM_CC, 1));
56 return 0;
57 }
58
59 static const struct i2c_mux_ops max96755f_ops = {
60 .select = max96755f_select,
61 .deselect = max96755f_deselect,
62 };
63
max96755f_power_on(struct max96755f_priv * priv)64 static int max96755f_power_on(struct max96755f_priv *priv)
65 {
66 int ret;
67
68 if (dm_gpio_is_valid(&priv->enable_gpio)) {
69 dm_gpio_set_value(&priv->enable_gpio, 1);
70 mdelay(100);
71 }
72
73 ret = dm_i2c_reg_clrset(priv->dev, 0x0010, RESET_ALL,
74 FIELD_PREP(RESET_ALL, 1));
75 if (ret < 0)
76 return ret;
77
78 mdelay(100);
79
80 dm_i2c_reg_clrset(priv->dev, 0x0001, DIS_REM_CC,
81 FIELD_PREP(DIS_REM_CC, 1));
82 return 0;
83 }
84
max96755f_probe(struct udevice * dev)85 static int max96755f_probe(struct udevice *dev)
86 {
87 struct max96755f_priv *priv = dev_get_priv(dev);
88 ofnode child;
89 u8 nr = 0;
90 int ret;
91
92 ret = i2c_set_chip_offset_len(dev, 2);
93 if (ret)
94 return ret;
95
96 priv->dev = dev;
97
98 ret = gpio_request_by_name(dev, "enable-gpios", 0,
99 &priv->enable_gpio, GPIOD_IS_OUT);
100 if (ret && ret != -ENOENT) {
101 dev_err(dev, "%s: failed to get enable GPIO: %d\n", __func__, ret);
102 return ret;
103 }
104
105 ret = max96755f_power_on(priv);
106 if (ret) {
107 dev_err(dev, "%s: failed to power on: %d\n", __func__, ret);
108 return ret;
109 }
110
111 ofnode_for_each_subnode(child, dev_ofnode(dev)) {
112 if (!ofnode_is_available(child) ||
113 !of_find_property(ofnode_to_np(child), "reg", NULL))
114 continue;
115
116 nr++;
117 }
118
119 if (nr == 2)
120 priv->split_mode = true;
121
122 return 0;
123 }
124
125 static const struct udevice_id max96755f_of_match[] = {
126 { .compatible = "maxim,max96755f" },
127 {}
128 };
129
130 U_BOOT_DRIVER(max96755f) = {
131 .name = "max96755f",
132 .id = UCLASS_I2C_MUX,
133 .of_match = max96755f_of_match,
134 .bind = dm_scan_fdt_dev,
135 .probe = max96755f_probe,
136 .ops = &max96755f_ops,
137 .priv_auto_alloc_size = sizeof(struct max96755f_priv),
138 };
139
140