1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-08-08     thread-liu   first version
9  */
10 
11 #include "board.h"
12 
13 #include "mfxstm32l152.h"
14 #define DRV_DEBUG
15 #define LOG_TAG             "drv.mfx"
16 #include <drv_log.h>
17 
18 #define CHIP_ADDRESS    0x42     /* mfx address */
19 #define I2C_NAME       "i2c2"
20 
21 struct st_mfx
22 {
23     struct rt_device dev;
24     struct rt_i2c_bus_device *i2c_bus;
25     rt_uint8_t id;
26     rt_uint16_t type;
27 };
28 static struct st_mfx rt_mfx = {0};
29 static IO_DrvTypeDef *IoDrv = NULL;
30 
read_reg(struct rt_i2c_bus_device * bus,rt_uint8_t reg,rt_uint16_t len,rt_uint8_t * buf)31 static rt_err_t read_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint16_t len, rt_uint8_t *buf)
32 {
33     struct rt_i2c_msg msg[2] = {0, 0};
34 
35     RT_ASSERT(bus != RT_NULL);
36 
37     msg[0].addr  = CHIP_ADDRESS;
38     msg[0].flags = RT_I2C_WR;
39     msg[0].buf   = &reg;
40     msg[0].len   = 1;
41 
42     msg[1].addr  = CHIP_ADDRESS;
43     msg[1].flags = RT_I2C_RD;
44     msg[1].len   = len;
45     msg[1].buf   = buf;
46 
47     if (rt_i2c_transfer(bus, msg, 2) == 2)
48     {
49         return RT_EOK;
50     }
51 
52     return -RT_ERROR;
53 }
54 
55 /* i2c write reg */
write_reg(struct rt_i2c_bus_device * bus,rt_uint8_t reg,rt_uint8_t data)56 static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data)
57 {
58     rt_uint8_t buf[2];
59     struct rt_i2c_msg msgs;
60 
61     RT_ASSERT(bus != RT_NULL);
62     buf[0] = reg;
63     buf[1] = data;
64 
65     msgs.addr  = CHIP_ADDRESS;
66     msgs.flags = RT_I2C_WR;
67     msgs.buf   = buf;
68     msgs.len   = sizeof(buf);
69 
70     if (rt_i2c_transfer(bus, &msgs, 1) == 1)
71     {
72         return RT_EOK;
73     }
74 
75     return -RT_ERROR;
76 }
77 
MFX_IO_Init(void)78 void MFX_IO_Init(void)
79 {
80     rt_mfx.i2c_bus = rt_i2c_bus_device_find(I2C_NAME);
81     if (rt_mfx.i2c_bus == RT_NULL)
82     {
83         LOG_E("can't find %c deivce", I2C_NAME);
84     }
85 }
86 
MFX_IO_DeInit(void)87 void MFX_IO_DeInit(void)
88 {
89 }
90 
MFX_IO_ITConfig(void)91 void MFX_IO_ITConfig(void)
92 {
93     static rt_uint8_t mfx_io_it_enabled = 0;
94     GPIO_InitTypeDef  gpio_init_structure;
95 
96     if(mfx_io_it_enabled == 0)
97     {
98         mfx_io_it_enabled = 1;
99         /* Enable the GPIO EXTI clock */
100         __HAL_RCC_GPIOI_CLK_ENABLE();
101 
102         gpio_init_structure.Pin   = GPIO_PIN_8;
103         gpio_init_structure.Pull  = GPIO_NOPULL;
104         gpio_init_structure.Speed = GPIO_SPEED_FREQ_LOW;
105         gpio_init_structure.Mode  = GPIO_MODE_IT_RISING;
106         HAL_GPIO_Init(GPIOI, &gpio_init_structure);
107 
108         /* Enable and set GPIO EXTI Interrupt to the lowest priority */
109         HAL_NVIC_SetPriority((IRQn_Type)(EXTI8_IRQn), 0x04, 0x00);
110         HAL_NVIC_EnableIRQ((IRQn_Type)(EXTI8_IRQn));
111     }
112 }
113 
MFX_IO_Write(rt_uint16_t Addr,rt_uint8_t Reg,rt_uint8_t Value)114 void MFX_IO_Write(rt_uint16_t Addr, rt_uint8_t Reg, rt_uint8_t Value)
115 {
116     write_reg(rt_mfx.i2c_bus, Reg, Value);
117 }
118 
MFX_IO_Read(rt_uint16_t Addr,rt_uint8_t Reg)119 rt_uint8_t MFX_IO_Read(rt_uint16_t Addr, rt_uint8_t Reg)
120 {
121     rt_uint8_t value = 0;
122     read_reg(rt_mfx.i2c_bus, Reg, 1, &value);
123 
124     return value;
125 }
126 
MFX_IO_ReadMultiple(rt_uint16_t Addr,rt_uint8_t Reg,rt_uint8_t * Buffer,rt_uint16_t Length)127 rt_uint16_t MFX_IO_ReadMultiple(rt_uint16_t Addr, rt_uint8_t Reg, rt_uint8_t *Buffer, rt_uint16_t Length)
128 {
129     return read_reg(rt_mfx.i2c_bus, Reg, Length, Buffer);
130 }
131 
MFX_IO_Delay(rt_uint32_t Delay)132 rt_weak void MFX_IO_Delay(rt_uint32_t Delay)
133 {
134     rt_thread_delay(Delay);
135 }
136 
MFX_IO_Wakeup(void)137 rt_weak void MFX_IO_Wakeup(void)
138 {
139 }
140 
MFX_IO_EnableWakeupPin(void)141 rt_weak void MFX_IO_EnableWakeupPin(void)
142 {
143 }
144 
BSP_IO_DeInit(void)145 rt_uint8_t BSP_IO_DeInit(void)
146 {
147     IoDrv = NULL;
148     return RT_EOK;
149 }
150 
BSP_IO_ITGetStatus(rt_uint32_t IoPin)151 rt_uint32_t BSP_IO_ITGetStatus(rt_uint32_t IoPin)
152 {
153     /* Return the IO Pin IT status */
154     return (IoDrv->ITStatus(0, IoPin));
155 }
156 
157 /**
158   * @brief  Clears all the IO IT pending bits.
159   * @retval None
160   */
BSP_IO_ITClear(void)161 void BSP_IO_ITClear(void)
162 {
163     /* Clear all IO IT pending bits */
164     IoDrv->ClearIT(0, MFXSTM32L152_GPIO_PINS_ALL);
165 }
166 
BSP_IO_ITClearPin(rt_uint32_t IO_Pins_To_Clear)167 void BSP_IO_ITClearPin(rt_uint32_t IO_Pins_To_Clear)
168 {
169     /* Clear only the selected list of IO IT pending bits */
170     IoDrv->ClearIT(0, IO_Pins_To_Clear);
171 }
172 
173 /**
174   * @brief  Configures the IO pin(s) according to IO mode structure value.
175   * @param  IoPin: IO pin(s) to be configured.
176   *          This parameter can be one of the following values:
177   *            @arg  MFXSTM32L152_GPIO_PIN_x: where x can be from 0 to 23.
178   * @param  IoMode: IO pin mode to configure
179   *          This parameter can be one of the following values:
180   *            @arg  IO_MODE_INPUT
181   *            @arg  IO_MODE_OUTPUT
182   *            @arg  IO_MODE_IT_RISING_EDGE
183   *            @arg  IO_MODE_IT_FALLING_EDGE
184   *            @arg  IO_MODE_IT_LOW_LEVEL
185   *            @arg  IO_MODE_IT_HIGH_LEVEL
186   *            @arg  IO_MODE_ANALOG
187   *            @arg  IO_MODE_OFF
188   *            @arg  IO_MODE_INPUT_PU,
189   *            @arg  IO_MODE_INPUT_PD,
190   *            @arg  IO_MODE_OUTPUT_OD,
191   *            @arg  IO_MODE_OUTPUT_OD_PU,
192   *            @arg  IO_MODE_OUTPUT_OD_PD,
193   *            @arg  IO_MODE_OUTPUT_PP,
194   *            @arg  IO_MODE_OUTPUT_PP_PU,
195   *            @arg  IO_MODE_OUTPUT_PP_PD,
196   *            @arg  IO_MODE_IT_RISING_EDGE_PU
197   *            @arg  IO_MODE_IT_FALLING_EDGE_PU
198   *            @arg  IO_MODE_IT_LOW_LEVEL_PU
199   *            @arg  IO_MODE_IT_HIGH_LEVEL_PU
200   *            @arg  IO_MODE_IT_RISING_EDGE_PD
201   *            @arg  IO_MODE_IT_FALLING_EDGE_PD
202   *            @arg  IO_MODE_IT_LOW_LEVEL_PD
203   *            @arg  IO_MODE_IT_HIGH_LEVEL_PD
204   * @retval RT_EOK if all initializations are OK. Other value if error.
205   */
rt_mfx_pin_mode(rt_uint32_t IoPin,IO_ModeTypedef IoMode)206 rt_uint8_t rt_mfx_pin_mode(rt_uint32_t IoPin, IO_ModeTypedef IoMode)
207 {
208     /* Configure the selected IO pin(s) mode */
209     IoDrv->Config(0, IoPin, IoMode);
210 
211     return RT_EOK;
212 }
213 
214 /**
215   * @brief  Sets the IRQ_OUT pin polarity and type
216   * @param  IoIrqOutPinPolarity: High/Low
217   * @param  IoIrqOutPinType:     OpenDrain/PushPull
218   * @retval OK
219   */
rt_mfx_config_irq(rt_uint8_t IoIrqOutPinPolarity,rt_uint8_t IoIrqOutPinType)220 rt_uint8_t rt_mfx_config_irq(rt_uint8_t IoIrqOutPinPolarity, rt_uint8_t IoIrqOutPinType)
221 {
222     if((rt_mfx.id == MFXSTM32L152_ID_1) || (rt_mfx.id == MFXSTM32L152_ID_2))
223     {
224         /* Initialize the IO driver structure */
225         mfxstm32l152_SetIrqOutPinPolarity(0, IoIrqOutPinPolarity);
226         mfxstm32l152_SetIrqOutPinType(0, IoIrqOutPinType);
227     }
228 
229     return RT_EOK;
230 }
231 
232 /**
233   * @brief  Sets the selected pins state.
234   * @param  IoPin: Selected pins to write.
235   *          This parameter can be any combination of the IO pins.
236   * @param  PinState: New pins state to write
237   * @retval None
238   */
rt_mfx_pin_write(rt_uint32_t IoPin,rt_base_t PinState)239 void rt_mfx_pin_write(rt_uint32_t IoPin, rt_base_t PinState)
240 {
241     /* Set the Pin state */
242     IoDrv->WritePin(0, IoPin, PinState);
243 }
244 
245 /**
246   * @brief  Gets the selected pins current state.
247   * @param  IoPin: Selected pins to read.
248   *          This parameter can be any combination of the IO pins.
249   * @retval The current pins state
250   */
rt_mfx_pin_read(rt_uint32_t IoPin)251 rt_uint32_t rt_mfx_pin_read(rt_uint32_t IoPin)
252 {
253     return(IoDrv->ReadPin(0, IoPin));
254 }
255 
256 /**
257   * @brief  Toggles the selected pins state.
258   * @param  IoPin: Selected pins to toggle.
259   *          This parameter can be any combination of the IO pins.
260   * @note   This function is only used to toggle one pin in the same time
261   * @retval None
262   */
rt_mfx_pin_toggle(rt_uint32_t IoPin)263 void rt_mfx_pin_toggle(rt_uint32_t IoPin)
264 {
265     /* Toggle the current pin state */
266     if(IoDrv->ReadPin(0, IoPin) != 0)
267     {
268         IoDrv->WritePin(0, IoPin, 0); /* Reset */
269     }
270     else
271     {
272         IoDrv->WritePin(0, IoPin, 1); /* Set */
273     }
274 }
275 
rt_mfx_init(void)276 int rt_mfx_init(void)
277 {
278     /* Read ID and verify the MFX is ready */
279     rt_mfx.id = mfxstm32l152_io_drv.ReadID(0);
280     if((rt_mfx.id == MFXSTM32L152_ID_1) || (rt_mfx.id == MFXSTM32L152_ID_2))
281     {
282         /* Initialize the IO driver structure */
283         IoDrv = &mfxstm32l152_io_drv;
284 
285         /* Initialize MFX */
286         IoDrv->Init(0);
287         IoDrv->Start(0, IO_PIN_ALL);
288 
289         LOG_I("mfx init success, id: 0x%x", rt_mfx.id);
290 
291         return RT_EOK;
292     }
293     LOG_I("mfx init error, id: 0x%x", rt_mfx.id);
294 
295     return -RT_ERROR;
296 }
297 INIT_DEVICE_EXPORT(rt_mfx_init);
298