.. | .. |
---|
9 | 9 | * Copyright (C) 2009 Provigent Ltd. |
---|
10 | 10 | */ |
---|
11 | 11 | |
---|
| 12 | +#include <linux/bits.h> |
---|
| 13 | +#include <linux/compiler_types.h> |
---|
| 14 | +#include <linux/completion.h> |
---|
| 15 | +#include <linux/dev_printk.h> |
---|
| 16 | +#include <linux/errno.h> |
---|
12 | 17 | #include <linux/i2c.h> |
---|
13 | | -#include <linux/pm_qos.h> |
---|
| 18 | +#include <linux/regmap.h> |
---|
| 19 | +#include <linux/types.h> |
---|
14 | 20 | |
---|
15 | 21 | #define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \ |
---|
16 | 22 | I2C_FUNC_SMBUS_BYTE | \ |
---|
.. | .. |
---|
121 | 127 | #define STATUS_WRITE_IN_PROGRESS 0x1 |
---|
122 | 128 | #define STATUS_READ_IN_PROGRESS 0x2 |
---|
123 | 129 | |
---|
124 | | -#define TIMEOUT 20 /* ms */ |
---|
125 | | - |
---|
126 | 130 | /* |
---|
127 | 131 | * operation modes |
---|
128 | 132 | */ |
---|
.. | .. |
---|
171 | 175 | DW_IC_TX_ABRT_TXDATA_NOACK | \ |
---|
172 | 176 | DW_IC_TX_ABRT_GCALL_NOACK) |
---|
173 | 177 | |
---|
| 178 | +struct clk; |
---|
| 179 | +struct device; |
---|
| 180 | +struct reset_control; |
---|
174 | 181 | |
---|
175 | 182 | /** |
---|
176 | 183 | * struct dw_i2c_dev - private i2c-designware data |
---|
177 | 184 | * @dev: driver model device node |
---|
| 185 | + * @map: IO registers map |
---|
| 186 | + * @sysmap: System controller registers map |
---|
178 | 187 | * @base: IO registers pointer |
---|
| 188 | + * @ext: Extended IO registers pointer |
---|
179 | 189 | * @cmd_complete: tx completion indicator |
---|
180 | 190 | * @clk: input reference clock |
---|
| 191 | + * @pclk: clock required to access the registers |
---|
181 | 192 | * @slave: represent an I2C slave device |
---|
182 | 193 | * @cmd_err: run time hadware error code |
---|
183 | 194 | * @msgs: points to an array of messages currently being transferred |
---|
.. | .. |
---|
209 | 220 | * @fp_lcnt: fast plus LCNT value |
---|
210 | 221 | * @hs_hcnt: high speed HCNT value |
---|
211 | 222 | * @hs_lcnt: high speed LCNT value |
---|
212 | | - * @pm_qos: pm_qos_request used while holding a hardware lock on the bus |
---|
213 | 223 | * @acquire_lock: function to acquire a hardware lock on the bus |
---|
214 | 224 | * @release_lock: function to release a hardware lock on the bus |
---|
215 | | - * @pm_disabled: true if power-management should be disabled for this i2c-bus |
---|
| 225 | + * @shared_with_punit: true if this bus is shared with the SoCs PUNIT |
---|
216 | 226 | * @disable: function to disable the controller |
---|
217 | 227 | * @disable_int: function to disable all interrupts |
---|
218 | 228 | * @init: function to initialize the I2C hardware |
---|
219 | 229 | * @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE |
---|
| 230 | + * @suspended: set to true if the controller is suspended |
---|
220 | 231 | * |
---|
221 | 232 | * HCNT and LCNT parameters can be used if the platform knows more accurate |
---|
222 | 233 | * values than the one computed based only on the input clock frequency. |
---|
.. | .. |
---|
224 | 235 | */ |
---|
225 | 236 | struct dw_i2c_dev { |
---|
226 | 237 | struct device *dev; |
---|
| 238 | + struct regmap *map; |
---|
| 239 | + struct regmap *sysmap; |
---|
227 | 240 | void __iomem *base; |
---|
| 241 | + void __iomem *ext; |
---|
228 | 242 | struct completion cmd_complete; |
---|
229 | 243 | struct clk *clk; |
---|
| 244 | + struct clk *pclk; |
---|
230 | 245 | struct reset_control *rst; |
---|
231 | 246 | struct i2c_client *slave; |
---|
232 | 247 | u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev); |
---|
233 | | - struct dw_pci_controller *controller; |
---|
234 | 248 | int cmd_err; |
---|
235 | 249 | struct i2c_msg *msgs; |
---|
236 | 250 | int msgs_num; |
---|
.. | .. |
---|
262 | 276 | u16 fp_lcnt; |
---|
263 | 277 | u16 hs_hcnt; |
---|
264 | 278 | u16 hs_lcnt; |
---|
265 | | - struct pm_qos_request pm_qos; |
---|
266 | | - int (*acquire_lock)(struct dw_i2c_dev *dev); |
---|
267 | | - void (*release_lock)(struct dw_i2c_dev *dev); |
---|
268 | | - bool pm_disabled; |
---|
| 279 | + int (*acquire_lock)(void); |
---|
| 280 | + void (*release_lock)(void); |
---|
| 281 | + bool shared_with_punit; |
---|
269 | 282 | void (*disable)(struct dw_i2c_dev *dev); |
---|
270 | 283 | void (*disable_int)(struct dw_i2c_dev *dev); |
---|
271 | 284 | int (*init)(struct dw_i2c_dev *dev); |
---|
| 285 | + int (*set_sda_hold_time)(struct dw_i2c_dev *dev); |
---|
272 | 286 | int mode; |
---|
273 | 287 | struct i2c_bus_recovery_info rinfo; |
---|
| 288 | + bool suspended; |
---|
274 | 289 | }; |
---|
275 | 290 | |
---|
276 | | -#define ACCESS_SWAP 0x00000001 |
---|
277 | | -#define ACCESS_16BIT 0x00000002 |
---|
278 | | -#define ACCESS_INTR_MASK 0x00000004 |
---|
| 291 | +#define ACCESS_INTR_MASK 0x00000001 |
---|
| 292 | +#define ACCESS_NO_IRQ_SUSPEND 0x00000002 |
---|
279 | 293 | |
---|
280 | | -#define MODEL_CHERRYTRAIL 0x00000100 |
---|
| 294 | +#define MODEL_MSCC_OCELOT 0x00000100 |
---|
| 295 | +#define MODEL_BAIKAL_BT1 0x00000200 |
---|
| 296 | +#define MODEL_MASK 0x00000f00 |
---|
281 | 297 | |
---|
282 | | -u32 dw_readl(struct dw_i2c_dev *dev, int offset); |
---|
283 | | -void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset); |
---|
284 | | -int i2c_dw_set_reg_access(struct dw_i2c_dev *dev); |
---|
| 298 | +int i2c_dw_init_regmap(struct dw_i2c_dev *dev); |
---|
285 | 299 | u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset); |
---|
286 | 300 | u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset); |
---|
287 | 301 | int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev); |
---|
.. | .. |
---|
291 | 305 | void i2c_dw_release_lock(struct dw_i2c_dev *dev); |
---|
292 | 306 | int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev); |
---|
293 | 307 | int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev); |
---|
| 308 | +int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev); |
---|
294 | 309 | u32 i2c_dw_func(struct i2c_adapter *adap); |
---|
295 | 310 | void i2c_dw_disable(struct dw_i2c_dev *dev); |
---|
296 | 311 | void i2c_dw_disable_int(struct dw_i2c_dev *dev); |
---|
297 | 312 | |
---|
298 | 313 | static inline void __i2c_dw_enable(struct dw_i2c_dev *dev) |
---|
299 | 314 | { |
---|
300 | | - dw_writel(dev, 1, DW_IC_ENABLE); |
---|
| 315 | + regmap_write(dev->map, DW_IC_ENABLE, 1); |
---|
301 | 316 | } |
---|
302 | 317 | |
---|
303 | 318 | static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev) |
---|
304 | 319 | { |
---|
305 | | - dw_writel(dev, 0, DW_IC_ENABLE); |
---|
| 320 | + regmap_write(dev->map, DW_IC_ENABLE, 0); |
---|
306 | 321 | } |
---|
307 | 322 | |
---|
308 | 323 | void __i2c_dw_disable(struct dw_i2c_dev *dev); |
---|
309 | 324 | |
---|
310 | | -extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev); |
---|
311 | | -extern int i2c_dw_probe(struct dw_i2c_dev *dev); |
---|
| 325 | +extern void i2c_dw_configure_master(struct dw_i2c_dev *dev); |
---|
| 326 | +extern int i2c_dw_probe_master(struct dw_i2c_dev *dev); |
---|
| 327 | + |
---|
312 | 328 | #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_SLAVE) |
---|
| 329 | +extern void i2c_dw_configure_slave(struct dw_i2c_dev *dev); |
---|
313 | 330 | extern int i2c_dw_probe_slave(struct dw_i2c_dev *dev); |
---|
314 | 331 | #else |
---|
| 332 | +static inline void i2c_dw_configure_slave(struct dw_i2c_dev *dev) { } |
---|
315 | 333 | static inline int i2c_dw_probe_slave(struct dw_i2c_dev *dev) { return -EINVAL; } |
---|
316 | 334 | #endif |
---|
317 | 335 | |
---|
| 336 | +static inline int i2c_dw_probe(struct dw_i2c_dev *dev) |
---|
| 337 | +{ |
---|
| 338 | + switch (dev->mode) { |
---|
| 339 | + case DW_IC_SLAVE: |
---|
| 340 | + return i2c_dw_probe_slave(dev); |
---|
| 341 | + case DW_IC_MASTER: |
---|
| 342 | + return i2c_dw_probe_master(dev); |
---|
| 343 | + default: |
---|
| 344 | + dev_err(dev->dev, "Wrong operation mode: %d\n", dev->mode); |
---|
| 345 | + return -EINVAL; |
---|
| 346 | + } |
---|
| 347 | +} |
---|
| 348 | + |
---|
| 349 | +static inline void i2c_dw_configure(struct dw_i2c_dev *dev) |
---|
| 350 | +{ |
---|
| 351 | + if (i2c_detect_slave_mode(dev->dev)) |
---|
| 352 | + i2c_dw_configure_slave(dev); |
---|
| 353 | + else |
---|
| 354 | + i2c_dw_configure_master(dev); |
---|
| 355 | +} |
---|
| 356 | + |
---|
318 | 357 | #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_BAYTRAIL) |
---|
319 | 358 | extern int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev); |
---|
320 | | -extern void i2c_dw_remove_lock_support(struct dw_i2c_dev *dev); |
---|
321 | 359 | #else |
---|
322 | 360 | static inline int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev) { return 0; } |
---|
323 | | -static inline void i2c_dw_remove_lock_support(struct dw_i2c_dev *dev) {} |
---|
| 361 | +#endif |
---|
| 362 | + |
---|
| 363 | +int i2c_dw_validate_speed(struct dw_i2c_dev *dev); |
---|
| 364 | +void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev); |
---|
| 365 | + |
---|
| 366 | +#if IS_ENABLED(CONFIG_ACPI) |
---|
| 367 | +int i2c_dw_acpi_configure(struct device *device); |
---|
| 368 | +#else |
---|
| 369 | +static inline int i2c_dw_acpi_configure(struct device *device) { return -ENODEV; } |
---|
324 | 370 | #endif |
---|