blob: b9868505a3be5bcec0e0612475b4e6d44c0f6966 [file] [log] [blame]
Jean-Jacques Hiblot35b8b922020-10-16 16:16:32 +05301// 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 <kernel@pengutronix.de>
7 * Copyright (C) 2019 Texas Instrument, Jean-jacques Hiblot <jjhiblot@ti.com>
8 */
9#include <common.h>
10#include <dm.h>
11#include <mux-internal.h>
12#include <regmap.h>
13#include <syscon.h>
14#include <dm/device.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
21static 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
28static const struct mux_control_ops mux_mmio_ops = {
29 .set = mux_mmio_set,
30};
31
32static const struct udevice_id mmio_mux_of_match[] = {
33 { .compatible = "mmio-mux" },
34 { /* sentinel */ },
35};
36
37static int mmio_mux_probe(struct udevice *dev)
38{
39 struct regmap_field **fields;
40 struct mux_chip *mux_chip = dev_get_uclass_priv(dev);
41 struct regmap *regmap;
42 u32 *mux_reg_masks;
43 u32 *idle_states;
44 int num_fields;
45 int ret;
46 int i;
47
48 regmap = syscon_node_to_regmap(dev_ofnode(dev->parent));
49 if (IS_ERR(regmap)) {
50 ret = PTR_ERR(regmap);
51 dev_err(dev, "failed to get regmap: %d\n", ret);
52 return ret;
53 }
54
55 num_fields = dev_read_size(dev, "mux-reg-masks");
56 if (num_fields < 0)
57 return log_msg_ret("mux-reg-masks missing", -EINVAL);
58
59 num_fields /= sizeof(u32);
60 if (num_fields == 0 || num_fields % 2)
61 ret = -EINVAL;
62 num_fields = num_fields / 2;
63
64 ret = mux_alloc_controllers(dev, num_fields);
65 if (ret < 0)
66 return log_msg_ret("mux_alloc_controllers", ret);
67
68 fields = devm_kmalloc(dev, num_fields * sizeof(*fields), __GFP_ZERO);
69 if (!fields)
70 return -ENOMEM;
71 dev->priv = fields;
72
73 mux_reg_masks = devm_kmalloc(dev, num_fields * 2 * sizeof(u32),
74 __GFP_ZERO);
75 if (!mux_reg_masks)
76 return -ENOMEM;
77
78 ret = dev_read_u32_array(dev, "mux-reg-masks", mux_reg_masks,
79 num_fields * 2);
80 if (ret < 0)
81 return log_msg_ret("mux-reg-masks read", ret);
82
83 idle_states = devm_kmalloc(dev, num_fields * sizeof(u32), __GFP_ZERO);
84 if (!idle_states)
85 return -ENOMEM;
86
87 ret = dev_read_u32_array(dev, "idle-states", idle_states, num_fields);
88 if (ret < 0) {
89 log_err("idle-states");
90 devm_kfree(dev, idle_states);
91 idle_states = NULL;
92 }
93
94 for (i = 0; i < num_fields; i++) {
95 struct mux_control *mux = &mux_chip->mux[i];
96 struct reg_field field;
97 u32 reg, mask;
98 int bits;
99
100 reg = mux_reg_masks[2 * i];
101 mask = mux_reg_masks[2 * i + 1];
102
103 field.reg = reg;
104 field.msb = fls(mask) - 1;
105 field.lsb = ffs(mask) - 1;
106
107 if (mask != GENMASK(field.msb, field.lsb))
108 return log_msg_ret("invalid mask", -EINVAL);
109
110 fields[i] = devm_regmap_field_alloc(dev, regmap, field);
111 if (IS_ERR(fields[i])) {
112 ret = PTR_ERR(fields[i]);
113 return log_msg_ret("regmap_field_alloc", ret);
114 }
115
116 bits = 1 + field.msb - field.lsb;
117 mux->states = 1 << bits;
118
119 if (!idle_states)
120 continue;
121
122 if (idle_states[i] != MUX_IDLE_AS_IS &&
123 idle_states[i] >= mux->states)
124 return log_msg_ret("idle-states range", -EINVAL);
125
126 mux->idle_state = idle_states[i];
127 }
128
129 devm_kfree(dev, mux_reg_masks);
130 if (idle_states)
131 devm_kfree(dev, idle_states);
132
133 return 0;
134}
135
136U_BOOT_DRIVER(mmio_mux) = {
137 .name = "mmio-mux",
138 .id = UCLASS_MUX,
139 .of_match = mmio_mux_of_match,
140 .probe = mmio_mux_probe,
141 .ops = &mux_mmio_ops,
142};