]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
cc54a0f7 TK |
2 | /* |
3 | * Copyright (C) 2012 Boundary Devices Inc. | |
cc54a0f7 | 4 | */ |
d678a59d | 5 | #include <common.h> |
c6f3f323 | 6 | #include <malloc.h> |
cc54a0f7 TK |
7 | #include <asm/arch/clock.h> |
8 | #include <asm/arch/imx-regs.h> | |
c05ed00a | 9 | #include <linux/delay.h> |
1221ce45 | 10 | #include <linux/errno.h> |
cc54a0f7 | 11 | #include <asm/gpio.h> |
552a848e | 12 | #include <asm/mach-imx/mxc_i2c.h> |
cc54a0f7 TK |
13 | #include <watchdog.h> |
14 | ||
71204e95 | 15 | int force_idle_bus(void *priv) |
cc54a0f7 TK |
16 | { |
17 | int i; | |
18 | int sda, scl; | |
19 | ulong elapsed, start_time; | |
20 | struct i2c_pads_info *p = (struct i2c_pads_info *)priv; | |
21 | int ret = 0; | |
22 | ||
23 | gpio_direction_input(p->sda.gp); | |
24 | gpio_direction_input(p->scl.gp); | |
25 | ||
26 | imx_iomux_v3_setup_pad(p->sda.gpio_mode); | |
27 | imx_iomux_v3_setup_pad(p->scl.gpio_mode); | |
28 | ||
29 | sda = gpio_get_value(p->sda.gp); | |
30 | scl = gpio_get_value(p->scl.gp); | |
31 | if ((sda & scl) == 1) | |
32 | goto exit; /* Bus is idle already */ | |
33 | ||
34 | printf("%s: sda=%d scl=%d sda.gp=0x%x scl.gp=0x%x\n", __func__, | |
35 | sda, scl, p->sda.gp, p->scl.gp); | |
36 | /* Send high and low on the SCL line */ | |
37 | for (i = 0; i < 9; i++) { | |
38 | gpio_direction_output(p->scl.gp, 0); | |
39 | udelay(50); | |
40 | gpio_direction_input(p->scl.gp); | |
41 | udelay(50); | |
42 | } | |
43 | start_time = get_timer(0); | |
44 | for (;;) { | |
45 | sda = gpio_get_value(p->sda.gp); | |
46 | scl = gpio_get_value(p->scl.gp); | |
47 | if ((sda & scl) == 1) | |
48 | break; | |
29caf930 | 49 | schedule(); |
cc54a0f7 TK |
50 | elapsed = get_timer(start_time); |
51 | if (elapsed > (CONFIG_SYS_HZ / 5)) { /* .2 seconds */ | |
52 | ret = -EBUSY; | |
53 | printf("%s: failed to clear bus, sda=%d scl=%d\n", | |
54 | __func__, sda, scl); | |
55 | break; | |
56 | } | |
57 | } | |
58 | exit: | |
59 | imx_iomux_v3_setup_pad(p->sda.i2c_mode); | |
60 | imx_iomux_v3_setup_pad(p->scl.i2c_mode); | |
61 | return ret; | |
62 | } | |
63 | ||
64 | static void * const i2c_bases[] = { | |
65 | (void *)I2C1_BASE_ADDR, | |
66 | (void *)I2C2_BASE_ADDR, | |
67 | #ifdef I2C3_BASE_ADDR | |
68 | (void *)I2C3_BASE_ADDR, | |
69 | #endif | |
21a26940 HS |
70 | #ifdef I2C4_BASE_ADDR |
71 | (void *)I2C4_BASE_ADDR, | |
72 | #endif | |
c92c3a44 MW |
73 | #ifdef I2C5_BASE_ADDR |
74 | (void *)I2C5_BASE_ADDR, | |
75 | #endif | |
76 | #ifdef I2C6_BASE_ADDR | |
77 | (void *)I2C6_BASE_ADDR, | |
78 | #endif | |
cc54a0f7 TK |
79 | }; |
80 | ||
21a26940 | 81 | /* i2c_index can be from 0 - 3 */ |
edbf8b4f SG |
82 | int setup_i2c(unsigned i2c_index, int speed, int slave_addr, |
83 | struct i2c_pads_info *p) | |
cc54a0f7 | 84 | { |
cd3c5896 | 85 | char name[9]; |
edbf8b4f SG |
86 | int ret; |
87 | ||
cc54a0f7 | 88 | if (i2c_index >= ARRAY_SIZE(i2c_bases)) |
edbf8b4f | 89 | return -EINVAL; |
c6f3f323 | 90 | |
cd3c5896 MV |
91 | snprintf(name, sizeof(name), "i2c_sda%01d", i2c_index); |
92 | ret = gpio_request(p->sda.gp, name); | |
c6f3f323 | 93 | if (ret) |
cd3c5896 | 94 | return ret; |
c6f3f323 | 95 | |
cd3c5896 MV |
96 | snprintf(name, sizeof(name), "i2c_scl%01d", i2c_index); |
97 | ret = gpio_request(p->scl.gp, name); | |
c6f3f323 | 98 | if (ret) |
cd3c5896 | 99 | goto err_req; |
c6f3f323 | 100 | |
cc54a0f7 | 101 | /* Enable i2c clock */ |
edbf8b4f SG |
102 | ret = enable_i2c_clk(1, i2c_index); |
103 | if (ret) | |
104 | goto err_clk; | |
105 | ||
cc54a0f7 | 106 | /* Make sure bus is idle */ |
edbf8b4f SG |
107 | ret = force_idle_bus(p); |
108 | if (ret) | |
109 | goto err_idle; | |
110 | ||
2147a169 | 111 | #if !CONFIG_IS_ENABLED(DM_I2C) |
71204e95 PF |
112 | bus_i2c_init(i2c_index, speed, slave_addr, force_idle_bus, p); |
113 | #endif | |
edbf8b4f SG |
114 | |
115 | return 0; | |
116 | ||
117 | err_idle: | |
118 | err_clk: | |
c6f3f323 | 119 | gpio_free(p->scl.gp); |
cd3c5896 | 120 | err_req: |
c6f3f323 | 121 | gpio_free(p->sda.gp); |
c6f3f323 | 122 | |
edbf8b4f | 123 | return ret; |
cc54a0f7 | 124 | } |