]> git.sur5r.net Git - u-boot/blob - drivers/i2c/sandbox_i2c.c
mtd: spi: Correct parameters for s25fs512s flash
[u-boot] / drivers / i2c / sandbox_i2c.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Simulate an I2C port
4  *
5  * Copyright (c) 2014 Google, Inc
6  */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <i2c.h>
12 #include <asm/test.h>
13 #include <dm/lists.h>
14 #include <dm/device-internal.h>
15
16 struct sandbox_i2c_priv {
17         bool test_mode;
18 };
19
20 static int get_emul(struct udevice *dev, struct udevice **devp,
21                     struct dm_i2c_ops **opsp)
22 {
23         struct dm_i2c_chip *plat;
24         struct udevice *child;
25         int ret;
26
27         *devp = NULL;
28         *opsp = NULL;
29         plat = dev_get_parent_platdata(dev);
30         if (!plat->emul) {
31                 ret = dm_scan_fdt_dev(dev);
32                 if (ret)
33                         return ret;
34
35                 for (device_find_first_child(dev, &child); child;
36                      device_find_next_child(&child)) {
37                         if (device_get_uclass_id(child) != UCLASS_I2C_EMUL)
38                                 continue;
39
40                         ret = device_probe(child);
41                         if (ret)
42                                 return ret;
43
44                         break;
45                 }
46
47                 if (child)
48                         plat->emul = child;
49                 else
50                         return -ENODEV;
51         }
52         *devp = plat->emul;
53         *opsp = i2c_get_ops(plat->emul);
54
55         return 0;
56 }
57
58 void sandbox_i2c_set_test_mode(struct udevice *bus, bool test_mode)
59 {
60         struct sandbox_i2c_priv *priv = dev_get_priv(bus);
61
62         priv->test_mode = test_mode;
63 }
64
65 static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
66                             int nmsgs)
67 {
68         struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus);
69         struct sandbox_i2c_priv *priv = dev_get_priv(bus);
70         struct dm_i2c_ops *ops;
71         struct udevice *emul, *dev;
72         bool is_read;
73         int ret;
74
75         /* Special test code to return success but with no emulation */
76         if (priv->test_mode && msg->addr == SANDBOX_I2C_TEST_ADDR)
77                 return 0;
78
79         ret = i2c_get_chip(bus, msg->addr, 1, &dev);
80         if (ret)
81                 return ret;
82
83         ret = get_emul(dev, &emul, &ops);
84         if (ret)
85                 return ret;
86
87         if (priv->test_mode) {
88                 /*
89                 * For testing, don't allow writing above 100KHz for writes and
90                 * 400KHz for reads.
91                 */
92                 is_read = nmsgs > 1;
93                 if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
94                         debug("%s: Max speed exceeded\n", __func__);
95                         return -EINVAL;
96                 }
97         }
98
99         return ops->xfer(emul, msg, nmsgs);
100 }
101
102 static const struct dm_i2c_ops sandbox_i2c_ops = {
103         .xfer           = sandbox_i2c_xfer,
104 };
105
106 static const struct udevice_id sandbox_i2c_ids[] = {
107         { .compatible = "sandbox,i2c" },
108         { }
109 };
110
111 U_BOOT_DRIVER(i2c_sandbox) = {
112         .name   = "i2c_sandbox",
113         .id     = UCLASS_I2C,
114         .of_match = sandbox_i2c_ids,
115         .ops    = &sandbox_i2c_ops,
116         .priv_auto_alloc_size = sizeof(struct sandbox_i2c_priv),
117 };