Skip to content

Commit 8670de9

Browse files
PatrickRudolphlinusw
authored andcommitted
pinctrl: cy8c95x0: Use regmap ranges
Instead of implementing a custom register paging mechanism in the driver use the existing regmap ranges feature. Signed-off-by: Patrick Rudolph <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Linus Walleij <[email protected]>
1 parent f71aba3 commit 8670de9

File tree

1 file changed

+53
-126
lines changed

1 file changed

+53
-126
lines changed

drivers/pinctrl/pinctrl-cy8c95x0.c

Lines changed: 53 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,14 @@
5858

5959
#define CY8C95X0_PIN_TO_OFFSET(x) (((x) >= 20) ? ((x) + 4) : (x))
6060

61-
#define CY8C95X0_MUX_REGMAP_TO_PORT(x) ((x) / MUXED_STRIDE)
62-
#define CY8C95X0_MUX_REGMAP_TO_REG(x) (((x) % MUXED_STRIDE) + CY8C95X0_INTMASK)
63-
#define CY8C95X0_MUX_REGMAP_TO_OFFSET(x, p) ((x) - CY8C95X0_INTMASK + (p) * MUXED_STRIDE)
61+
#define MAX_BANK 8
62+
#define BANK_SZ 8
63+
#define MAX_LINE (MAX_BANK * BANK_SZ)
64+
#define MUXED_STRIDE (CY8C95X0_DRV_HIZ - CY8C95X0_INTMASK)
65+
#define CY8C95X0_GPIO_MASK GENMASK(7, 0)
66+
#define CY8C95X0_VIRTUAL (CY8C95X0_COMMAND + 1)
67+
#define CY8C95X0_MUX_REGMAP_TO_OFFSET(x, p) \
68+
(CY8C95X0_VIRTUAL + (x) - CY8C95X0_INTMASK + (p) * MUXED_STRIDE)
6469

6570
static const struct i2c_device_id cy8c95x0_id[] = {
6671
{ "cy8c9520", 20, },
@@ -120,18 +125,11 @@ static const struct dmi_system_id cy8c95x0_dmi_acpi_irq_info[] = {
120125
{}
121126
};
122127

123-
#define MAX_BANK 8
124-
#define BANK_SZ 8
125-
#define MAX_LINE (MAX_BANK * BANK_SZ)
126-
#define MUXED_STRIDE 16
127-
#define CY8C95X0_GPIO_MASK GENMASK(7, 0)
128-
129128
/**
130129
* struct cy8c95x0_pinctrl - driver data
131130
* @regmap: Device's regmap. Only direct access registers.
132-
* @muxed_regmap: Regmap for all muxed registers.
133131
* @irq_lock: IRQ bus lock
134-
* @i2c_lock: Mutex for the device internal mux register
132+
* @i2c_lock: Mutex to hold while using the regmap
135133
* @irq_mask: I/O bits affected by interrupts
136134
* @irq_trig_raise: I/O bits affected by raising voltage level
137135
* @irq_trig_fall: I/O bits affected by falling voltage level
@@ -152,7 +150,6 @@ static const struct dmi_system_id cy8c95x0_dmi_acpi_irq_info[] = {
152150
*/
153151
struct cy8c95x0_pinctrl {
154152
struct regmap *regmap;
155-
struct regmap *muxed_regmap;
156153
struct mutex irq_lock;
157154
struct mutex i2c_lock;
158155
DECLARE_BITMAP(irq_mask, MAX_LINE);
@@ -331,6 +328,9 @@ static int cypress_get_pin_mask(struct cy8c95x0_pinctrl *chip, unsigned int pin)
331328

332329
static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg)
333330
{
331+
if (reg >= CY8C95X0_VIRTUAL)
332+
return true;
333+
334334
switch (reg) {
335335
case 0x24 ... 0x27:
336336
return false;
@@ -341,6 +341,9 @@ static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg)
341341

342342
static bool cy8c95x0_writeable_register(struct device *dev, unsigned int reg)
343343
{
344+
if (reg >= CY8C95X0_VIRTUAL)
345+
return true;
346+
344347
switch (reg) {
345348
case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7):
346349
return false;
@@ -433,106 +436,33 @@ static bool cy8c95x0_quick_path_register(unsigned int reg)
433436
}
434437
}
435438

436-
static const struct reg_default cy8c95x0_reg_defaults[] = {
437-
{ CY8C95X0_OUTPUT_(0), GENMASK(7, 0) },
438-
{ CY8C95X0_OUTPUT_(1), GENMASK(7, 0) },
439-
{ CY8C95X0_OUTPUT_(2), GENMASK(7, 0) },
440-
{ CY8C95X0_OUTPUT_(3), GENMASK(7, 0) },
441-
{ CY8C95X0_OUTPUT_(4), GENMASK(7, 0) },
442-
{ CY8C95X0_OUTPUT_(5), GENMASK(7, 0) },
443-
{ CY8C95X0_OUTPUT_(6), GENMASK(7, 0) },
444-
{ CY8C95X0_OUTPUT_(7), GENMASK(7, 0) },
445-
{ CY8C95X0_PORTSEL, 0 },
446-
{ CY8C95X0_PWMSEL, 0 },
447-
};
448-
449-
static int
450-
cy8c95x0_mux_reg_read(void *context, unsigned int off, unsigned int *val)
451-
{
452-
struct cy8c95x0_pinctrl *chip = context;
453-
u8 port = CY8C95X0_MUX_REGMAP_TO_PORT(off);
454-
int ret, reg = CY8C95X0_MUX_REGMAP_TO_REG(off);
455-
456-
/* Select the correct bank */
457-
ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
458-
if (ret < 0)
459-
goto out;
460-
461-
/*
462-
* Read the register through direct access regmap. The target range
463-
* is marked volatile.
464-
*/
465-
return regmap_read(chip->regmap, reg, val);
466-
}
467-
468-
static int
469-
cy8c95x0_mux_reg_write(void *context, unsigned int off, unsigned int val)
470-
{
471-
struct cy8c95x0_pinctrl *chip = context;
472-
u8 port = CY8C95X0_MUX_REGMAP_TO_PORT(off);
473-
int ret, reg = CY8C95X0_MUX_REGMAP_TO_REG(off);
474-
475-
/* Select the correct bank */
476-
ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
477-
if (ret < 0)
478-
goto out;
479-
480-
/*
481-
* Write the register through direct access regmap. The target range
482-
* is marked volatile.
483-
*/
484-
return regmap_write(chip->regmap, reg, val);
485-
}
486-
487-
static bool cy8c95x0_mux_accessible_register(struct device *dev, unsigned int off)
488-
{
489-
struct i2c_client *i2c = to_i2c_client(dev);
490-
struct cy8c95x0_pinctrl *chip = i2c_get_clientdata(i2c);
491-
u8 port = CY8C95X0_MUX_REGMAP_TO_PORT(off);
492-
u8 reg = CY8C95X0_MUX_REGMAP_TO_REG(off);
493-
494-
if (port >= chip->nport)
495-
return false;
496-
497-
return cy8c95x0_muxed_register(reg);
498-
}
499-
500-
static struct regmap_bus cy8c95x0_regmap_bus = {
501-
.reg_read = cy8c95x0_mux_reg_read,
502-
.reg_write = cy8c95x0_mux_reg_write,
503-
};
504-
505-
/* Regmap for muxed registers CY8C95X0_INTMASK - CY8C95X0_DRV_HIZ */
506-
static const struct regmap_config cy8c95x0_muxed_regmap = {
507-
.name = "muxed",
508-
.reg_bits = 8,
509-
.val_bits = 8,
510-
.cache_type = REGCACHE_FLAT,
511-
.use_single_read = true,
512-
.use_single_write = true,
513-
.max_register = MUXED_STRIDE * BANK_SZ,
514-
.num_reg_defaults_raw = MUXED_STRIDE * BANK_SZ,
515-
.readable_reg = cy8c95x0_mux_accessible_register,
516-
.writeable_reg = cy8c95x0_mux_accessible_register,
517-
.disable_locking = true,
439+
static const struct regmap_range_cfg cy8c95x0_ranges[] = {
440+
{
441+
.range_min = CY8C95X0_VIRTUAL,
442+
.range_max = 0, /* Updated at runtime */
443+
.selector_reg = CY8C95X0_PORTSEL,
444+
.selector_mask = 0x07,
445+
.selector_shift = 0x0,
446+
.window_start = CY8C95X0_INTMASK,
447+
.window_len = MUXED_STRIDE,
448+
}
518449
};
519450

520-
/* Direct access regmap */
521-
static const struct regmap_config cy8c95x0_i2c_regmap = {
522-
.name = "direct",
451+
static const struct regmap_config cy8c9520_i2c_regmap = {
523452
.reg_bits = 8,
524453
.val_bits = 8,
525454

526-
.reg_defaults = cy8c95x0_reg_defaults,
527-
.num_reg_defaults = ARRAY_SIZE(cy8c95x0_reg_defaults),
528-
529455
.readable_reg = cy8c95x0_readable_register,
530456
.writeable_reg = cy8c95x0_writeable_register,
531457
.volatile_reg = cy8c95x0_volatile_register,
532458
.precious_reg = cy8c95x0_precious_register,
533459

534460
.cache_type = REGCACHE_FLAT,
535-
.max_register = CY8C95X0_COMMAND,
461+
.ranges = NULL, /* Updated at runtime */
462+
.num_ranges = 1,
463+
.max_register = 0, /* Updated at runtime */
464+
.num_reg_defaults_raw = 0, /* Updated at runtime */
465+
.use_single_read = true, /* Workaround for regcache bug */
536466
.disable_locking = true,
537467
};
538468

@@ -544,7 +474,6 @@ static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip
544474
bool *change, bool async,
545475
bool force)
546476
{
547-
struct regmap *regmap;
548477
int ret, off, i, read_val;
549478

550479
/* Caller should never modify PORTSEL directly */
@@ -553,20 +482,18 @@ static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip
553482

554483
mutex_lock(&chip->i2c_lock);
555484

556-
/* Registers behind the PORTSEL mux have their own regmap */
485+
/* Registers behind the PORTSEL mux have their own range in regmap */
557486
if (cy8c95x0_muxed_register(reg)) {
558-
regmap = chip->muxed_regmap;
559487
off = CY8C95X0_MUX_REGMAP_TO_OFFSET(reg, port);
560488
} else {
561-
regmap = chip->regmap;
562489
/* Quick path direct access registers honor the port argument */
563490
if (cy8c95x0_quick_path_register(reg))
564491
off = reg + port;
565492
else
566493
off = reg;
567494
}
568495

569-
ret = regmap_update_bits_base(regmap, off, mask, val, change, async, force);
496+
ret = regmap_update_bits_base(chip->regmap, off, mask, val, change, async, force);
570497
if (ret < 0)
571498
goto out;
572499

@@ -577,16 +504,16 @@ static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip
577504
continue;
578505
off = CY8C95X0_MUX_REGMAP_TO_OFFSET(i, port);
579506

580-
ret = regmap_read(regmap, off, &read_val);
507+
ret = regmap_read(chip->regmap, off, &read_val);
581508
if (ret < 0)
582509
continue;
583510

584511
if (!(read_val & mask & val))
585512
continue;
586513

587-
regcache_cache_only(regmap, true);
588-
regmap_update_bits(regmap, off, mask & val, 0);
589-
regcache_cache_only(regmap, false);
514+
regcache_cache_only(chip->regmap, true);
515+
regmap_update_bits(chip->regmap, off, mask & val, 0);
516+
regcache_cache_only(chip->regmap, false);
590517
}
591518
}
592519
out:
@@ -662,25 +589,22 @@ static int cy8c95x0_regmap_update_bits(struct cy8c95x0_pinctrl *chip, unsigned i
662589
static int cy8c95x0_regmap_read(struct cy8c95x0_pinctrl *chip, unsigned int reg,
663590
unsigned int port, unsigned int *read_val)
664591
{
665-
struct regmap *regmap;
666592
int off, ret;
667593

668594
mutex_lock(&chip->i2c_lock);
669595

670-
/* Registers behind the PORTSEL mux have their own regmap */
596+
/* Registers behind the PORTSEL mux have their own range in regmap */
671597
if (cy8c95x0_muxed_register(reg)) {
672-
regmap = chip->muxed_regmap;
673598
off = CY8C95X0_MUX_REGMAP_TO_OFFSET(reg, port);
674599
} else {
675-
regmap = chip->regmap;
676600
/* Quick path direct access registers honor the port argument */
677601
if (cy8c95x0_quick_path_register(reg))
678602
off = reg + port;
679603
else
680604
off = reg;
681605
}
682606

683-
ret = regmap_read(regmap, off, read_val);
607+
ret = regmap_read(chip->regmap, off, read_val);
684608

685609
mutex_unlock(&chip->i2c_lock);
686610

@@ -1513,6 +1437,8 @@ static int cy8c95x0_detect(struct i2c_client *client,
15131437
static int cy8c95x0_probe(struct i2c_client *client)
15141438
{
15151439
struct cy8c95x0_pinctrl *chip;
1440+
struct regmap_config regmap_conf;
1441+
struct regmap_range_cfg regmap_range_conf;
15161442
struct regulator *reg;
15171443
int ret;
15181444

@@ -1532,15 +1458,20 @@ static int cy8c95x0_probe(struct i2c_client *client)
15321458
chip->tpin = chip->driver_data & CY8C95X0_GPIO_MASK;
15331459
chip->nport = DIV_ROUND_UP(CY8C95X0_PIN_TO_OFFSET(chip->tpin), BANK_SZ);
15341460

1461+
memcpy(&regmap_range_conf, &cy8c95x0_ranges[0], sizeof(regmap_range_conf));
1462+
15351463
switch (chip->tpin) {
15361464
case 20:
15371465
strscpy(chip->name, cy8c95x0_id[0].name, I2C_NAME_SIZE);
1466+
regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 3 * MUXED_STRIDE;
15381467
break;
15391468
case 40:
15401469
strscpy(chip->name, cy8c95x0_id[1].name, I2C_NAME_SIZE);
1470+
regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 6 * MUXED_STRIDE;
15411471
break;
15421472
case 60:
15431473
strscpy(chip->name, cy8c95x0_id[2].name, I2C_NAME_SIZE);
1474+
regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 8 * MUXED_STRIDE;
15441475
break;
15451476
default:
15461477
return -ENODEV;
@@ -1573,22 +1504,18 @@ static int cy8c95x0_probe(struct i2c_client *client)
15731504
gpiod_set_consumer_name(chip->gpio_reset, "CY8C95X0 RESET");
15741505
}
15751506

1576-
/* Generic regmap for direct access registers */
1577-
chip->regmap = devm_regmap_init_i2c(client, &cy8c95x0_i2c_regmap);
1507+
/* Regmap for direct and paged registers */
1508+
memcpy(&regmap_conf, &cy8c9520_i2c_regmap, sizeof(regmap_conf));
1509+
regmap_conf.ranges = &regmap_range_conf;
1510+
regmap_conf.max_register = regmap_range_conf.range_max;
1511+
regmap_conf.num_reg_defaults_raw = regmap_range_conf.range_max;
1512+
1513+
chip->regmap = devm_regmap_init_i2c(client, &regmap_conf);
15781514
if (IS_ERR(chip->regmap)) {
15791515
ret = PTR_ERR(chip->regmap);
15801516
goto err_exit;
15811517
}
15821518

1583-
/* Port specific regmap behind PORTSEL mux */
1584-
chip->muxed_regmap = devm_regmap_init(&client->dev, &cy8c95x0_regmap_bus,
1585-
chip, &cy8c95x0_muxed_regmap);
1586-
if (IS_ERR(chip->muxed_regmap)) {
1587-
ret = dev_err_probe(&client->dev, PTR_ERR(chip->muxed_regmap),
1588-
"Failed to register muxed regmap\n");
1589-
goto err_exit;
1590-
}
1591-
15921519
bitmap_zero(chip->push_pull, MAX_LINE);
15931520
bitmap_zero(chip->shiftmask, MAX_LINE);
15941521
bitmap_set(chip->shiftmask, 0, 20);

0 commit comments

Comments
 (0)