summaryrefslogtreecommitdiff
path: root/bsp/microchip/common/board/sam_i2c.c
blob: 52e6392d1025690bc468fd048ac2d8c7a8bbe5f3 (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
/*
 * Copyright (c) 2006-2023, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date        Author    Email                    Notes
 * 2022-04-11  Kevin.Liu [email protected] First Release
 */

#include <rtthread.h>
#include <rtdevice.h>

#include <atmel_start.h>

#ifdef SAM_I2C_EXAMPLE

struct sam_i2c_bus
{
    struct rt_i2c_bus_device parent;
    struct i2c_m_sync_desc  *i2c_desc;
    char                    *device_name;
};

#define I2CBUS_NAME          "i2c0"

static struct sam_i2c_bus sam_i2c0 =
{
    .i2c_desc    = &I2C_0,
    .device_name = I2CBUS_NAME,
};

static rt_ssize_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus,
                                     struct rt_i2c_msg msgs[],
                                     rt_uint32_t num);
static rt_ssize_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus,
                                    struct rt_i2c_msg msgs[],
                                    rt_uint32_t num);
static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus,
                                    int cmd, void *args);

static const struct rt_i2c_bus_device_ops sam_i2c_ops =
{
    .master_xfer     = sam_i2c_master_xfer,
    .slave_xfer      = sam_i2c_slave_xfer,
    .i2c_bus_control = sam_i2c_bus_control,
};

static inline void sam_i2c_update_control(struct rt_i2c_msg *src,
                                          struct _i2c_m_msg *dest)
{
    dest->len    = (int32_t)src->len;
    dest->addr   = src->addr;
    dest->buffer = src->buf;

    /* Get I2C message R/W attribute first */
    dest->flags = dest->flags & 0x0001;

    if (dest->flags & RT_I2C_ADDR_10BIT)
        dest->flags |= I2C_M_TEN;
    else
        dest->flags |= I2C_M_SEVEN;
}

static rt_ssize_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus,
                                     struct rt_i2c_msg msgs[],
                                     rt_uint32_t num)
{
    struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus;
    struct _i2c_m_msg   i2c_msg;
    rt_size_t i;

    RT_ASSERT(bus != RT_NULL);

    for (i = 0; i < num; i++)
    {
        sam_i2c_update_control(&msgs[i], &i2c_msg);
        if (i2c_m_sync_transfer(sam_i2c->i2c_desc, &i2c_msg) != 0)
            break;
    }

    return i;
}

static rt_ssize_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus,
                                    struct rt_i2c_msg msgs[],
                                    rt_uint32_t num)
{
    return 0;
}

static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus,
                                    int cmd,
                                    void *args)
{
    return -RT_ERROR;
    struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus;

    RT_ASSERT(bus != RT_NULL);

    switch (cmd)
    {
    case RT_I2C_DEV_CTRL_CLK:
        i2c_m_sync_set_baudrate(sam_i2c->i2c_desc, 0, *(rt_uint32_t *)args);
        break;
    default:
        return -RT_EIO;
    }

    return RT_EOK;
}

int rt_hw_i2c_init(void)
{
    rt_i2c_bus_device_register(&sam_i2c0.parent, sam_i2c0.device_name);
    return 0;
}
#ifdef RT_USING_COMPONENTS_INIT
INIT_BOARD_EXPORT(rt_hw_i2c_init);
#endif
#endif
/*@}*/