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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
|
// SPDX-License-Identifier: GPL-2.0
/*
* Support to GPIOs on ROHM BD73800
* Copyright 2024 ROHM Semiconductors.
* Author: Matti Vaittinen <mazziesaccount@gmail.com>
*/
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/regmap.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/rohm-bd73800.h>
#define BD73800_GPIO_MAX_PINS 4
/*
* The BD73800 has several "one time programmable" (OTP) configurations which
* can be set at manufacturing phase. Some of these options allow using
* individual pins as GPI or GPO (not both at the same time). The OTP
* configuration can't be read at run-time, so drivers rely on device-tree to
* advertise the OTP programmed in manufacturing.
*
* The pins which can be used as GPIO are:
* GPIO1, CLKOUT (GPIO2), FAULT_B, EXTEN_OUT.
*
* The OTP options 2 and 3 state for all the pins:
* - OTP2: GPI (also IRQ source)
* - OTP3: GPO (NOTE: This is actually 2 different OTP options. Either a
* register controllable output or a power-sequence controlled output.
* The "gpo" referred here means only the register controllable output.)
* The datasheet refers to this as: "<pin> output is controlled by
* GPIO<N>_OUT or power on/off sequencer to control external VRs. ON/OFF
* sequence timing is configurable."
*
* The data-sheet further says that the GPI/GPO is not a default OTP
* configuration for any of the pins. Hence the GPIO driver defaults to a pin
* not being a GPI or GPO, but requires the pin to be explicitly marked as a
* GPI or GPO in the device-tree.
*
* DT properties:
* "rohm,pin-gpio1", "rohm,pin-clkout", "rohm,pin-fault_b", "rohm,pin-exten"
* can be set to one of the values "gpi" or "gpo" to enable them to be used as
* GPIO.
*
* The amount of GPIO lines the chip exposes to the user-space (chip.ngpio) is
* always the same, regardless of the OTP variant in use. The lines which are
* not usable as GPIO on a given OTP variant are marked invalid via the GPIO
* valid_mask. This way the user-space always sees a constant amount of GPIO
* lines, where numbering (relative to the chip's base) stays also the same.
* Users can then use the valid_mask to find out which of the lines are usable.
*/
struct bd73800_gpio {
/* dev points to the platform device for devm and prints */
struct device *dev;
struct regmap *regmap;
/* Pins which have been OTP configured as GPI or GPO */
DECLARE_BITMAP(valid_mask, BD73800_GPIO_MAX_PINS);
/* Subset of valid_mask - pins which have been OTP configured as GPO */
DECLARE_BITMAP(output_mask, BD73800_GPIO_MAX_PINS);
};
static const char * const bd73800_gpio_properties[BD73800_GPIO_MAX_PINS] = {
"rohm,pin-gpio1",
"rohm,pin-clkout",
"rohm,pin-fault_b",
"rohm,pin-exten"
};
static int bd73800_gpio_get_pins(struct bd73800_gpio *data)
{
struct device *parent = data->dev->parent;
const char *val;
int i, ret;
for (i = 0; i < BD73800_GPIO_MAX_PINS; i++) {
ret = device_property_read_string(parent,
bd73800_gpio_properties[i],
&val);
if (ret) {
if (ret == -EINVAL)
continue;
return dev_err_probe(data->dev, ret,
"pin %d (%s), bad configuration\n", i,
bd73800_gpio_properties[i]);
}
if (!strcmp(val, "gpi")) {
__set_bit(i, data->valid_mask);
} else if (!strcmp(val, "gpo")) {
__set_bit(i, data->valid_mask);
__set_bit(i, data->output_mask);
} else {
dev_warn(data->dev,
"pin %d (%s), unknown value '%s' ignored\n", i,
bd73800_gpio_properties[i], val);
}
}
return 0;
}
static int bd73800_gpio_init_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask,
unsigned int ngpios)
{
struct gpio_regmap *gpio = gpiochip_get_data(gc);
struct bd73800_gpio *data = gpio_regmap_get_drvdata(gpio);
bitmap_copy(valid_mask, data->valid_mask, ngpios);
return 0;
}
/*
* The used register depends on OTP:
* - If OTP has set pin as GPO, only the GPO_OUT register is valid.
* - If OTP has set pin as GPI, only the INT_5_SRC register is valid.
*/
static int bd73800_gpio_reg_mask_xlate(struct gpio_regmap *gpio,
enum gpio_regmap_operation op,
unsigned int base, unsigned int offset,
unsigned int *reg, unsigned int *mask)
{
struct bd73800_gpio *data = gpio_regmap_get_drvdata(gpio);
bool is_output = test_bit(offset, data->output_mask);
if (is_output)
*reg = BD73800_REG_GPO_OUT;
else
*reg = base;
*mask = BIT(offset);
return 0;
}
static int gpo_bd73800_probe(struct platform_device *pdev)
{
struct gpio_regmap_config config = { };
struct bd73800_gpio *data;
struct device *parent, *dev;
int ret;
dev = &pdev->dev;
/* The device-tree and regmap come from MFD => use parent for that */
parent = dev->parent;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->dev = dev;
data->regmap = dev_get_regmap(parent, NULL);
if (!data->regmap)
return dev_err_probe(dev, -ENODEV, "no parent regmap\n");
ret = bd73800_gpio_get_pins(data);
if (ret)
return ret;
if (bitmap_empty(data->valid_mask, BD73800_GPIO_MAX_PINS)) {
/*
* The BD73800 may or may not have pins allocated for GPIO
* depending on the OTP used at manufacturing.
* If there are no pins, then we have nothing to do.
*/
dev_dbg(dev, "no GPIO pins\n");
return -ENODEV;
}
config.parent = parent;
config.regmap = data->regmap;
config.label = "bd73800";
config.ngpio = BD73800_GPIO_MAX_PINS;
config.reg_dat_base = BD73800_REG_INT_5_SRC;
config.reg_set_base = BD73800_REG_GPO_OUT;
config.reg_mask_xlate = bd73800_gpio_reg_mask_xlate;
config.init_valid_mask = bd73800_gpio_init_valid_mask;
/* All pins that are valid GPIO lines also have a fixed direction */
config.fixed_direction_mask = data->valid_mask;
config.fixed_direction_output = data->output_mask;
config.drvdata = data;
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &config));
}
static const struct platform_device_id bd73800_gpio_id[] = {
{ "bd73800-gpio" },
{ },
};
MODULE_DEVICE_TABLE(platform, bd73800_gpio_id);
static struct platform_driver gpo_bd73800_driver = {
.driver = {
.name = "bd73800-gpio",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = gpo_bd73800_probe,
.id_table = bd73800_gpio_id,
};
module_platform_driver(gpo_bd73800_driver);
MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
MODULE_DESCRIPTION("GPIO interface for BD73800");
MODULE_LICENSE("GPL");
|