summaryrefslogtreecommitdiff
path: root/bsp/maxim/libraries/HAL_Drivers/drv_i2c.c
blob: 4ae3a0631903d79fe15c0aa2fc26e2c879dcf0b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-02-26     Jackistang   first version
 *
 */

#include "drv_i2c.h"
#include "i2c.h"
#include <rtdevice.h>
#include <rtthread.h>
#include "board.h"

#ifdef RT_USING_I2C

#if !defined(BSP_USING_I2C0) && !defined(BSP_USING_I2C1)
    #error "Please define at least one BSP_USING_I2Cx"
    /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable I2C */
#endif

#define DBG_LEVEL   DBG_LOG
#include <rtdbg.h>
#define LOG_TAG                "drv.i2c"

/* mxc config class */
struct mxc_i2c_config
{
    const char *name;
    mxc_i2c_regs_t *i2c_periph;
    i2c_speed_t speed;
    IRQn_Type irq_type;
};

struct mxc_i2c
{
    struct rt_i2c_bus_device bus;
    struct mxc_i2c_config *config;
};

static struct mxc_i2c_config i2c_config[] =
{
#ifdef BSP_USING_I2C0
    {
        .name       = "i2c0",
        .i2c_periph = MXC_I2C_GET_I2C(0),
        .irq_type   = MXC_I2C_GET_IRQ(0),
        .speed      = I2C_STD_MODE,
        /*I2C_STD_MODE: 100KHz, I2C_FAST_MODE: 400KHz, I2C_FASTPLUS_MODE: 1MHz, I2C_HS_MODE: 3.4MHz */
    },
#endif
#ifdef BSP_USING_I2C1
    {
        .name       = "i2c1",
        .i2c_periph = MXC_I2C_GET_I2C(1),
        .irq_type   = MXC_I2C_GET_IRQ(1),
        .speed      = I2C_STD_MODE,
        /*I2C_STD_MODE: 100KHz, I2C_FAST_MODE: 400KHz, I2C_FASTPLUS_MODE: 1MHz, I2C_HS_MODE: 3.4MHz */
    },
#endif
};

static struct mxc_i2c i2c_obj[sizeof(i2c_config) / sizeof(i2c_config[0])] = {0};


static rt_ssize_t mxc_i2c_mst_xfer(struct rt_i2c_bus_device *bus,
                                  struct rt_i2c_msg msgs[],
                                  rt_uint32_t num)
{
    rt_uint32_t i, ret;
    rt_uint16_t addr;
    int error;
    int restart = 0;
    struct rt_i2c_msg *msg;
    struct mxc_i2c *obj = (struct mxc_i2c *)bus;

    for (i = 0; i < num; i++)
    {
        msg = &msgs[i];

        if (msg->flags & RT_I2C_ADDR_10BIT || msg->flags & RT_I2C_NO_START || msg->flags & RT_I2C_IGNORE_NACK || msg->flags & RT_I2C_NO_READ_ACK)
        {
            LOG_E("Not support RT_I2C_ADDR_10BIT or RT_I2C_NO_START or RT_I2C_IGNORE_NACK or RT_I2C_NO_READ_ACK");
            return 0;
        }

        if (msg->flags & RT_I2C_NO_STOP)
        {
            restart = 1;
        }

        if (msg->flags & RT_I2C_RD)
        {
            addr = msg->addr << 1;
            if ((error = I2C_MasterRead(obj->config->i2c_periph, (uint8_t)addr, msg->buf, msg->len, restart)) != msg->len)
            {
                LOG_E("Error writing %d", error);
                return 0;
            }
        }
        else    /* RT_I2C_WR */
        {
            addr = msg->addr << 1;
            if ((error = I2C_MasterWrite(obj->config->i2c_periph, (uint8_t)addr, msg->buf, msg->len, restart)) != msg->len)
            {
                LOG_E("Error writing %d", error);
                return 0;
            }
        }
    }
    ret = i;

    return ret;
}

static const struct rt_i2c_bus_device_ops mxc_i2c_ops =
{
    mxc_i2c_mst_xfer,
    RT_NULL,
    RT_NULL,
};

int rt_hw_i2c_init(void)
{
    rt_size_t obj_num;
    int index;
    rt_err_t result = 0;

#ifdef BSP_USING_I2C0
    NVIC_EnableIRQ(I2C0_IRQn);
#endif
#ifdef BSP_USING_I2C1
    NVIC_EnableIRQ(I2C1_IRQn);
#endif

    obj_num = sizeof(i2c_obj) / sizeof(struct mxc_i2c);
    for (index = 0; index < obj_num; index++)
    {
        /* init i2c object */
        i2c_obj[index].config = &i2c_config[index];
        i2c_obj[index].bus.ops = &mxc_i2c_ops;

        /* init i2c device */
        I2C_Shutdown(i2c_config[index].i2c_periph);
        I2C_Init(i2c_config[index].i2c_periph, i2c_config[index].speed, RT_NULL);

        /* register i2c device */
        result = rt_i2c_bus_device_register(&i2c_obj[index].bus,
                                            i2c_obj[index].config->name
                                           );
        RT_ASSERT(result == RT_EOK);
    }

    return 0;
}
INIT_DEVICE_EXPORT(rt_hw_i2c_init);

#ifdef BSP_USING_I2C0
void I2C0_IRQHandler(void)
{
    rt_interrupt_enter();
    I2C_Handler(MXC_I2C0);
    rt_interrupt_leave();
}
#endif

#ifdef BSP_USING_I2C1
void I2C1_IRQHandler(void)
{
    rt_interrupt_enter();
    I2C_Handler(MXC_I2C1);
    rt_interrupt_leave();
}
#endif

#endif /* RT_USING_I2C */