xref: /btstack/port/renesas-ek-ra6m4a-da14531/e2-project/ra/fsp/src/r_ioport/r_ioport.c (revision c30869498fb8e98c1408c9db0e7624f02f483b73)
1 /***********************************************************************************************************************
2  * Copyright [2020-2022] Renesas Electronics Corporation and/or its affiliates.  All Rights Reserved.
3  *
4  * This software and documentation are supplied by Renesas Electronics America Inc. and may only be used with products
5  * of Renesas Electronics Corp. and its affiliates ("Renesas").  No other uses are authorized.  Renesas products are
6  * sold pursuant to Renesas terms and conditions of sale.  Purchasers are solely responsible for the selection and use
7  * of Renesas products and Renesas assumes no liability.  No license, express or implied, to any intellectual property
8  * right is granted by Renesas. This software is protected under all applicable laws, including copyright laws. Renesas
9  * reserves the right to change or discontinue this software and/or this documentation. THE SOFTWARE AND DOCUMENTATION
10  * IS DELIVERED TO YOU "AS IS," AND RENESAS MAKES NO REPRESENTATIONS OR WARRANTIES, AND TO THE FULLEST EXTENT
11  * PERMISSIBLE UNDER APPLICABLE LAW, DISCLAIMS ALL WARRANTIES, WHETHER EXPLICITLY OR IMPLICITLY, INCLUDING WARRANTIES
12  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT, WITH RESPECT TO THE SOFTWARE OR
13  * DOCUMENTATION.  RENESAS SHALL HAVE NO LIABILITY ARISING OUT OF ANY SECURITY VULNERABILITY OR BREACH.  TO THE MAXIMUM
14  * EXTENT PERMITTED BY LAW, IN NO EVENT WILL RENESAS BE LIABLE TO YOU IN CONNECTION WITH THE SOFTWARE OR DOCUMENTATION
15  * (OR ANY PERSON OR ENTITY CLAIMING RIGHTS DERIVED FROM YOU) FOR ANY LOSS, DAMAGES, OR CLAIMS WHATSOEVER, INCLUDING,
16  * WITHOUT LIMITATION, ANY DIRECT, CONSEQUENTIAL, SPECIAL, INDIRECT, PUNITIVE, OR INCIDENTAL DAMAGES; ANY LOST PROFITS,
17  * OTHER ECONOMIC DAMAGE, PROPERTY DAMAGE, OR PERSONAL INJURY; AND EVEN IF RENESAS HAS BEEN ADVISED OF THE POSSIBILITY
18  * OF SUCH LOSS, DAMAGES, CLAIMS OR COSTS.
19  **********************************************************************************************************************/
20 
21 /***********************************************************************************************************************
22  * Includes
23  **********************************************************************************************************************/
24 #include <stdint.h>
25 #include "bsp_api.h"
26 #include "r_ioport.h"
27 #include "r_ioport_api.h"
28 
29 /***********************************************************************************************************************
30  * Macro definitions
31  **********************************************************************************************************************/
32 
33 /* "PORT" in ASCII, used to determine if the module is open */
34 #define IOPORT_OPEN                       (0x504F5254U)
35 #define IOPORT_CLOSED                     (0x00000000U)
36 
37 /* Mask to get PSEL bitfield from PFS register. */
38 #define BSP_PRV_PFS_PSEL_MASK             (0x1F000000UL)
39 
40 /* Shift to get pin 0 on a package in extended data. */
41 #define IOPORT_PRV_EXISTS_B0_SHIFT        (16UL)
42 
43 /* Mask to determine if any pins on port exist on this package. */
44 #define IOPORT_PRV_PORT_EXISTS_MASK       (0xFFFF0000U)
45 
46 /* Shift to get port in bsp_io_port_t and bsp_io_port_pin_t enums. */
47 #define IOPORT_PRV_PORT_OFFSET            (8U)
48 
49 #ifndef BSP_MCU_VBATT_SUPPORT
50  #define BSP_MCU_VBATT_SUPPORT            (0U)
51 #endif
52 
53 #define IOPORT_PRV_PORT_BITS              (0xFF00U)
54 #define IOPORT_PRV_PIN_BITS               (0x00FFU)
55 
56 #define IOPORT_PRV_PCNTR_OFFSET           0x00000020U
57 
58 #define IOPORT_PRV_PERIPHERAL_FUNCTION    (1U << 16)
59 #define IOPORT_PRV_CLEAR_BITS_MASK        (0x1F01FCD5U) ///< Zero bits in mask must be written as zero to PFS register
60 
61 #define IOPORT_PRV_8BIT_MASK              (0xFFU)
62 #define IOPORT_PRV_16BIT_MASK             (0xFFFFU)
63 #define IOPORT_PRV_UPPER_16BIT_MASK       (0xFFFF0000U)
64 #define IOPORT_PRV_PFENET_MASK            (0x30U)
65 
66 #define IOPORT_PRV_SET_PWPR_PFSWE         (0x40U)
67 #define IOPORT_PRV_SET_PWPR_BOWI          (0x80U)
68 
69 #define IOPORT_PRV_PORT_ADDRESS(port_number)    ((uint32_t) (R_PORT1 - R_PORT0) * (port_number) + R_PORT0)
70 
71 /***********************************************************************************************************************
72  * Typedef definitions
73  **********************************************************************************************************************/
74 
75 /***********************************************************************************************************************
76  * Private function prototypes
77  **********************************************************************************************************************/
78 static void r_ioport_pins_config(const ioport_cfg_t * p_cfg);
79 
80 static void r_ioport_hw_pin_event_output_data_write(bsp_io_port_t  port,
81                                                     ioport_size_t  set_value,
82                                                     ioport_size_t  reset_value,
83                                                     bsp_io_level_t pin_level);
84 
85 static void r_ioport_pfs_write(bsp_io_port_pin_t pin, uint32_t value);
86 
87 #if BSP_MCU_VBATT_SUPPORT
88 static void bsp_vbatt_init(ioport_cfg_t const * const p_pin_cfg); // Used internally by BSP
89 
90 #endif
91 
92 /***********************************************************************************************************************
93  * Private global variables
94  **********************************************************************************************************************/
95 
96 /***********************************************************************************************************************
97  * Global Variables
98  **********************************************************************************************************************/
99 
100 /* IOPort Implementation of IOPort Driver  */
101 const ioport_api_t g_ioport_on_ioport =
102 {
103     .open                 = R_IOPORT_Open,
104     .close                = R_IOPORT_Close,
105     .pinsCfg              = R_IOPORT_PinsCfg,
106     .pinCfg               = R_IOPORT_PinCfg,
107     .pinEventInputRead    = R_IOPORT_PinEventInputRead,
108     .pinEventOutputWrite  = R_IOPORT_PinEventOutputWrite,
109     .pinEthernetModeCfg   = R_IOPORT_EthernetModeCfg,
110     .pinRead              = R_IOPORT_PinRead,
111     .pinWrite             = R_IOPORT_PinWrite,
112     .portDirectionSet     = R_IOPORT_PortDirectionSet,
113     .portEventInputRead   = R_IOPORT_PortEventInputRead,
114     .portEventOutputWrite = R_IOPORT_PortEventOutputWrite,
115     .portRead             = R_IOPORT_PortRead,
116     .portWrite            = R_IOPORT_PortWrite,
117 };
118 
119 #if BSP_MCU_VBATT_SUPPORT
120 static const bsp_io_port_pin_t g_vbatt_pins_input[] =
121 {
122     BSP_IO_PORT_04_PIN_02,             ///< Associated with VBTICTLR->VCH0INEN
123     BSP_IO_PORT_04_PIN_03,             ///< Associated with VBTICTLR->VCH1INEN
124     BSP_IO_PORT_04_PIN_04              ///< Associated with VBTICTLR->VCH2INEN
125 };
126 #endif
127 
128 /*******************************************************************************************************************//**
129  * @addtogroup IOPORT
130  * @{
131  **********************************************************************************************************************/
132 
133 /***********************************************************************************************************************
134  * Functions
135  **********************************************************************************************************************/
136 
137 /*******************************************************************************************************************//**
138  * Initializes internal driver data, then calls pin configuration function to configure pins.
139  *
140  * @retval FSP_SUCCESS                  Pin configuration data written to PFS register(s)
141  * @retval FSP_ERR_ASSERTION            NULL pointer
142  * @retval FSP_ERR_ALREADY_OPEN         Module is already open.
143  **********************************************************************************************************************/
R_IOPORT_Open(ioport_ctrl_t * const p_ctrl,const ioport_cfg_t * p_cfg)144 fsp_err_t R_IOPORT_Open (ioport_ctrl_t * const p_ctrl, const ioport_cfg_t * p_cfg)
145 {
146     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
147 
148 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
149     FSP_ASSERT(NULL != p_instance_ctrl);
150     FSP_ASSERT(NULL != p_cfg);
151     FSP_ASSERT(NULL != p_cfg->p_pin_cfg_data);
152     FSP_ERROR_RETURN(IOPORT_OPEN != p_instance_ctrl->open, FSP_ERR_ALREADY_OPEN);
153 #else
154     FSP_PARAMETER_NOT_USED(p_ctrl);
155 #endif
156 
157     /* Set driver status to open */
158     p_instance_ctrl->open = IOPORT_OPEN;
159 
160     r_ioport_pins_config(p_cfg);
161 
162     return FSP_SUCCESS;
163 }
164 
165 /*******************************************************************************************************************//**
166  * Resets IOPORT registers. Implements @ref ioport_api_t::close
167  *
168  * @retval FSP_SUCCESS             The IOPORT was successfully uninitialized
169  * @retval FSP_ERR_ASSERTION       p_ctrl was NULL
170  * @retval FSP_ERR_NOT_OPEN        The module has not been opened
171  *
172  **********************************************************************************************************************/
R_IOPORT_Close(ioport_ctrl_t * const p_ctrl)173 fsp_err_t R_IOPORT_Close (ioport_ctrl_t * const p_ctrl)
174 {
175     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
176 
177 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
178     FSP_ASSERT(NULL != p_instance_ctrl);
179     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
180 #else
181     FSP_PARAMETER_NOT_USED(p_ctrl);
182 #endif
183 
184     /* Set state to closed */
185     p_instance_ctrl->open = IOPORT_CLOSED;
186 
187     return FSP_SUCCESS;
188 }
189 
190 /*******************************************************************************************************************//**
191  * Configures the functions of multiple pins by loading configuration data into pin PFS registers.
192  * Implements @ref ioport_api_t::pinsCfg.
193  *
194  * This function initializes the supplied list of PmnPFS registers with the supplied values. This data can be generated
195  * by the Pins tab of the RA Configuration editor or manually by the developer. Different pin configurations can be
196  * loaded for different situations such as low power modes and testing.
197  *
198  * @retval FSP_SUCCESS             Pin configuration data written to PFS register(s)
199  * @retval FSP_ERR_NOT_OPEN        The module has not been opened
200  * @retval FSP_ERR_ASSERTION       NULL pointer
201  **********************************************************************************************************************/
R_IOPORT_PinsCfg(ioport_ctrl_t * const p_ctrl,const ioport_cfg_t * p_cfg)202 fsp_err_t R_IOPORT_PinsCfg (ioport_ctrl_t * const p_ctrl, const ioport_cfg_t * p_cfg)
203 {
204 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
205     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
206     FSP_ASSERT(NULL != p_instance_ctrl);
207     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
208     FSP_ASSERT(NULL != p_cfg);
209     FSP_ASSERT(NULL != p_cfg->p_pin_cfg_data);
210 #else
211     FSP_PARAMETER_NOT_USED(p_ctrl);
212 #endif
213 
214     r_ioport_pins_config(p_cfg);
215 
216     return FSP_SUCCESS;
217 }
218 
219 /*******************************************************************************************************************//**
220  * Configures the settings of a pin. Implements @ref ioport_api_t::pinCfg.
221  *
222  * @retval FSP_SUCCESS             Pin configured
223  * @retval FSP_ERR_NOT_OPEN        The module has not been opened
224  * @retval FSP_ERR_ASSERTION       NULL pointer
225  *
226  * @note This function is re-entrant for different pins.
227  * This function will change the configuration of the pin with the new configuration. For example it is not possible
228  * with this function to change the drive strength of a pin while leaving all the other pin settings unchanged. To
229  * achieve this the original settings with the required change will need to be written using this function.
230  **********************************************************************************************************************/
R_IOPORT_PinCfg(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,uint32_t cfg)231 fsp_err_t R_IOPORT_PinCfg (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, uint32_t cfg)
232 {
233 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
234     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
235     FSP_ASSERT(NULL != p_instance_ctrl);
236     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
237 #else
238     FSP_PARAMETER_NOT_USED(p_ctrl);
239 #endif
240 
241 #if BSP_MCU_VBATT_SUPPORT
242 
243     /* Create temporary structure for handling VBATT pins. */
244     ioport_cfg_t     temp_cfg;
245     ioport_pin_cfg_t temp_pin_cfg;
246 
247     temp_pin_cfg.pin     = pin;
248     temp_pin_cfg.pin_cfg = cfg;
249 
250     temp_cfg.number_of_pins = 1U;
251     temp_cfg.p_pin_cfg_data = &temp_pin_cfg;
252 
253     /* Handle any VBATT domain pin configuration. */
254     bsp_vbatt_init(&temp_cfg);
255 #endif
256 
257     R_BSP_PinAccessEnable();
258 
259     r_ioport_pfs_write(pin, cfg);
260 
261     R_BSP_PinAccessDisable();
262 
263     return FSP_SUCCESS;
264 }
265 
266 /*******************************************************************************************************************//**
267  * Reads the level on a pin. Implements @ref ioport_api_t::pinRead.
268  *
269  * @retval FSP_SUCCESS             Pin read
270  * @retval FSP_ERR_ASSERTION       NULL pointer
271  * @retval FSP_ERR_NOT_OPEN        The module has not been opened
272  *
273  * @note This function is re-entrant for different pins.
274  **********************************************************************************************************************/
R_IOPORT_PinRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t * p_pin_value)275 fsp_err_t R_IOPORT_PinRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t * p_pin_value)
276 {
277 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
278     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
279     FSP_ASSERT(NULL != p_instance_ctrl);
280     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
281     FSP_ASSERT(NULL != p_pin_value);
282 #else
283     FSP_PARAMETER_NOT_USED(p_ctrl);
284 #endif
285 
286     *p_pin_value = (bsp_io_level_t) R_BSP_PinRead(pin);
287 
288     return FSP_SUCCESS;
289 }
290 
291 /*******************************************************************************************************************//**
292  * Reads the value on an IO port. Implements @ref ioport_api_t::portRead.
293  *
294  * The specified port will be read, and the levels for all the pins will be returned.
295  * Each bit in the returned value corresponds to a pin on the port. For example, bit 7 corresponds
296  * to pin 7, bit 6 to pin 6, and so on.
297  *
298  * @retval FSP_SUCCESS             Port read
299  * @retval FSP_ERR_ASSERTION       NULL pointer
300  * @retval FSP_ERR_NOT_OPEN        The module has not been opened
301  *
302  * @note This function is re-entrant for different ports.
303  **********************************************************************************************************************/
R_IOPORT_PortRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t * p_port_value)304 fsp_err_t R_IOPORT_PortRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_t port, ioport_size_t * p_port_value)
305 {
306 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
307     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
308     FSP_ASSERT(NULL != p_instance_ctrl);
309     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
310     FSP_ASSERT(NULL != p_port_value);
311 #else
312     FSP_PARAMETER_NOT_USED(p_ctrl);
313 #endif
314 
315     /* Get the port address */
316     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
317 
318     /* Read current value of PCNTR2 register for the specified port */
319     *p_port_value = p_ioport_regs->PCNTR2 & IOPORT_PRV_16BIT_MASK;
320 
321     return FSP_SUCCESS;
322 }
323 
324 /*******************************************************************************************************************//**
325  * Writes to multiple pins on a port. Implements @ref ioport_api_t::portWrite.
326  *
327  * The input value will be written to the specified port. Each bit in the value parameter corresponds to a bit
328  * on the port. For example, bit 7 corresponds to pin 7, bit 6 to pin 6, and so on.
329  * Each bit in the mask parameter corresponds to a pin on the port.
330  *
331  * Only the bits with the corresponding bit in the mask value set will be updated.
332  * For example, value = 0xFFFF, mask = 0x0003 results in only bits 0 and 1 being updated.
333  *
334  * @retval FSP_SUCCESS                  Port written to
335  * @retval FSP_ERR_INVALID_ARGUMENT     The port and/or mask not valid
336  * @retval FSP_ERR_NOT_OPEN             The module has not been opened
337  * @retval FSP_ERR_ASSERTION            NULL pointerd
338  *
339  * @note This function is re-entrant for different ports. This function makes use of the PCNTR3 register to atomically
340  * modify the levels on the specified pins on a port.
341  **********************************************************************************************************************/
R_IOPORT_PortWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t value,ioport_size_t mask)342 fsp_err_t R_IOPORT_PortWrite (ioport_ctrl_t * const p_ctrl, bsp_io_port_t port, ioport_size_t value, ioport_size_t mask)
343 {
344 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
345     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
346     FSP_ASSERT(NULL != p_instance_ctrl);
347     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
348     FSP_ERROR_RETURN(mask > (ioport_size_t) 0, FSP_ERR_INVALID_ARGUMENT);
349 #else
350     FSP_PARAMETER_NOT_USED(p_ctrl);
351 #endif
352 
353     ioport_size_t setbits;
354     ioport_size_t clrbits;
355 
356     /* High bits */
357     setbits = value & mask;
358 
359     /* Low bits */
360     /* Cast to ensure size */
361     clrbits = (ioport_size_t) ((~value) & mask);
362 
363     /* Get the port address */
364     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
365 
366     /* PCNTR3 register: lower word = set data, upper word = reset_data */
367     p_ioport_regs->PCNTR3 = (uint32_t) (((uint32_t) clrbits << 16) | setbits);
368 
369     return FSP_SUCCESS;
370 }
371 
372 /*******************************************************************************************************************//**
373  * Sets a pin's output either high or low. Implements @ref ioport_api_t::pinWrite.
374  *
375  * @retval FSP_SUCCESS                  Pin written to
376  * @retval FSP_ERR_INVALID_ARGUMENT     The pin and/or level not valid
377  * @retval FSP_ERR_NOT_OPEN             The module has not been opene
378  * @retval FSP_ERR_ASSERTION            NULL pointerd
379  *
380  * @note This function is re-entrant for different pins. This function makes use of the PCNTR3 register to atomically
381  * modify the level on the specified pin on a port.
382  **********************************************************************************************************************/
R_IOPORT_PinWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t level)383 fsp_err_t R_IOPORT_PinWrite (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t level)
384 {
385 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
386     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
387     FSP_ASSERT(NULL != p_instance_ctrl);
388     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
389     FSP_ERROR_RETURN(level <= BSP_IO_LEVEL_HIGH, FSP_ERR_INVALID_ARGUMENT);
390 #else
391     FSP_PARAMETER_NOT_USED(p_ctrl);
392 #endif
393 
394     ioport_size_t setbits = 0U;
395     ioport_size_t clrbits = 0U;
396     bsp_io_port_t port    = (bsp_io_port_t) (IOPORT_PRV_PORT_BITS & (ioport_size_t) pin);
397 
398     ioport_size_t shift    = IOPORT_PRV_PIN_BITS & (ioport_size_t) pin;
399     ioport_size_t pin_mask = (ioport_size_t) (1U << shift);
400 
401     if (BSP_IO_LEVEL_LOW == level)
402     {
403         clrbits = pin_mask;
404     }
405     else
406     {
407         setbits = pin_mask;
408     }
409 
410     /* PCNTR register is updated instead of using PFS as access is atomic and PFS requires seperate enable/disable
411      * using PWPR register */
412 
413     /* Get the port address */
414     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
415 
416     /* PCNTR3 register: lower word = set data, upper word = reset_data */
417     p_ioport_regs->PCNTR3 = (uint32_t) (((uint32_t) clrbits << 16) | setbits);
418 
419     return FSP_SUCCESS;
420 }
421 
422 /*******************************************************************************************************************//**
423  * Sets the direction of individual pins on a port. Implements @ref ioport_api_t::portDirectionSet().
424  *
425  * Multiple pins on a port can be set to inputs or outputs at once.
426  * Each bit in the mask parameter corresponds to a pin on the port. For example, bit 7 corresponds to
427  * pin 7, bit 6 to pin 6, and so on. If a bit is set to 1 then the corresponding pin will be changed to
428  * an input or an output as specified by the direction values. If a mask bit is set to 0 then the direction of
429  * the pin will not be changed.
430  *
431  * @retval FSP_SUCCESS                 Port direction updated
432  * @retval FSP_ERR_INVALID_ARGUMENT    The port and/or mask not valid
433  * @retval FSP_ERR_NOT_OPEN            The module has not been opened
434  * @retval FSP_ERR_ASSERTION           NULL pointer
435  *
436  * @note This function is re-entrant for different ports.
437  **********************************************************************************************************************/
R_IOPORT_PortDirectionSet(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t direction_values,ioport_size_t mask)438 fsp_err_t R_IOPORT_PortDirectionSet (ioport_ctrl_t * const p_ctrl,
439                                      bsp_io_port_t         port,
440                                      ioport_size_t         direction_values,
441                                      ioport_size_t         mask)
442 {
443     uint32_t orig_value;
444     uint32_t set_bits;
445     uint32_t clr_bits;
446     uint32_t write_value;
447 
448 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
449     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
450     FSP_ASSERT(NULL != p_instance_ctrl);
451     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
452     FSP_ERROR_RETURN(mask > (ioport_size_t) 0, FSP_ERR_INVALID_ARGUMENT);
453 #else
454     FSP_PARAMETER_NOT_USED(p_ctrl);
455 #endif
456 
457     /* Get the port address */
458     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
459 
460     /* Read current value of PCNTR1 register for the specified port */
461     orig_value = p_ioport_regs->PCNTR1;
462 
463     /* High bits */
464     set_bits = direction_values & mask;
465 
466     /*  Low bits */
467     /* Cast to ensure size */
468     clr_bits = (uint32_t) ((~direction_values) & mask);
469 
470     /* New value to write to port direction register */
471     write_value  = orig_value;
472     write_value |= set_bits;
473 
474     /* Clear bits as needed */
475     write_value &= ~clr_bits;
476 
477     p_ioport_regs->PCNTR1 = write_value;
478 
479     return FSP_SUCCESS;
480 }
481 
482 /*******************************************************************************************************************//**
483  * Reads the value of the event input data. Implements @ref ioport_api_t::portEventInputRead().
484  *
485  * The event input data for the port will be read. Each bit in the returned value corresponds to a pin on the port.
486  * For example, bit 7 corresponds to pin 7, bit 6 to pin 6, and so on.
487  *
488  * The port event data is captured in response to a trigger from the ELC. This function enables this data to be read.
489  * Using the event system allows the captured data to be stored when it occurs and then read back at a later time.
490  *
491  * @retval FSP_SUCCESS              Port read
492  * @retval FSP_ERR_INVALID_ARGUMENT Port not a valid ELC port
493  * @retval FSP_ERR_ASSERTION        NULL pointer
494  * @retval FSP_ERR_NOT_OPEN         The module has not been opened
495  *
496  * @note This function is re-entrant for different ports.
497  *
498  **********************************************************************************************************************/
R_IOPORT_PortEventInputRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t * p_event_data)499 fsp_err_t R_IOPORT_PortEventInputRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_t port, ioport_size_t * p_event_data)
500 {
501 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
502     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
503     FSP_ASSERT(NULL != p_instance_ctrl);
504     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
505     FSP_ASSERT(NULL != p_event_data);
506     uint32_t port_number = port >> IOPORT_PRV_PORT_OFFSET;
507     FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
508 #else
509     FSP_PARAMETER_NOT_USED(p_ctrl);
510 #endif
511 
512     /* Get the port address */
513     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS(port >> IOPORT_PRV_PORT_OFFSET & IOPORT_PRV_8BIT_MASK);
514 
515     /* Read current value of EIDR value from PCNTR2 register for the specified port */
516     *p_event_data = p_ioport_regs->PCNTR2_b.EIDR;
517 
518     return FSP_SUCCESS;
519 }
520 
521 /*******************************************************************************************************************//**
522  * Reads the value of the event input data of a specific pin. Implements @ref ioport_api_t::pinEventInputRead.
523  *
524  * The pin event data is captured in response to a trigger from the ELC. This function enables this data to be read.
525  * Using the event system allows the captured data to be stored when it occurs and then read back at a later time.
526  *
527  * @retval FSP_SUCCESS                  Pin read
528  * @retval FSP_ERR_ASSERTION            NULL pointer
529  * @retval FSP_ERR_NOT_OPEN             The module has not been opened
530  * @retval FSP_ERR_INVALID_ARGUMENT     Port is not valid ELC PORT.
531  *
532  * @note This function is re-entrant.
533  *
534  **********************************************************************************************************************/
R_IOPORT_PinEventInputRead(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t * p_pin_event)535 fsp_err_t R_IOPORT_PinEventInputRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t * p_pin_event)
536 {
537     ioport_size_t portvalue;
538     ioport_size_t mask;
539 
540 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
541     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
542     FSP_ASSERT(NULL != p_instance_ctrl);
543     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
544     FSP_ASSERT(NULL != p_pin_event);
545     uint32_t port_number = pin >> IOPORT_PRV_PORT_OFFSET;
546     FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
547 #else
548     FSP_PARAMETER_NOT_USED(p_ctrl);
549 #endif
550 
551     /* Get the port address */
552     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((pin >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
553 
554     /* Read current value of EIDR value from PCNTR2 register for the specified port */
555     portvalue = p_ioport_regs->PCNTR2_b.EIDR;
556     mask      = (ioport_size_t) (1U << (IOPORT_PRV_PIN_BITS & (bsp_io_port_t) pin));
557 
558     if ((portvalue & mask) == mask)
559     {
560         *p_pin_event = BSP_IO_LEVEL_HIGH;
561     }
562     else
563     {
564         *p_pin_event = BSP_IO_LEVEL_LOW;
565     }
566 
567     return FSP_SUCCESS;
568 }
569 
570 /*******************************************************************************************************************//**
571  * This function writes the set and reset event output data for a port. Implements
572  * @ref ioport_api_t::portEventOutputWrite.
573  *
574  * Using the event system enables a port state to be stored by this function in advance of being output on the port.
575  * The output to the port will occur when the ELC event occurs.
576  *
577  * The input value will be written to the specified port when an ELC event configured for that port occurs.
578  * Each bit in the value parameter corresponds to a bit on the port. For example, bit 7 corresponds to pin 7,
579  * bit 6 to pin 6, and so on. Each bit in the mask parameter corresponds to a pin on the port.
580  *
581  * @retval FSP_SUCCESS                Port event data written
582  * @retval FSP_ERR_INVALID_ARGUMENT   Port or Mask not valid
583  * @retval FSP_ERR_NOT_OPEN           The module has not been opened
584  * @retval FSP_ERR_ASSERTION          NULL pointer
585  *
586  * @note This function is re-entrant for different ports.
587  **********************************************************************************************************************/
R_IOPORT_PortEventOutputWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_t port,ioport_size_t event_data,ioport_size_t mask_value)588 fsp_err_t R_IOPORT_PortEventOutputWrite (ioport_ctrl_t * const p_ctrl,
589                                          bsp_io_port_t         port,
590                                          ioport_size_t         event_data,
591                                          ioport_size_t         mask_value)
592 {
593     ioport_size_t set_bits;
594     ioport_size_t reset_bits;
595 
596 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
597     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
598     FSP_ASSERT(NULL != p_instance_ctrl);
599     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
600     FSP_ERROR_RETURN(mask_value > (ioport_size_t) 0, FSP_ERR_INVALID_ARGUMENT);
601     uint32_t port_number = port >> IOPORT_PRV_PORT_OFFSET;
602     FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
603 #else
604     FSP_PARAMETER_NOT_USED(p_ctrl);
605 #endif
606 
607     set_bits = event_data & mask_value;
608 
609     /* Cast to ensure size */
610     reset_bits = (ioport_size_t) ((~event_data) & mask_value);
611 
612     /* Get the port address */
613     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
614 
615     /* PCNTR4 register: lower word = set data, upper word = reset_data */
616     p_ioport_regs->PCNTR4 = (uint32_t) (((uint32_t) reset_bits << 16) | set_bits);
617 
618     return FSP_SUCCESS;
619 }
620 
621 /**********************************************************************************************************************//**
622  * This function writes the event output data value to a pin. Implements @ref ioport_api_t::pinEventOutputWrite.
623  *
624  * Using the event system enables a pin state to be stored by this function in advance of being output on the pin.
625  * The output to the pin will occur when the ELC event occurs.
626  *
627  * @retval FSP_SUCCESS               Pin event data written
628  * @retval FSP_ERR_INVALID_ARGUMENT  Port or Pin or value not valid
629  * @retval FSP_ERR_NOT_OPEN          The module has not been opened
630  * @retval FSP_ERR_ASSERTION         NULL pointer
631  *
632  * @note This function is re-entrant for different ports.
633  *
634  **********************************************************************************************************************/
R_IOPORT_PinEventOutputWrite(ioport_ctrl_t * const p_ctrl,bsp_io_port_pin_t pin,bsp_io_level_t pin_value)635 fsp_err_t R_IOPORT_PinEventOutputWrite (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t pin_value)
636 {
637 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
638     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
639     FSP_ASSERT(NULL != p_instance_ctrl);
640     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
641     FSP_ERROR_RETURN((pin_value == BSP_IO_LEVEL_HIGH) || (pin_value == BSP_IO_LEVEL_LOW), FSP_ERR_INVALID_ARGUMENT);
642     uint32_t port_number = pin >> IOPORT_PRV_PORT_OFFSET;
643     FSP_ERROR_RETURN((BSP_FEATURE_IOPORT_ELC_PORTS & (1 << port_number)), FSP_ERR_INVALID_ARGUMENT);
644 #else
645     FSP_PARAMETER_NOT_USED(p_ctrl);
646 #endif
647 
648     ioport_size_t set_bits;
649     ioport_size_t reset_bits;
650     bsp_io_port_t port;
651     uint16_t      pin_to_port;
652 
653     /* Cast to ensure correct conversion of parameter. */
654     pin_to_port = (uint16_t) pin;
655     pin_to_port = pin_to_port & (uint16_t) IOPORT_PRV_PORT_BITS;
656     port        = (bsp_io_port_t) pin_to_port;
657     set_bits    = (ioport_size_t) 0;
658     reset_bits  = (ioport_size_t) 0;
659 
660     if (BSP_IO_LEVEL_HIGH == pin_value)
661     {
662         /* Cast to ensure size */
663         set_bits = (ioport_size_t) (1U << ((ioport_size_t) pin & IOPORT_PRV_PIN_BITS));
664     }
665     else
666     {
667         /* Cast to ensure size */
668         reset_bits = (ioport_size_t) (1U << ((ioport_size_t) pin & IOPORT_PRV_PIN_BITS));
669     }
670 
671     r_ioport_hw_pin_event_output_data_write(port, set_bits, reset_bits, pin_value);
672 
673     return FSP_SUCCESS;
674 }
675 
676 /***********************************************************************************************************************
677  * DEPRECATED Configures Ethernet channel PHY mode. Implements @ref ioport_api_t::pinEthernetModeCfg.
678  *
679  * @retval FSP_SUCCESS              Ethernet PHY mode set
680  * @retval FSP_ERR_INVALID_ARGUMENT Channel or mode not valid
681  * @retval FSP_ERR_UNSUPPORTED      Ethernet configuration not supported on this device.
682  * @retval FSP_ERR_NOT_OPEN         The module has not been opened
683  * @retval FSP_ERR_ASSERTION        NULL pointer
684  *
685  * @note This function is not re-entrant.
686  **********************************************************************************************************************/
R_IOPORT_EthernetModeCfg(ioport_ctrl_t * const p_ctrl,ioport_ethernet_channel_t channel,ioport_ethernet_mode_t mode)687 fsp_err_t R_IOPORT_EthernetModeCfg (ioport_ctrl_t * const     p_ctrl,
688                                     ioport_ethernet_channel_t channel,
689                                     ioport_ethernet_mode_t    mode)
690 {
691     FSP_ERROR_RETURN(1U == BSP_FEATURE_IOPORT_HAS_ETHERNET, FSP_ERR_UNSUPPORTED);
692 
693 #if (1 == IOPORT_CFG_PARAM_CHECKING_ENABLE)
694     ioport_instance_ctrl_t * p_instance_ctrl = (ioport_instance_ctrl_t *) p_ctrl;
695     FSP_ASSERT(NULL != p_instance_ctrl);
696     FSP_ERROR_RETURN(IOPORT_OPEN == p_instance_ctrl->open, FSP_ERR_NOT_OPEN);
697     FSP_ERROR_RETURN(channel < IOPORT_ETHERNET_CHANNEL_END, FSP_ERR_INVALID_ARGUMENT);
698     FSP_ERROR_RETURN(mode < IOPORT_ETHERNET_MODE_END, FSP_ERR_INVALID_ARGUMENT);
699 #else
700     FSP_PARAMETER_NOT_USED(p_ctrl);
701     FSP_PARAMETER_NOT_USED(channel);
702 #endif
703 
704     R_PMISC->PFENET = (uint8_t) mode;
705 
706     return FSP_SUCCESS;
707 }
708 
709 /*******************************************************************************************************************//**
710  * @} (end addtogroup IOPORT)
711  **********************************************************************************************************************/
712 
713 /***********************************************************************************************************************
714  * Private Functions
715  **********************************************************************************************************************/
716 
717 /*******************************************************************************************************************//**
718  * Configures pins.
719  *
720  * @param[in]    p_cfg          Pin configuration data
721  **********************************************************************************************************************/
r_ioport_pins_config(const ioport_cfg_t * p_cfg)722 void r_ioport_pins_config (const ioport_cfg_t * p_cfg)
723 {
724 #if BSP_MCU_VBATT_SUPPORT
725 
726     /* Handle any VBATT domain pin configuration. */
727     bsp_vbatt_init(p_cfg);
728 #endif
729 
730     uint16_t       pin_count;
731     ioport_cfg_t * p_pin_data;
732 
733     p_pin_data = (ioport_cfg_t *) p_cfg;
734 
735     R_BSP_PinAccessEnable();           // Protect PWPR from re-entrancy
736 
737     for (pin_count = 0U; pin_count < p_pin_data->number_of_pins; pin_count++)
738     {
739         r_ioport_pfs_write(p_pin_data->p_pin_cfg_data[pin_count].pin, p_pin_data->p_pin_cfg_data[pin_count].pin_cfg);
740     }
741 
742     R_BSP_PinAccessDisable();
743 }
744 
745 /*******************************************************************************************************************//**
746  * Writes the set and clear values on a pin of the port when an ELC event occurs. This allows accurate timing of
747  * pin output level.
748  *
749  * @param[in]    port           Port to read event data
750  * @param[in]    set_value      Bit in the port to set high (1 = that bit will be set high)
751  * @param[in]    reset_value    Bit in the port to clear low (1 = that bit will be cleared low)
752  * @param[in]    pin_level      Event data for pin
753  **********************************************************************************************************************/
r_ioport_hw_pin_event_output_data_write(bsp_io_port_t port,ioport_size_t set_value,ioport_size_t reset_value,bsp_io_level_t pin_level)754 static void r_ioport_hw_pin_event_output_data_write (bsp_io_port_t  port,
755                                                      ioport_size_t  set_value,
756                                                      ioport_size_t  reset_value,
757                                                      bsp_io_level_t pin_level)
758 {
759     uint32_t port_value = 0;
760 
761     /* Get the port address */
762     R_PORT0_Type * p_ioport_regs = IOPORT_PRV_PORT_ADDRESS((port >> IOPORT_PRV_PORT_OFFSET) & IOPORT_PRV_8BIT_MASK);
763 
764     /* Read current value of PCNTR4 register */
765     port_value = p_ioport_regs->PCNTR4;
766 
767     if (BSP_IO_LEVEL_HIGH == pin_level)
768     {
769         /* set value contains the bit to be set high (bit mask) */
770         port_value |= (uint32_t) (set_value);
771 
772         /* reset value contains the mask to clear the corresponding bit in EOSR because both EOSR and EORR
773          *  bit of a particular pin should not be high at the same time */
774         port_value &= (((uint32_t) reset_value << 16) | IOPORT_PRV_16BIT_MASK);
775     }
776     else
777     {
778         /* reset_value contains the bit to be cleared low */
779         port_value |= (uint32_t) reset_value << 16;
780 
781         /* set value contains the mask to clear the corresponding bit in EOSR because both EOSR and EORR bit of a
782          *  particular pin should not be high at the same time */
783         port_value &= (uint32_t) ((set_value | IOPORT_PRV_UPPER_16BIT_MASK));
784     }
785 
786     p_ioport_regs->PCNTR4 = port_value;
787 }
788 
789 /*******************************************************************************************************************//**
790  * Writes to the specified pin's PFS register
791  *
792  * @param[in]    pin        Pin to write PFS data for
793  * @param[in]    value      Value to be written to the PFS register
794  *
795  **********************************************************************************************************************/
r_ioport_pfs_write(bsp_io_port_pin_t pin,uint32_t value)796 static void r_ioport_pfs_write (bsp_io_port_pin_t pin, uint32_t value)
797 {
798     /* PMR bits should be cleared before specifying PSEL. Reference section "20.7 Notes on the PmnPFS Register Setting"
799      * in the RA6M3 manual R01UH0886EJ0100. */
800     if ((value & IOPORT_PRV_PERIPHERAL_FUNCTION) > 0)
801     {
802         /* Clear PMR */
803         R_PFS->PORT[pin >> IOPORT_PRV_PORT_OFFSET].PIN[pin & BSP_IO_PRV_8BIT_MASK].PmnPFS_b.PMR = 0;
804 
805         /* New config with PMR = 0 */
806         R_PFS->PORT[pin >> IOPORT_PRV_PORT_OFFSET].PIN[pin &
807                                                        BSP_IO_PRV_8BIT_MASK].PmnPFS =
808             (value & ~((uint32_t) IOPORT_PRV_PERIPHERAL_FUNCTION));
809     }
810 
811     /* Write configuration */
812     R_PFS->PORT[pin >> IOPORT_PRV_PORT_OFFSET].PIN[pin & BSP_IO_PRV_8BIT_MASK].PmnPFS = value;
813 }
814 
815 #if BSP_MCU_VBATT_SUPPORT
816 
817 /*******************************************************************************************************************//**
818  * @brief Initializes VBTICTLR register based on pin configuration.
819  *
820  * The VBTICTLR register may need to be modified based on the project's pin configuration. There is a set of pins that
821  * needs to be checked. If one of these pins is found in the pin configuration table then it will be tested to see if
822  * the appropriate VBTICTLR bit needs to be set or cleared. If one of the pins that is being searched for is not found
823  * then the accompanying VBTICTLR bit is left as-is.
824  **********************************************************************************************************************/
bsp_vbatt_init(ioport_cfg_t const * const p_pin_cfg)825 static void bsp_vbatt_init (ioport_cfg_t const * const p_pin_cfg)
826 {
827     uint32_t pin_index;
828     uint32_t vbatt_index;
829     uint8_t  local_vbtictlr_set;       ///< Will hold bits to set in VBTICTLR
830     uint8_t  local_vbtictlr_clear;     ///< Will hold bits to clear in VBTICTLR
831 
832     /* Make no changes unless required. */
833     local_vbtictlr_set   = 0U;
834     local_vbtictlr_clear = 0U;
835 
836     /* Must loop over all pins as pin configuration table is unordered. */
837     for (pin_index = 0U; pin_index < p_pin_cfg->number_of_pins; pin_index++)
838     {
839         /* Loop over VBATT input pins. */
840         for (vbatt_index = 0U;
841              vbatt_index < (sizeof(g_vbatt_pins_input) / sizeof(g_vbatt_pins_input[0]));
842              vbatt_index++)
843         {
844             if (p_pin_cfg->p_pin_cfg_data[pin_index].pin == g_vbatt_pins_input[vbatt_index])
845             {
846                 /* Get PSEL value for pin. */
847                 uint32_t pfs_psel_value = p_pin_cfg->p_pin_cfg_data[pin_index].pin_cfg & BSP_PRV_PFS_PSEL_MASK;
848 
849                 /* Check if pin is being used for RTC or AGT use. */
850                 if ((IOPORT_PERIPHERAL_AGT == pfs_psel_value) || (IOPORT_PERIPHERAL_CLKOUT_COMP_RTC == pfs_psel_value))
851                 {
852                     /* Bit should be set to 1. */
853                     local_vbtictlr_set |= (uint8_t) (1U << vbatt_index);
854                 }
855                 else
856                 {
857                     /* Bit should be cleared to 0. */
858                     local_vbtictlr_clear |= (uint8_t) (1U << vbatt_index);
859                 }
860             }
861         }
862     }
863 
864     /* Disable write protection on VBTICTLR. */
865     R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_OM_LPC_BATT);
866 
867     /* Read value, set and clear bits as needed and write back. */
868     uint8_t local_vbtictlr = R_SYSTEM->VBTICTLR;
869     local_vbtictlr |= local_vbtictlr_set;              ///< Set appropriate bits
870     local_vbtictlr &= (uint8_t) ~local_vbtictlr_clear; ///< Clear appropriate bits
871 
872     R_SYSTEM->VBTICTLR = local_vbtictlr;
873 
874     /* Enable write protection on VBTICTLR. */
875     R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_OM_LPC_BATT);
876 }
877 
878 #endif
879