Skip to content

Commit f9f4fda

Browse files
bigunclemaxLinus Walleij
authored andcommitted
pinctrl: mcp23s08: init reg_defaults from HW at probe and switch cache type
The probe function does not guarantee that chip registers are in their default state. Thus using reg_defaults for regmap is incorrect. For example, the chip may have already been configured by the bootloader before the Linux driver loads, or the mcp might not have a reset at all and not reset a state between reboots. In such cases, using reg_defaults leads to the cache values diverging from the actual registers values in the chip. Previous attempts to fix consequences of this issue were made in 'commit 3ede3f8 ("pinctrl: mcp23s08: Reset all pins to input at probe")', but this is insufficient. The OLAT register reset is also required. And there's still potential for new issues arising due to cache desynchronization of other registers. Therefore, remove reg_defaults and provide num_reg_defaults_raw. In that case the cache defaults being initialized from hardware. Also switch cache type to REGCACHE_MAPLE, which is aware of (in)valid cache entries. And remove the force reset all pins to input at probe as it is no longer required. Link: https://lore.kernel.org/all/20251009132651.649099-2-bigunclemax@gmail.com/ Suggested-by: Mike Looijmans <mike.looijmans@topic.nl> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Suggested-by: Sander Vanheule <sander@svanheule.net> Signed-off-by: Maksim Kiselev <bigunclemax@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
1 parent b459288 commit f9f4fda

1 file changed

Lines changed: 4 additions & 36 deletions

File tree

drivers/pinctrl/pinctrl-mcp23s08.c

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,6 @@
4444
#define MCP_GPIO 0x09
4545
#define MCP_OLAT 0x0a
4646

47-
static const struct reg_default mcp23x08_defaults[] = {
48-
{.reg = MCP_IODIR, .def = 0xff},
49-
{.reg = MCP_IPOL, .def = 0x00},
50-
{.reg = MCP_GPINTEN, .def = 0x00},
51-
{.reg = MCP_DEFVAL, .def = 0x00},
52-
{.reg = MCP_INTCON, .def = 0x00},
53-
{.reg = MCP_IOCON, .def = 0x00},
54-
{.reg = MCP_GPPU, .def = 0x00},
55-
{.reg = MCP_OLAT, .def = 0x00},
56-
};
57-
5847
static const struct regmap_range mcp23x08_volatile_range = {
5948
.range_min = MCP_INTF,
6049
.range_max = MCP_GPIO,
@@ -82,25 +71,13 @@ const struct regmap_config mcp23x08_regmap = {
8271
.reg_stride = 1,
8372
.volatile_table = &mcp23x08_volatile_table,
8473
.precious_table = &mcp23x08_precious_table,
85-
.reg_defaults = mcp23x08_defaults,
86-
.num_reg_defaults = ARRAY_SIZE(mcp23x08_defaults),
87-
.cache_type = REGCACHE_FLAT,
74+
.num_reg_defaults_raw = MCP_OLAT + 1,
75+
.cache_type = REGCACHE_MAPLE,
8876
.max_register = MCP_OLAT,
8977
.disable_locking = true, /* mcp->lock protects the regmap */
9078
};
9179
EXPORT_SYMBOL_GPL(mcp23x08_regmap);
9280

93-
static const struct reg_default mcp23x17_defaults[] = {
94-
{.reg = MCP_IODIR << 1, .def = 0xffff},
95-
{.reg = MCP_IPOL << 1, .def = 0x0000},
96-
{.reg = MCP_GPINTEN << 1, .def = 0x0000},
97-
{.reg = MCP_DEFVAL << 1, .def = 0x0000},
98-
{.reg = MCP_INTCON << 1, .def = 0x0000},
99-
{.reg = MCP_IOCON << 1, .def = 0x0000},
100-
{.reg = MCP_GPPU << 1, .def = 0x0000},
101-
{.reg = MCP_OLAT << 1, .def = 0x0000},
102-
};
103-
10481
static const struct regmap_range mcp23x17_volatile_range = {
10582
.range_min = MCP_INTF << 1,
10683
.range_max = MCP_GPIO << 1,
@@ -129,9 +106,8 @@ const struct regmap_config mcp23x17_regmap = {
129106
.max_register = MCP_OLAT << 1,
130107
.volatile_table = &mcp23x17_volatile_table,
131108
.precious_table = &mcp23x17_precious_table,
132-
.reg_defaults = mcp23x17_defaults,
133-
.num_reg_defaults = ARRAY_SIZE(mcp23x17_defaults),
134-
.cache_type = REGCACHE_FLAT,
109+
.num_reg_defaults_raw = MCP_OLAT + 1,
110+
.cache_type = REGCACHE_MAPLE,
135111
.val_format_endian = REGMAP_ENDIAN_LITTLE,
136112
.disable_locking = true, /* mcp->lock protects the regmap */
137113
};
@@ -642,14 +618,6 @@ int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
642618

643619
mcp->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
644620

645-
/*
646-
* Reset the chip - we don't really know what state it's in, so reset
647-
* all pins to input first to prevent surprises.
648-
*/
649-
ret = mcp_write(mcp, MCP_IODIR, mcp->chip.ngpio == 16 ? 0xFFFF : 0xFF);
650-
if (ret < 0)
651-
return ret;
652-
653621
/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
654622
* and MCP_IOCON.HAEN = 1, so we work with all chips.
655623
*/

0 commit comments

Comments
 (0)