Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: designware: Add support for 16bit register access

The STM SPEAr platform can only access the i2c controller register
via 16bit read/write functions. This patch adds support to
automatically detect this 16bit access mode.

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>

authored by

Stefan Roese and committed by
Wolfram Sang
a8a9f3fe 44454baa

+25 -11
+21 -10
drivers/i2c/busses/i2c-designware-core.c
··· 164 164 165 165 u32 dw_readl(struct dw_i2c_dev *dev, int offset) 166 166 { 167 - u32 value = readl(dev->base + offset); 167 + u32 value; 168 168 169 - if (dev->swab) 169 + if (dev->accessor_flags & ACCESS_16BIT) 170 + value = readw(dev->base + offset) | 171 + (readw(dev->base + offset + 2) << 16); 172 + else 173 + value = readl(dev->base + offset); 174 + 175 + if (dev->accessor_flags & ACCESS_SWAP) 170 176 return swab32(value); 171 177 else 172 178 return value; ··· 180 174 181 175 void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) 182 176 { 183 - if (dev->swab) 177 + if (dev->accessor_flags & ACCESS_SWAP) 184 178 b = swab32(b); 185 179 186 - writel(b, dev->base + offset); 180 + if (dev->accessor_flags & ACCESS_16BIT) { 181 + writew((u16)b, dev->base + offset); 182 + writew((u16)(b >> 16), dev->base + offset + 2); 183 + } else { 184 + writel(b, dev->base + offset); 185 + } 187 186 } 188 187 189 188 static u32 ··· 262 251 263 252 input_clock_khz = dev->get_clk_rate_khz(dev); 264 253 265 - /* Configure register endianess access */ 266 254 reg = dw_readl(dev, DW_IC_COMP_TYPE); 267 255 if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) { 268 - dev->swab = 1; 269 - reg = DW_IC_COMP_TYPE_VALUE; 270 - } 271 - 272 - if (reg != DW_IC_COMP_TYPE_VALUE) { 256 + /* Configure register endianess access */ 257 + dev->accessor_flags |= ACCESS_SWAP; 258 + } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) { 259 + /* Configure register access mode 16bit */ 260 + dev->accessor_flags |= ACCESS_16BIT; 261 + } else if (reg != DW_IC_COMP_TYPE_VALUE) { 273 262 dev_err(dev->dev, "Unknown Synopsys component type: " 274 263 "0x%08x\n", reg); 275 264 return -ENODEV;
+4 -1
drivers/i2c/busses/i2c-designware-core.h
··· 82 82 unsigned int status; 83 83 u32 abort_source; 84 84 int irq; 85 - int swab; 85 + u32 accessor_flags; 86 86 struct i2c_adapter adapter; 87 87 u32 functionality; 88 88 u32 master_cfg; 89 89 unsigned int tx_fifo_depth; 90 90 unsigned int rx_fifo_depth; 91 91 }; 92 + 93 + #define ACCESS_SWAP 0x00000001 94 + #define ACCESS_16BIT 0x00000002 92 95 93 96 extern u32 dw_readl(struct dw_i2c_dev *dev, int offset); 94 97 extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);