1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Helper module for board specific I2C bus registration |
4 | * |
5 | * Copyright (C) 2009 Nokia Corporation. |
6 | */ |
7 | |
8 | #include "soc.h" |
9 | #include "omap_hwmod.h" |
10 | #include "omap_device.h" |
11 | |
12 | #include "prm.h" |
13 | #include "common.h" |
14 | #include "i2c.h" |
15 | |
16 | /* In register I2C_CON, Bit 15 is the I2C enable bit */ |
17 | #define I2C_EN BIT(15) |
18 | #define OMAP2_I2C_CON_OFFSET 0x24 |
19 | #define OMAP4_I2C_CON_OFFSET 0xA4 |
20 | |
21 | #define MAX_OMAP_I2C_HWMOD_NAME_LEN 16 |
22 | |
23 | /** |
24 | * omap_i2c_reset - reset the omap i2c module. |
25 | * @oh: struct omap_hwmod * |
26 | * |
27 | * The i2c moudle in omap2, omap3 had a special sequence to reset. The |
28 | * sequence is: |
29 | * - Disable the I2C. |
30 | * - Write to SOFTRESET bit. |
31 | * - Enable the I2C. |
32 | * - Poll on the RESETDONE bit. |
33 | * The sequence is implemented in below function. This is called for 2420, |
34 | * 2430 and omap3. |
35 | */ |
36 | int omap_i2c_reset(struct omap_hwmod *oh) |
37 | { |
38 | u32 v; |
39 | u16 i2c_con; |
40 | int c = 0; |
41 | |
42 | if (soc_is_omap24xx() || soc_is_omap34xx() || soc_is_am35xx()) |
43 | i2c_con = OMAP2_I2C_CON_OFFSET; |
44 | else |
45 | i2c_con = OMAP4_I2C_CON_OFFSET; |
46 | |
47 | /* Disable I2C */ |
48 | v = omap_hwmod_read(oh, i2c_con); |
49 | v &= ~I2C_EN; |
50 | omap_hwmod_write(v, oh, i2c_con); |
51 | |
52 | /* Write to the SOFTRESET bit */ |
53 | omap_hwmod_softreset(oh); |
54 | |
55 | /* Enable I2C */ |
56 | v = omap_hwmod_read(oh, i2c_con); |
57 | v |= I2C_EN; |
58 | omap_hwmod_write(v, oh, i2c_con); |
59 | |
60 | /* Poll on RESETDONE bit */ |
61 | omap_test_timeout((omap_hwmod_read(oh, |
62 | oh->class->sysc->syss_offs) |
63 | & SYSS_RESETDONE_MASK), |
64 | MAX_MODULE_SOFTRESET_WAIT, c); |
65 | |
66 | if (c == MAX_MODULE_SOFTRESET_WAIT) |
67 | pr_warn("%s: %s: softreset failed (waited %d usec)\n" , |
68 | __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT); |
69 | else |
70 | pr_debug("%s: %s: softreset in %d usec\n" , __func__, |
71 | oh->name, c); |
72 | |
73 | return 0; |
74 | } |
75 | |