drv_i2c.c 5.0 KB
Newer Older
N
nxp58695 已提交
1
/*
Y
yandld 已提交
2
 * Copyright (c) 2006-2023, RT-Thread Development Team
N
nxp58695 已提交
3 4 5 6 7 8
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2019-07-15     Magicoe      The first version for LPC55S6x
9
 * 2023-02-17     Vandoul      Add status to lpc_i2c_bus.
N
nxp58695 已提交
10
 */
mysterywolf's avatar
mysterywolf 已提交
11

N
nxp58695 已提交
12 13 14 15 16 17
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "fsl_iocon.h"
#include "fsl_gpio.h"
#include "fsl_i2c.h"
18
#include "fsl_i2c_dma.h"
N
nxp58695 已提交
19

20
#ifdef BSP_USING_I2C
N
nxp58695 已提交
21

22 23
enum
{
24 25 26
#ifdef BSP_USING_I2C1
    I2C1_INDEX,
#endif
27 28 29 30 31 32 33
#ifdef BSP_USING_I2C4
    I2C4_INDEX,
#endif
};


#define i2c_dbg                 rt_kprintf
Y
yandld 已提交
34

N
nxp58695 已提交
35 36
struct lpc_i2c_bus
{
37 38 39 40 41 42 43 44 45 46 47
    struct rt_i2c_bus_device    parent;
    I2C_Type                    *I2C;
    DMA_Type                    *DMA;
    i2c_master_dma_handle_t     i2c_mst_dma_handle;
    dma_handle_t                dmaHandle;
    rt_sem_t                    sem;
    clock_attach_id_t           i2c_clock_id;
    uint32_t                    dma_chl;
    uint32_t                    instance;
    uint32_t                    baud;
    char                        *device_name;
48
    uint32_t                    status;
49 50 51 52 53
};


struct lpc_i2c_bus lpc_obj[] =
{
54 55 56 57 58 59 60 61 62 63 64
#ifdef BSP_USING_I2C1
        {
            .I2C = I2C1,
            .DMA = DMA0,
            .dma_chl = 12,
            .device_name = "i2c1",
            .baud = 100000U,
            .instance = 1U,
            .i2c_clock_id = kFRO12M_to_FLEXCOMM1,
        },
#endif
65 66 67 68 69 70 71 72 73 74 75
#ifdef BSP_USING_I2C4
        {
            .I2C = I2C4,
            .DMA = DMA0,
            .dma_chl = 13,
            .device_name = "i2c4",
            .baud = 400000U,
            .instance = 4U,
            .i2c_clock_id = kFRO12M_to_FLEXCOMM4,
        },
#endif
N
nxp58695 已提交
76 77
};

78 79 80 81

static void i2c_mst_dma_callback(I2C_Type *base, i2c_master_dma_handle_t *handle, status_t status, void *userData)
{
    struct lpc_i2c_bus *lpc_i2c = (struct lpc_i2c_bus*)userData;
82
    lpc_i2c->status = status;
83 84 85
    rt_sem_release(lpc_i2c->sem);
}

86
static rt_ssize_t lpc_i2c_xfer(struct rt_i2c_bus_device *bus,
N
nxp58695 已提交
87 88 89 90 91
                              struct rt_i2c_msg msgs[], rt_uint32_t num)
{
    struct rt_i2c_msg *msg;
    i2c_master_transfer_t xfer = {0};
    rt_uint32_t i;
92
    rt_err_t ret = -RT_ERROR;
N
nxp58695 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

    struct lpc_i2c_bus *lpc_i2c = (struct lpc_i2c_bus *)bus;

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

        if (msg->flags & RT_I2C_RD)
        {
            xfer.slaveAddress = msg->addr;
            xfer.direction = kI2C_Read;
            xfer.subaddress = 0;
            xfer.subaddressSize = 0;
            xfer.data = msg->buf;
            xfer.dataSize = msg->len;
            if(i != 0)
                xfer.flags = kI2C_TransferRepeatedStartFlag;
            else
                xfer.flags = kI2C_TransferDefaultFlag;

113 114
          //  if (I2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
            if(I2C_MasterTransferDMA(lpc_i2c->I2C, &lpc_i2c->i2c_mst_dma_handle, &xfer) != kStatus_Success)
N
nxp58695 已提交
115
            {
116 117
                i2c_dbg("i2c bus read failed!\n");
                return i;
N
nxp58695 已提交
118
            }
119
            rt_sem_take(lpc_i2c->sem, RT_WAITING_FOREVER);
N
nxp58695 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133
        }
        else
        {
            xfer.slaveAddress = msg->addr;
            xfer.direction = kI2C_Write;
            xfer.subaddress = 0;
            xfer.subaddressSize = 0;
            xfer.data = msg->buf;
            xfer.dataSize = msg->len;
            if(i == 0)
                xfer.flags = kI2C_TransferNoStopFlag;
            else
                xfer.flags = kI2C_TransferDefaultFlag;

134 135
            //if (I2C_MasterTransferBlocking(lpc_i2c->I2C, &xfer) != kStatus_Success)
            if(I2C_MasterTransferDMA(lpc_i2c->I2C, &lpc_i2c->i2c_mst_dma_handle, &xfer) != kStatus_Success)
N
nxp58695 已提交
136
            {
137 138
                i2c_dbg("i2c bus write failed!\n");
                return i;
N
nxp58695 已提交
139
            }
140
            rt_sem_take(lpc_i2c->sem, RT_WAITING_FOREVER);
141 142 143 144
            if(lpc_i2c->status != kStatus_Success)
            {
                break;
            }
N
nxp58695 已提交
145 146 147 148 149 150 151 152
        }
    }
    ret = i;

    return ret;
}

static const struct rt_i2c_bus_device_ops i2c_ops =
mysterywolf's avatar
mysterywolf 已提交
153
{
N
nxp58695 已提交
154 155 156 157 158 159 160
    lpc_i2c_xfer,
    RT_NULL,
    RT_NULL
};

int rt_hw_i2c_init(void)
{
161
    int i;
N
nxp58695 已提交
162 163
    i2c_master_config_t masterConfig;

164 165 166
    for(i=0; i<ARRAY_SIZE(lpc_obj); i++)
    {
        CLOCK_AttachClk(lpc_obj[i].i2c_clock_id);
N
nxp58695 已提交
167

168 169
        I2C_MasterGetDefaultConfig(&masterConfig);
        masterConfig.baudRate_Bps = lpc_obj[i].baud;
N
nxp58695 已提交
170

171 172
        /* Initialize the I2C master peripheral */
        I2C_MasterInit(lpc_obj[i].I2C, &masterConfig, CLOCK_GetFlexCommClkFreq(lpc_obj[i].instance));
N
nxp58695 已提交
173

174 175
        lpc_obj[i].parent.ops = &i2c_ops;
        lpc_obj[i].sem = rt_sem_create("sem_i2c", 0, RT_IPC_FLAG_FIFO);
N
nxp58695 已提交
176

177 178
        DMA_CreateHandle(&lpc_obj[i].dmaHandle, lpc_obj[i].DMA, lpc_obj[i].dma_chl);
        I2C_MasterTransferCreateHandleDMA(lpc_obj[i].I2C, &lpc_obj[i].i2c_mst_dma_handle, i2c_mst_dma_callback, &lpc_obj[i], &lpc_obj[i].dmaHandle);
N
nxp58695 已提交
179

180 181
        rt_i2c_bus_device_register(&lpc_obj[i].parent, lpc_obj[i].device_name);
    }
N
nxp58695 已提交
182 183 184 185 186

    return 0;
}
INIT_DEVICE_EXPORT(rt_hw_i2c_init);

187
#endif /* BSP_USING_I2C */