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