hc
2023-11-06 9df731a176aab8e03b984b681b1bea01ccff6644
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2022 Rockchip Electronics Co., Ltd
 */
 
#include <asm-generic/gpio.h>
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <i2c.h>
#include <max96745.h>
 
struct max96745_priv {
   struct udevice *dev;
   struct gpio_desc enable_gpio;
   struct gpio_desc pwdnb_gpio;
   bool idle_disc;
};
 
static int max96745_select(struct udevice *mux, struct udevice *bus,
              uint channel)
{
   struct max96745_priv *priv = dev_get_priv(mux);
 
   if (!priv->idle_disc)
       return 0;
 
   if (channel == 1)
       dm_i2c_reg_clrset(mux, 0x0086, DIS_REM_CC,
                 FIELD_PREP(DIS_REM_CC, 0));
   else
       dm_i2c_reg_clrset(mux, 0x0076, DIS_REM_CC,
                 FIELD_PREP(DIS_REM_CC, 0));
 
   return 0;
}
 
static int max96745_deselect(struct udevice *mux, struct udevice *bus,
                uint channel)
{
   struct max96745_priv *priv = dev_get_priv(mux);
 
   if (!priv->idle_disc)
       return 0;
 
   if (channel == 1)
       dm_i2c_reg_clrset(mux, 0x0086, DIS_REM_CC,
                 FIELD_PREP(DIS_REM_CC, 1));
   else
       dm_i2c_reg_clrset(mux, 0x0076, DIS_REM_CC,
                 FIELD_PREP(DIS_REM_CC, 1));
 
   return 0;
}
 
static const struct i2c_mux_ops max96745_ops = {
   .select = max96745_select,
   .deselect = max96745_deselect,
};
 
static int max96745_power_on(struct max96745_priv *priv)
{
   int ret;
 
   if (dm_gpio_is_valid(&priv->enable_gpio)) {
       dm_gpio_set_value(&priv->enable_gpio, 1);
       mdelay(200);
   }
 
   if (dm_gpio_is_valid(&priv->pwdnb_gpio)) {
       dm_gpio_set_value(&priv->pwdnb_gpio, 0);
       mdelay(30);
   }
 
   /* Set for I2C Fast-mode speed */
   ret = dm_i2c_reg_write(priv->dev, 0x0070, 0x16);
   if (ret < 0)
       return ret;
 
   if (priv->idle_disc) {
       ret = dm_i2c_reg_clrset(priv->dev, 0x0076, DIS_REM_CC,
                   FIELD_PREP(DIS_REM_CC, 1));
       if (ret < 0)
           return ret;
 
       ret = dm_i2c_reg_clrset(priv->dev, 0x0086, DIS_REM_CC,
                   FIELD_PREP(DIS_REM_CC, 1));
       if (ret < 0)
           return ret;
   }
 
   return 0;
}
 
static int max96745_probe(struct udevice *dev)
{
   struct max96745_priv *priv = dev_get_priv(dev);
   int ret;
 
   ret = i2c_set_chip_offset_len(dev, 2);
   if (ret)
       return ret;
 
   priv->dev = dev;
   priv->idle_disc = dev_read_bool(dev, "i2c-mux-idle-disconnect");
 
   ret = gpio_request_by_name(dev, "enable-gpios", 0,
                  &priv->enable_gpio, GPIOD_IS_OUT);
   if (ret && ret != -ENOENT) {
       dev_err(dev, "%s: failed to get enable GPIO: %d\n", __func__, ret);
       return ret;
   }
 
   ret = gpio_request_by_name(dev, "pwdnb-gpios", 0,
                  &priv->pwdnb_gpio, GPIOD_IS_OUT);
   if (ret && ret != -ENOENT) {
       dev_err(dev, "%s: failed to get pwdnb GPIO: %d\n", __func__, ret);
       return ret;
   }
 
   max96745_power_on(priv);
 
   return 0;
}
 
static const struct udevice_id max96745_of_match[] = {
   { .compatible = "maxim,max96745" },
   {}
};
 
U_BOOT_DRIVER(max96745) = {
   .name = "max96745",
   .id = UCLASS_I2C_MUX,
   .of_match = max96745_of_match,
   .bind = dm_scan_fdt_dev,
   .probe = max96745_probe,
   .ops = &max96745_ops,
   .priv_auto_alloc_size = sizeof(struct max96745_priv),
};