1 /**
2  * @file      i2c-board.c
3  *
4  * @brief     Target board I2C driver implementation
5  *
6  * @copyright Copyright (c) 2020 The Things Industries B.V.
7  *
8  * Revised BSD License
9  * Copyright The Things Industries B.V 2020. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *     * Redistributions of source code must retain the above copyright
14  *       notice, this list of conditions and the following disclaimer.
15  *     * Redistributions in binary form must reproduce the above copyright
16  *       notice, this list of conditions and the following disclaimer in the
17  *       documentation and/or other materials provided with the distribution.
18  *     * Neither the name of the Things Industries B.V nor the
19  *       names of its contributors may be used to endorse or promote products
20  *       derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE THINGS INDUSTRIES B.V BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <peripheral_clk_config.h>
35 #include <hal_gpio.h>
36 #include <hal_i2c_m_sync.h>
37 
38 #include "board.h"
39 #include "i2c-board.h"
40 
41 struct i2c_m_sync_desc I2C_INSTANCE;
42 
I2cMcuInit(I2c_t * obj,I2cId_t i2cId,PinNames scl,PinNames sda)43 void I2cMcuInit( I2c_t* obj, I2cId_t i2cId, PinNames scl, PinNames sda )
44 {
45     obj->I2cId = i2cId;
46 
47     // Clock initialization
48     hri_gclk_write_PCHCTRL_reg( GCLK, SERCOM1_GCLK_ID_CORE,
49                                 CONF_GCLK_SERCOM1_CORE_SRC | ( 1 << GCLK_PCHCTRL_CHEN_Pos ) );
50     hri_gclk_write_PCHCTRL_reg( GCLK, SERCOM1_GCLK_ID_SLOW,
51                                 CONF_GCLK_SERCOM1_SLOW_SRC | ( 1 << GCLK_PCHCTRL_CHEN_Pos ) );
52 
53     hri_mclk_set_APBCMASK_SERCOM1_bit( MCLK );
54 
55     // I2c initialization
56     i2c_m_sync_init( &I2C_INSTANCE, SERCOM1 );
57 
58     gpio_set_pin_function( sda, PINMUX_PA16C_SERCOM1_PAD0 );
59     gpio_set_pin_function( scl, PINMUX_PA17C_SERCOM1_PAD1 );
60 
61     i2c_m_sync_enable( &I2C_INSTANCE );
62 }
63 
I2cMcuDeInit(I2c_t * obj)64 void I2cMcuDeInit( I2c_t* obj )
65 {
66     // Left empty
67 }
68 
I2cMcuFormat(I2c_t * obj,I2cMode mode,I2cDutyCycle dutyCycle,bool I2cAckEnable,I2cAckAddrMode AckAddrMode,uint32_t I2cFrequency)69 void I2cMcuFormat( I2c_t* obj, I2cMode mode, I2cDutyCycle dutyCycle, bool I2cAckEnable, I2cAckAddrMode AckAddrMode,
70                    uint32_t I2cFrequency )
71 {
72     // configured via hpl_sercom_config.h
73     return;
74 }
75 
I2cMcuWriteBuffer(I2c_t * obj,uint8_t deviceAddr,uint8_t * buffer,uint16_t size)76 LmnStatus_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint8_t *buffer, uint16_t size )
77 {
78     i2c_m_sync_set_slaveaddr( &I2C_INSTANCE, deviceAddr, I2C_M_SEVEN );
79     if( io_write( &I2C_INSTANCE.io, buffer, size ) == size )
80     {
81         return 1;  // ok
82     }
83     else
84     {
85         return 0;  // something went wrong
86     }
87 }
88 
I2cMcuReadBuffer(I2c_t * obj,uint8_t deviceAddr,uint8_t * buffer,uint16_t size)89 LmnStatus_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint8_t *buffer, uint16_t size )
90 {
91     i2c_m_sync_set_slaveaddr( &I2C_INSTANCE, deviceAddr, I2C_M_SEVEN );
92     if( io_read( &I2C_INSTANCE.io, buffer, size ) == size )
93     {
94         return 1;  // ok
95     }
96     else
97     {
98         return 0;  // something went wrong
99     }
100 }
101 
I2cMcuWriteMemBuffer(I2c_t * obj,uint8_t deviceAddr,uint16_t addr,uint8_t * buffer,uint16_t size)102 LmnStatus_t I2cMcuWriteMemBuffer( I2c_t* obj, uint8_t deviceAddr, uint16_t addr, uint8_t* buffer, uint16_t size )
103 {
104     i2c_m_sync_set_slaveaddr( &I2C_INSTANCE, deviceAddr, I2C_M_SEVEN );
105     if( i2c_m_sync_cmd_write( &I2C_INSTANCE, addr, buffer, size ) == size )
106     {
107         return 1;  // ok
108     }
109     else
110     {
111         return 0;  // something went wrong
112     }
113 }
114 
I2cMcuReadMemBuffer(I2c_t * obj,uint8_t deviceAddr,uint16_t addr,uint8_t * buffer,uint16_t size)115 LmnStatus_t I2cMcuReadMemBuffer( I2c_t* obj, uint8_t deviceAddr, uint16_t addr, uint8_t* buffer, uint16_t size )
116 {
117     i2c_m_sync_set_slaveaddr( &I2C_INSTANCE, deviceAddr, I2C_M_SEVEN );
118     if( i2c_m_sync_cmd_read( &I2C_INSTANCE, addr, buffer, size ) == size )
119     {
120         return 1;  // ok
121     }
122     else
123     {
124         return 0;  // something went wrong
125     }
126 }