Skip to content

Commit 0daede8

Browse files
fancerwsakernel
authored andcommitted
i2c: designware: Convert driver to using regmap API
Seeing the DW I2C driver is using flags-based accessors with two conditional clauses it would be better to replace them with the regmap API IO methods and to initialize the regmap object with read/write callbacks specific to the controller registers map implementation. This will be also handy for the drivers with non-standard registers mapping (like an embedded into the Baikal-T1 System Controller DW I2C block, which glue-driver is a part of this series). As before the driver tries to detect the mapping setup at probe stage and creates a regmap object accordingly, which will be used by the rest of the code to correctly access the controller registers. In two places it was appropriate to convert the hand-written read-modify-write and read-poll-loop design patterns to the corresponding regmap API ready-to-use methods. Note the regmap IO methods return value is checked only at the probe stage. The rest of the code won't do this because basically we have MMIO-based regmap so non of the read/write methods can fail (this also won't be needed for the Baikal-T1-specific I2C controller). Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> [wsa: fix type of 'rx_valid' and remove outdated kdoc var description] Signed-off-by: Wolfram Sang <wsa@kernel.org>
1 parent c615f5c commit 0daede8

5 files changed

Lines changed: 248 additions & 156 deletions

File tree

drivers/i2c/busses/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ config I2C_DAVINCI
526526

527527
config I2C_DESIGNWARE_CORE
528528
tristate
529+
select REGMAP
529530

530531
config I2C_DESIGNWARE_SLAVE
531532
bool "Synopsys DesignWare Slave"

drivers/i2c/busses/i2c-designware-common.c

Lines changed: 126 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/kernel.h>
2222
#include <linux/module.h>
2323
#include <linux/pm_runtime.h>
24+
#include <linux/regmap.h>
2425
#include <linux/swab.h>
2526
#include <linux/types.h>
2627

@@ -57,66 +58,122 @@ static char *abort_sources[] = {
5758
"incorrect slave-transmitter mode configuration",
5859
};
5960

60-
u32 dw_readl(struct dw_i2c_dev *dev, int offset)
61+
static int dw_reg_read(void *context, unsigned int reg, unsigned int *val)
6162
{
62-
u32 value;
63+
struct dw_i2c_dev *dev = context;
6364

64-
if (dev->flags & ACCESS_16BIT)
65-
value = readw_relaxed(dev->base + offset) |
66-
(readw_relaxed(dev->base + offset + 2) << 16);
67-
else
68-
value = readl_relaxed(dev->base + offset);
65+
*val = readl_relaxed(dev->base + reg);
6966

70-
if (dev->flags & ACCESS_SWAP)
71-
return swab32(value);
72-
else
73-
return value;
67+
return 0;
7468
}
7569

76-
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
70+
static int dw_reg_write(void *context, unsigned int reg, unsigned int val)
7771
{
78-
if (dev->flags & ACCESS_SWAP)
79-
b = swab32(b);
80-
81-
if (dev->flags & ACCESS_16BIT) {
82-
writew_relaxed((u16)b, dev->base + offset);
83-
writew_relaxed((u16)(b >> 16), dev->base + offset + 2);
84-
} else {
85-
writel_relaxed(b, dev->base + offset);
86-
}
72+
struct dw_i2c_dev *dev = context;
73+
74+
writel_relaxed(val, dev->base + reg);
75+
76+
return 0;
77+
}
78+
79+
static int dw_reg_read_swab(void *context, unsigned int reg, unsigned int *val)
80+
{
81+
struct dw_i2c_dev *dev = context;
82+
83+
*val = swab32(readl_relaxed(dev->base + reg));
84+
85+
return 0;
86+
}
87+
88+
static int dw_reg_write_swab(void *context, unsigned int reg, unsigned int val)
89+
{
90+
struct dw_i2c_dev *dev = context;
91+
92+
writel_relaxed(swab32(val), dev->base + reg);
93+
94+
return 0;
95+
}
96+
97+
static int dw_reg_read_word(void *context, unsigned int reg, unsigned int *val)
98+
{
99+
struct dw_i2c_dev *dev = context;
100+
101+
*val = readw_relaxed(dev->base + reg) |
102+
(readw_relaxed(dev->base + reg + 2) << 16);
103+
104+
return 0;
105+
}
106+
107+
static int dw_reg_write_word(void *context, unsigned int reg, unsigned int val)
108+
{
109+
struct dw_i2c_dev *dev = context;
110+
111+
writew_relaxed(val, dev->base + reg);
112+
writew_relaxed(val >> 16, dev->base + reg + 2);
113+
114+
return 0;
87115
}
88116

89117
/**
90-
* i2c_dw_set_reg_access() - Set register access flags
118+
* i2c_dw_init_regmap() - Initialize registers map
91119
* @dev: device private data
92120
*
93-
* Autodetects needed register access mode and sets access flags accordingly.
94-
* This must be called before doing any other register access.
121+
* Autodetects needed register access mode and creates the regmap with
122+
* corresponding read/write callbacks. This must be called before doing any
123+
* other register access.
95124
*/
96-
int i2c_dw_set_reg_access(struct dw_i2c_dev *dev)
125+
int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
97126
{
127+
struct regmap_config map_cfg = {
128+
.reg_bits = 32,
129+
.val_bits = 32,
130+
.reg_stride = 4,
131+
.disable_locking = true,
132+
.reg_read = dw_reg_read,
133+
.reg_write = dw_reg_write,
134+
.max_register = DW_IC_COMP_TYPE,
135+
};
98136
u32 reg;
99137
int ret;
100138

139+
/*
140+
* Skip detecting the registers map configuration if the regmap has
141+
* already been provided by a higher code.
142+
*/
143+
if (dev->map)
144+
return 0;
145+
101146
ret = i2c_dw_acquire_lock(dev);
102147
if (ret)
103148
return ret;
104149

105-
reg = dw_readl(dev, DW_IC_COMP_TYPE);
150+
reg = readl(dev->base + DW_IC_COMP_TYPE);
106151
i2c_dw_release_lock(dev);
107152

108153
if (reg == swab32(DW_IC_COMP_TYPE_VALUE)) {
109-
/* Configure register endianness access */
110-
dev->flags |= ACCESS_SWAP;
154+
map_cfg.reg_read = dw_reg_read_swab;
155+
map_cfg.reg_write = dw_reg_write_swab;
111156
} else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
112-
/* Configure register access mode 16bit */
113-
dev->flags |= ACCESS_16BIT;
157+
map_cfg.reg_read = dw_reg_read_word;
158+
map_cfg.reg_write = dw_reg_write_word;
114159
} else if (reg != DW_IC_COMP_TYPE_VALUE) {
115160
dev_err(dev->dev,
116161
"Unknown Synopsys component type: 0x%08x\n", reg);
117162
return -ENODEV;
118163
}
119164

165+
/*
166+
* Note we'll check the return value of the regmap IO accessors only
167+
* at the probe stage. The rest of the code won't do this because
168+
* basically we have MMIO-based regmap so non of the read/write methods
169+
* can fail.
170+
*/
171+
dev->map = devm_regmap_init(dev->dev, NULL, dev, &map_cfg);
172+
if (IS_ERR(dev->map)) {
173+
dev_err(dev->dev, "Failed to init the registers map\n");
174+
return PTR_ERR(dev->map);
175+
}
176+
120177
return 0;
121178
}
122179

@@ -327,11 +384,17 @@ int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
327384
return ret;
328385

329386
/* Configure SDA Hold Time if required */
330-
reg = dw_readl(dev, DW_IC_COMP_VERSION);
387+
ret = regmap_read(dev->map, DW_IC_COMP_VERSION, &reg);
388+
if (ret)
389+
goto err_release_lock;
390+
331391
if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
332392
if (!dev->sda_hold_time) {
333393
/* Keep previous hold time setting if no one set it */
334-
dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
394+
ret = regmap_read(dev->map, DW_IC_SDA_HOLD,
395+
&dev->sda_hold_time);
396+
if (ret)
397+
goto err_release_lock;
335398
}
336399

337400
/*
@@ -355,22 +418,25 @@ int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
355418
dev->sda_hold_time = 0;
356419
}
357420

421+
err_release_lock:
358422
i2c_dw_release_lock(dev);
359423

360-
return 0;
424+
return ret;
361425
}
362426

363427
void __i2c_dw_disable(struct dw_i2c_dev *dev)
364428
{
365429
int timeout = 100;
430+
u32 status;
366431

367432
do {
368433
__i2c_dw_disable_nowait(dev);
369434
/*
370435
* The enable status register may be unimplemented, but
371436
* in that case this test reads zero and exits the loop.
372437
*/
373-
if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == 0)
438+
regmap_read(dev->map, DW_IC_ENABLE_STATUS, &status);
439+
if ((status & 1) == 0)
374440
return;
375441

376442
/*
@@ -449,22 +515,23 @@ void i2c_dw_release_lock(struct dw_i2c_dev *dev)
449515
*/
450516
int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
451517
{
452-
int timeout = TIMEOUT;
518+
u32 status;
519+
int ret;
453520

454-
while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) {
455-
if (timeout <= 0) {
456-
dev_warn(dev->dev, "timeout waiting for bus ready\n");
457-
i2c_recover_bus(&dev->adapter);
521+
ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
522+
!(status & DW_IC_STATUS_ACTIVITY),
523+
1100, 20000);
524+
if (ret) {
525+
dev_warn(dev->dev, "timeout waiting for bus ready\n");
458526

459-
if (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY)
460-
return -ETIMEDOUT;
461-
return 0;
462-
}
463-
timeout--;
464-
usleep_range(1000, 1100);
527+
i2c_recover_bus(&dev->adapter);
528+
529+
regmap_read(dev->map, DW_IC_STATUS, &status);
530+
if (!(status & DW_IC_STATUS_ACTIVITY))
531+
ret = 0;
465532
}
466533

467-
return 0;
534+
return ret;
468535
}
469536

470537
int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
@@ -490,15 +557,19 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
490557
return -EIO;
491558
}
492559

493-
void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
560+
int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
494561
{
495562
u32 param, tx_fifo_depth, rx_fifo_depth;
563+
int ret;
496564

497565
/*
498566
* Try to detect the FIFO depth if not set by interface driver,
499567
* the depth could be from 2 to 256 from HW spec.
500568
*/
501-
param = dw_readl(dev, DW_IC_COMP_PARAM_1);
569+
ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, &param);
570+
if (ret)
571+
return ret;
572+
502573
tx_fifo_depth = ((param >> 16) & 0xff) + 1;
503574
rx_fifo_depth = ((param >> 8) & 0xff) + 1;
504575
if (!dev->tx_fifo_depth) {
@@ -510,6 +581,8 @@ void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
510581
dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
511582
rx_fifo_depth);
512583
}
584+
585+
return 0;
513586
}
514587

515588
u32 i2c_dw_func(struct i2c_adapter *adap)
@@ -521,17 +594,19 @@ u32 i2c_dw_func(struct i2c_adapter *adap)
521594

522595
void i2c_dw_disable(struct dw_i2c_dev *dev)
523596
{
597+
u32 dummy;
598+
524599
/* Disable controller */
525600
__i2c_dw_disable(dev);
526601

527602
/* Disable all interrupts */
528-
dw_writel(dev, 0, DW_IC_INTR_MASK);
529-
dw_readl(dev, DW_IC_CLR_INTR);
603+
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
604+
regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
530605
}
531606

532607
void i2c_dw_disable_int(struct dw_i2c_dev *dev)
533608
{
534-
dw_writel(dev, 0, DW_IC_INTR_MASK);
609+
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
535610
}
536611

537612
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");

drivers/i2c/busses/i2c-designware-core.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/dev_printk.h>
1616
#include <linux/errno.h>
1717
#include <linux/i2c.h>
18+
#include <linux/regmap.h>
1819
#include <linux/types.h>
1920

2021
#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
@@ -126,8 +127,6 @@
126127
#define STATUS_WRITE_IN_PROGRESS 0x1
127128
#define STATUS_READ_IN_PROGRESS 0x2
128129

129-
#define TIMEOUT 20 /* ms */
130-
131130
/*
132131
* operation modes
133132
*/
@@ -183,7 +182,9 @@ struct reset_control;
183182
/**
184183
* struct dw_i2c_dev - private i2c-designware data
185184
* @dev: driver model device node
185+
* @map: IO registers map
186186
* @base: IO registers pointer
187+
* @ext: Extended IO registers pointer
187188
* @cmd_complete: tx completion indicator
188189
* @clk: input reference clock
189190
* @pclk: clock required to access the registers
@@ -233,6 +234,7 @@ struct reset_control;
233234
*/
234235
struct dw_i2c_dev {
235236
struct device *dev;
237+
struct regmap *map;
236238
void __iomem *base;
237239
void __iomem *ext;
238240
struct completion cmd_complete;
@@ -284,17 +286,13 @@ struct dw_i2c_dev {
284286
bool suspended;
285287
};
286288

287-
#define ACCESS_SWAP 0x00000001
288-
#define ACCESS_16BIT 0x00000002
289-
#define ACCESS_INTR_MASK 0x00000004
290-
#define ACCESS_NO_IRQ_SUSPEND 0x00000008
289+
#define ACCESS_INTR_MASK 0x00000001
290+
#define ACCESS_NO_IRQ_SUSPEND 0x00000002
291291

292292
#define MODEL_MSCC_OCELOT 0x00000100
293293
#define MODEL_MASK 0x00000f00
294294

295-
u32 dw_readl(struct dw_i2c_dev *dev, int offset);
296-
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
297-
int i2c_dw_set_reg_access(struct dw_i2c_dev *dev);
295+
int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
298296
u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
299297
u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
300298
int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
@@ -304,19 +302,19 @@ int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
304302
void i2c_dw_release_lock(struct dw_i2c_dev *dev);
305303
int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
306304
int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev);
307-
void i2c_dw_set_fifo_size(struct dw_i2c_dev *dev);
305+
int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev);
308306
u32 i2c_dw_func(struct i2c_adapter *adap);
309307
void i2c_dw_disable(struct dw_i2c_dev *dev);
310308
void i2c_dw_disable_int(struct dw_i2c_dev *dev);
311309

312310
static inline void __i2c_dw_enable(struct dw_i2c_dev *dev)
313311
{
314-
dw_writel(dev, 1, DW_IC_ENABLE);
312+
regmap_write(dev->map, DW_IC_ENABLE, 1);
315313
}
316314

317315
static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
318316
{
319-
dw_writel(dev, 0, DW_IC_ENABLE);
317+
regmap_write(dev->map, DW_IC_ENABLE, 0);
320318
}
321319

322320
void __i2c_dw_disable(struct dw_i2c_dev *dev);

0 commit comments

Comments
 (0)