1 /*
2  * Copyright 2017-2020 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_kbi.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.kbi"
17 #endif
18 
19 /*******************************************************************************
20  * Prototypes
21  ******************************************************************************/
22 
23 /*******************************************************************************
24  * Variables
25  ******************************************************************************/
26 
27 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
28 /*! @brief Pointers to SEMC clocks for each instance. */
29 static const clock_ip_name_t s_kbiClock[FSL_FEATURE_SOC_KBI_COUNT] = KBI_CLOCKS;
30 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
31 
32 /*! @brief Pointers to SEMC bases for each instance. */
33 static KBI_Type *const s_kbiBases[] = KBI_BASE_PTRS;
34 
35 /*! @brief Pointers to Kbi IRQ number for each instance. */
36 static const IRQn_Type s_kbiIrqs[] = KBI_IRQS;
37 /*******************************************************************************
38  * Code
39  ******************************************************************************/
KBI_GetInstance(KBI_Type * base)40 static uint32_t KBI_GetInstance(KBI_Type *base)
41 {
42     uint32_t instance;
43 
44     /* Find the instance index from base address mappings. */
45     for (instance = 0; instance < ARRAY_SIZE(s_kbiBases); instance++)
46     {
47         if (s_kbiBases[instance] == base)
48         {
49             break;
50         }
51     }
52 
53     assert(instance < ARRAY_SIZE(s_kbiBases));
54 
55     return instance;
56 }
57 
58 /*!
59  * brief KBI initialize.
60  * This function ungates the KBI clock and initializes KBI.
61  * This function must be called before calling any other KBI driver functions.
62  *
63  * param base KBI peripheral base address.
64  * param configure The KBI configuration structure pointer.
65  */
KBI_Init(KBI_Type * base,kbi_config_t * configure)66 void KBI_Init(KBI_Type *base, kbi_config_t *configure)
67 {
68     assert(configure);
69 
70     kbi_reg_t scReg;
71 
72     uint32_t instance = KBI_GetInstance(base);
73 
74 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
75     /* Un-gate sdram controller clock. */
76     CLOCK_EnableClock(s_kbiClock[KBI_GetInstance(base)]);
77 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
78 
79     /* Mask keyboard interrupts first to prevent false interrupt request during initialization */
80     base->SC = 0;
81     /* Setting KBI polarity. */
82     base->ES = KBI_ES_KBEDG(configure->pinsEdge);
83     /* Enable KBI pins. */
84     base->PE = KBI_PE_KBIPE(configure->pinsEnabled);
85     /* Clear any false interrupts. */
86     scReg = KBI_SC_KBACK_MASK;
87 #if defined(FSL_FEATURE_KBI_HAS_SOURCE_PIN) && FSL_FEATURE_KBI_HAS_SOURCE_PIN
88     /* Reset kbi sp register. */
89     scReg |= KBI_SC_RSTKBSP_MASK | KBI_SC_KBSPEN_MASK;
90 #endif
91     base->SC = scReg;
92 
93     /* Set KBI enable interrupts and KBI detect mode. */
94     scReg    = base->SC;
95     base->SC = ((kbi_reg_t)configure->mode & KBI_SC_KBMOD_MASK) | KBI_SC_KBIE_MASK | scReg;
96     /* Enable NVIC interrupt. */
97     (void)EnableIRQ(s_kbiIrqs[instance]);
98 }
99 
100 /*!
101  * brief Deinitializes the KBI module and gates the clock.
102  * This function gates the KBI clock. As a result, the KBI
103  * module doesn't work after calling this function.
104  *
105  * param base KBI peripheral base address.
106  */
KBI_Deinit(KBI_Type * base)107 void KBI_Deinit(KBI_Type *base)
108 {
109     kbi_reg_t scReg = KBI_SC_KBACK_MASK;
110 
111 #if defined(FSL_FEATURE_KBI_HAS_SOURCE_PIN) && FSL_FEATURE_KBI_HAS_SOURCE_PIN
112     /* Reset kbi sp register. */
113     scReg |= KBI_SC_RSTKBSP_MASK;
114 #endif
115     /* Disable interrupts. */
116     base->SC = scReg;
117     base->PE = 0;
118 
119 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
120     /* Disable Kbi clock. */
121     CLOCK_DisableClock(s_kbiClock[KBI_GetInstance(base)]);
122 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
123 }
124