]> Git Repo - J-u-boot.git/blob - drivers/mux/mmio.c
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / drivers / mux / mmio.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * MMIO register bitfield-controlled multiplexer driver
4  * Based on the linux mmio multiplexer driver
5  *
6  * Copyright (C) 2017 Pengutronix, Philipp Zabel <[email protected]>
7  * Copyright (C) 2019 Texas Instrument, Jean-jacques Hiblot <[email protected]>
8  */
9 #include <dm.h>
10 #include <mux-internal.h>
11 #include <regmap.h>
12 #include <syscon.h>
13 #include <dm/device.h>
14 #include <dm/device-internal.h>
15 #include <dm/device_compat.h>
16 #include <dm/read.h>
17 #include <dm/devres.h>
18 #include <dt-bindings/mux/mux.h>
19 #include <linux/bitops.h>
20
21 static int mux_mmio_set(struct mux_control *mux, int state)
22 {
23         struct regmap_field **fields = dev_get_priv(mux->dev);
24
25         return regmap_field_write(fields[mux_control_get_index(mux)], state);
26 }
27
28 static const struct mux_control_ops mux_mmio_ops = {
29         .set = mux_mmio_set,
30 };
31
32 static const struct udevice_id mmio_mux_of_match[] = {
33         { .compatible = "mmio-mux" },
34         { .compatible = "reg-mux" },
35         { /* sentinel */ },
36 };
37
38 static int mmio_mux_probe(struct udevice *dev)
39 {
40         struct regmap_field **fields;
41         struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
42         struct regmap *regmap;
43         u32 *mux_reg_masks;
44         u32 *idle_states;
45         int num_fields;
46         int ret;
47         int i;
48
49         if (ofnode_device_is_compatible(dev_ofnode(dev), "mmio-mux"))
50                 regmap = syscon_node_to_regmap(dev_ofnode(dev->parent));
51         else
52                 regmap_init_mem(dev_ofnode(dev), &regmap);
53
54         if (IS_ERR(regmap)) {
55                 ret = PTR_ERR(regmap);
56                 dev_err(dev, "failed to get regmap: %d\n", ret);
57                 return ret;
58         }
59
60         num_fields = dev_read_size(dev, "mux-reg-masks");
61         if (num_fields < 0)
62                 return log_msg_ret("mux-reg-masks missing", -EINVAL);
63
64         num_fields /= sizeof(u32);
65         if (num_fields == 0 || num_fields % 2)
66                 ret = -EINVAL;
67         num_fields = num_fields / 2;
68
69         ret = mux_alloc_controllers(dev, num_fields);
70         if (ret < 0)
71                 return log_msg_ret("mux_alloc_controllers", ret);
72
73         fields = devm_kmalloc(dev, num_fields * sizeof(*fields), __GFP_ZERO);
74         if (!fields)
75                 return -ENOMEM;
76         dev_set_priv(dev, fields);
77
78         mux_reg_masks = devm_kmalloc(dev, num_fields * 2 * sizeof(u32),
79                                      __GFP_ZERO);
80         if (!mux_reg_masks)
81                 return -ENOMEM;
82
83         ret = dev_read_u32_array(dev, "mux-reg-masks", mux_reg_masks,
84                                  num_fields * 2);
85         if (ret < 0)
86                 return log_msg_ret("mux-reg-masks read", ret);
87
88         idle_states = devm_kmalloc(dev, num_fields * sizeof(u32), __GFP_ZERO);
89         if (!idle_states)
90                 return -ENOMEM;
91
92         ret = dev_read_u32_array(dev, "idle-states", idle_states, num_fields);
93         if (ret < 0) {
94                 log_err("idle-states");
95                 devm_kfree(dev, idle_states);
96                 idle_states = NULL;
97         }
98
99         for (i = 0; i < num_fields; i++) {
100                 struct mux_control *mux = &mux_chip->mux[i];
101                 struct reg_field field;
102                 u32 reg, mask;
103                 int bits;
104
105                 reg = mux_reg_masks[2 * i];
106                 mask = mux_reg_masks[2 * i + 1];
107
108                 field.reg = reg;
109                 field.msb = fls(mask) - 1;
110                 field.lsb = ffs(mask) - 1;
111
112                 if (mask != GENMASK(field.msb, field.lsb))
113                         return log_msg_ret("invalid mask", -EINVAL);
114
115                 fields[i] = devm_regmap_field_alloc(dev, regmap, field);
116                 if (IS_ERR(fields[i])) {
117                         ret = PTR_ERR(fields[i]);
118                         return log_msg_ret("regmap_field_alloc", ret);
119                 }
120
121                 bits = 1 + field.msb - field.lsb;
122                 mux->states = 1 << bits;
123
124                 if (!idle_states)
125                         continue;
126
127                 if (idle_states[i] != MUX_IDLE_AS_IS &&
128                     idle_states[i] >= mux->states)
129                         return log_msg_ret("idle-states range", -EINVAL);
130
131                 mux->idle_state = idle_states[i];
132         }
133
134         devm_kfree(dev, mux_reg_masks);
135         if (idle_states)
136                 devm_kfree(dev, idle_states);
137
138         return 0;
139 }
140
141 U_BOOT_DRIVER(mmio_mux) = {
142         .name = "mmio-mux",
143         .id = UCLASS_MUX,
144         .of_match = mmio_mux_of_match,
145         .probe = mmio_mux_probe,
146         .ops = &mux_mmio_ops,
147 };
This page took 0.035118 seconds and 4 git commands to generate.