1 /*--------------------------------------------------------------------
\r
2 Copyright(c) 2015 Intel Corporation. All rights reserved.
\r
4 Redistribution and use in source and binary forms, with or without
\r
5 modification, are permitted provided that the following conditions
\r
8 * Redistributions of source code must retain the above copyright
\r
9 notice, this list of conditions and the following disclaimer.
\r
10 * Redistributions in binary form must reproduce the above copyright
\r
11 notice, this list of conditions and the following disclaimer in
\r
12 the documentation and/or other materials provided with the
\r
14 * Neither the name of Intel Corporation nor the names of its
\r
15 contributors may be used to endorse or promote products derived
\r
16 from this software without specific prior written permission.
\r
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\r
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
\r
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
\r
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
\r
22 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\r
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
24 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
\r
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
\r
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
29 --------------------------------------------------------------------*/
\r
31 /*-----------------------------------------------------------------------
\r
32 * Any required includes
\r
33 *------------------------------------------------------------------------
\r
35 #include "GPIO_I2C.h"
\r
37 /*-----------------------------------------------------------------------
\r
38 * Any required local definitions
\r
39 *------------------------------------------------------------------------
\r
42 #define NULL (void *)0
\r
44 /*-----------------------------------------------------------------------
\r
45 * Function prototypes
\r
46 *------------------------------------------------------------------------
\r
48 static void vGalileoRouteLEDPins(void);
\r
50 /*-----------------------------------------------------------------------
\r
52 *------------------------------------------------------------------------
\r
54 static struct BOARD_GPIO_CONTROLLER_CONFIG GpioConfig;
\r
55 static struct BOARD_LEGACY_GPIO_CONFIG LegacyGpioConfig;
\r
57 static uint32_t LegacyGpioBase = 0;
\r
58 static uint32_t IohGpioBase = 0;
\r
59 static uint32_t I2CGpioBase = 0;
\r
61 static uint32_t bGalileoGPIOInitialized = FALSE;
\r
63 /*-----------------------------------------------------------------------
\r
64 * GPIO support functions
\r
65 *------------------------------------------------------------------------
\r
67 static uint32_t pciIOread32(uint32_t addr)
\r
69 outl(IO_PCI_ADDRESS_PORT, addr);
\r
70 uint32_t data = inl(IO_PCI_DATA_PORT);
\r
73 /*-----------------------------------------------------------*/
\r
75 static void pciIOwrite32(uint32_t addr, uint32_t IO_data)
\r
77 outl(IO_PCI_ADDRESS_PORT, addr);
\r
78 outl(IO_PCI_DATA_PORT, IO_data );
\r
80 /*-----------------------------------------------------------*/
\r
82 static int32_t uiGalileoGPIORead(uint32_t Offset, uint8_t UseMask)
\r
84 // Keep reserved bits [31:8]
\r
86 return *((volatile uint32_t *) (uintn_t)(IohGpioBase + Offset)) & 0xFFFFFF00;
\r
88 return *((volatile uint32_t *) (uintn_t)(IohGpioBase + Offset));
\r
90 /*-----------------------------------------------------------*/
\r
92 static void vGalileoGPIOWrite(uint32_t Offset, uint32_t WriteData32)
\r
94 uint32_t Data32 = uiGalileoGPIORead(Offset, true);
\r
95 if (Offset != GPIO_INTSTATUS)
\r
96 Data32 |= (WriteData32 & 0x000FFFFF);
\r
97 *((volatile uint32_t *) (uintn_t)(IohGpioBase + Offset)) = Data32;
\r
99 /*-----------------------------------------------------------*/
\r
101 static int32_t uiGalileoLegacyGPIOPCIRead(uint32_t addr, uint32_t Mask)
\r
103 // Keep reserved bits (Mask Varies)
\r
104 return pciIOread32(addr) & Mask;
\r
106 /*-----------------------------------------------------------*/
\r
108 static void vGalileoLegacyGPIOPCIWrite(uint32_t addr, uint32_t WriteData32, uint32_t Mask)
\r
110 uint32_t Data32 = uiGalileoLegacyGPIOPCIRead(addr, Mask);
\r
111 Data32 |= (WriteData32 & ~Mask);
\r
112 pciIOwrite32(addr, Data32);
\r
114 /*-----------------------------------------------------------*/
\r
116 static int32_t uiGalileoLegacyGPIOPortRead(uint32_t addr, uint32_t Mask)
\r
118 // Keep reserved bits (Mask Varies)
\r
119 return inl(addr) & Mask;
\r
121 /*-----------------------------------------------------------*/
\r
123 static void vGalileoLegacyGPIOPortRMW(uint32_t addr, uint32_t WriteData32, uint32_t Mask)
\r
125 uint32_t Data32 = uiGalileoLegacyGPIOPortRead(addr, Mask);
\r
126 Data32 |= (WriteData32 & ~Mask);
\r
127 outl(addr, Data32);
\r
129 /*-----------------------------------------------------------*/
\r
131 /*-----------------------------------------------------------------------
\r
132 * Controller initialization functions
\r
133 *------------------------------------------------------------------------
\r
135 void vGalileoInitializeLegacyGPIO(void)
\r
137 // Read Register Default Values into Structure
\r
138 struct BOARD_LEGACY_GPIO_CONFIG LegacyGPIOConfigTable[] =
\r
139 { PLATFORM_LEGACY_GPIO_CONFIG_DEFINITION };
\r
141 // BDF for Legacy GPIO (from the Quark Datasheet)
\r
142 uint8_t Bus = LEGACY_GPIO_BUS_NUMBER;
\r
143 uint8_t Device = LEGACY_GPIO_DEVICE_NUMBER;
\r
144 uint8_t Func = LEGACY_GPIO_FUNCTION_NUMBER;
\r
146 // Get PCI Configuration IO Address
\r
148 uiGalileoLegacyGPIOPCIRead(IO_PCI_ADDRESS(Bus, Device, Func, R_QNC_LPC_GBA_BASE), B_QNC_LPC_GPA_BASE_MASK);
\r
150 // Quiet compiler by doing a legacy GPIO write
\r
151 uint32_t PciCmd = uiGalileoLegacyGPIOPCIRead((LegacyGpioBase + PCI_REG_PCICMD), 0xFFFFFFFF);
\r
152 vGalileoLegacyGPIOPCIWrite((LegacyGpioBase + PCI_REG_PCICMD), (PciCmd | 0x7), 0xFFFFFFFF);
\r
155 LegacyGpioConfig = LegacyGPIOConfigTable[0];
\r
158 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGEN_CORE_WELL, LegacyGpioConfig.CoreWellEnable, 0xFFFFFFFC);
\r
159 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGIO_CORE_WELL, LegacyGpioConfig.CoreWellIoSelect, 0xFFFFFFFC);
\r
160 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGLVL_CORE_WELL, LegacyGpioConfig.CoreWellLvlForInputOrOutput, 0xFFFFFFFC);
\r
161 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGTPE_CORE_WELL, LegacyGpioConfig.CoreWellTriggerPositiveEdge, 0xFFFFFFFC);
\r
162 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGTNE_CORE_WELL, LegacyGpioConfig.CoreWellTriggerNegativeEdge, 0xFFFFFFFC);
\r
163 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGGPE_CORE_WELL, LegacyGpioConfig.ResumeWellGPEEnable, 0xFFFFFFFC);
\r
164 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGSMI_CORE_WELL, LegacyGpioConfig.ResumeWellSMIEnable, 0xFFFFFFFC);
\r
165 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CGEN_CORE_WELL, LegacyGpioConfig.CoreWellTriggerStatus, 0xFFFFFFFC);
\r
166 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_CNMIEN_CORE_WELL, LegacyGpioConfig.ResumeWellNMIEnable, 0xFFFFFFFC);
\r
167 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGEN_RESUME_WELL, LegacyGpioConfig.ResumeWellEnable, 0xFFFFFFC0);
\r
168 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGIO_RESUME_WELL, LegacyGpioConfig.ResumeWellIoSelect, 0xFFFFFFC0);
\r
169 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGLVL_RESUME_WELL, LegacyGpioConfig.ResumeWellLvlForInputOrOutput, 0xFFFFFFC0);
\r
170 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGTPE_RESUME_WELL, LegacyGpioConfig.ResumeWellTriggerPositiveEdge, 0xFFFFFFC0);
\r
171 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGTNE_RESUME_WELL, LegacyGpioConfig.ResumeWellTriggerNegativeEdge, 0xFFFFFFC0);
\r
172 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGGPE_RESUME_WELL, LegacyGpioConfig.CoreWellGPEEnable, 0xFFFFFFC0);
\r
173 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGSMI_RESUME_WELL, LegacyGpioConfig.CoreWellSMIEnable, 0xFFFFFFC0);
\r
174 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RGTS_RESUME_WELL, LegacyGpioConfig.ResumeWellTriggerStatus, 0xFFFFFFC0);
\r
175 vGalileoLegacyGPIOPortRMW(LegacyGpioBase + R_QNC_GPIO_RNMIEN_RESUME_WELL, LegacyGpioConfig.CoreWellNMIEnable, 0xFFFFFFC0);
\r
177 /*-----------------------------------------------------------*/
\r
179 void vGalileoInitializeGpioController(void)
\r
181 // Read Register Default Values into Structure
\r
182 struct BOARD_GPIO_CONTROLLER_CONFIG BoardGpioControllerConfigTable[] =
\r
183 { PLATFORM_GPIO_CONTROLLER_CONFIG_DEFINITION };
\r
185 // BDF for I2C Controller (from the Quark Datasheet)
\r
186 uint8_t Bus = IOH_I2C_GPIO_BUS_NUMBER;
\r
187 uint8_t Device = IOH_I2C_GPIO_DEVICE_NUMBER;
\r
188 uint8_t Func = IOH_I2C_GPIO_FUNCTION_NUMBER;
\r
190 // Get PCI Configuration MMIO Address
\r
191 uint32_t gpio_controller_base = MMIO_PCI_ADDRESS(Bus, Device, Func, 0);
\r
193 // Get Vendor and Device IDs
\r
194 uint16_t PciVid = mem_read(gpio_controller_base, PCI_REG_VID, 2);
\r
195 uint16_t PciDid = mem_read(gpio_controller_base, PCI_REG_DID, 2);
\r
197 // Check for valid VID and DID
\r
198 if((PciVid == V_IOH_I2C_GPIO_VENDOR_ID) && (PciDid == V_IOH_I2C_GPIO_DEVICE_ID))
\r
201 uint8_t PciCmd = mem_read(gpio_controller_base, PCI_REG_PCICMD, 1);
\r
202 // Enable Bus Master(Bit2), MMIO Space(Bit1) & I/O Space(Bit0)
\r
203 mem_write(gpio_controller_base, PCI_REG_PCICMD, 1, (PciCmd | 0x7));
\r
205 IohGpioBase = mem_read(gpio_controller_base, R_IOH_GPIO_MEMBAR, 4);
\r
207 GpioConfig = BoardGpioControllerConfigTable[0];
\r
208 // IEN- Interrupt Enable Register
\r
209 vGalileoGPIOWrite(GPIO_INTEN, GpioConfig.IntEn);
\r
210 // ISTATUS- Interrupt Status Register
\r
211 vGalileoGPIOWrite(GPIO_INTSTATUS, 0);
\r
212 // GPIO SWPORTA Data Register - GPIO_SWPORTA_DR
\r
213 vGalileoGPIOWrite(GPIO_SWPORTA_DR, GpioConfig.PortADR);
\r
214 // GPIO SWPORTA Data Direction Register - GPIO_SWPORTA_DDR
\r
215 vGalileoGPIOWrite(GPIO_SWPORTA_DDR, GpioConfig.PortADir);
\r
216 // Interrupt Mask Register - GPIO_INTMASK
\r
217 vGalileoGPIOWrite(GPIO_INTMASK, GpioConfig.IntMask);
\r
218 // Interrupt Level Type Register - GPIO_INTTYPE_LEVEL
\r
219 vGalileoGPIOWrite(GPIO_INTTYPE_LEVEL, GpioConfig.IntType);
\r
220 // Interrupt Polarity Type Register - GPIO_INT_POLARITY
\r
221 vGalileoGPIOWrite(GPIO_INT_POLARITY, GpioConfig.IntPolarity);
\r
222 // Interrupt Debounce Type Register - GPIO_DEBOUNCE
\r
223 vGalileoGPIOWrite(GPIO_DEBOUNCE, GpioConfig.Debounce);
\r
224 // Interrupt Clock Synchronization Register - GPIO_LS_SYNC
\r
225 vGalileoGPIOWrite(GPIO_LS_SYNC, GpioConfig.LsSync);
\r
226 bGalileoGPIOInitialized = true;
\r
229 /*-----------------------------------------------------------*/
\r
231 /*-----------------------------------------------------------------------
\r
232 * I/O direction and level setting functions
\r
233 *------------------------------------------------------------------------
\r
235 void vGalileoSetGPIOBitDirection(uint32_t GPIONumber, uint32_t Direction)
\r
238 if(GPIONumber <= 9)
\r
240 /* setup gpio direction. */
\r
241 if (bGalileoGPIOInitialized)
\r
243 if(Direction == GPIO_OUTPUT)
\r
244 GpioConfig.PortADir |= (1 << GPIONumber);
\r
246 GpioConfig.PortADir &= ~(1 << GPIONumber);
\r
247 vGalileoGPIOWrite(GPIO_SWPORTA_DDR, GpioConfig.PortADir);
\r
251 /*-----------------------------------------------------------*/
\r
253 void vGalileoSetGPIOBitLevel(uint32_t GPIONumber, uint32_t Level)
\r
256 if(GPIONumber <= 9)
\r
258 /* Set the bit high or low. */
\r
259 if (bGalileoGPIOInitialized)
\r
261 // 1 for on, 0 for off.
\r
263 GpioConfig.PortADR |= (1 << GPIONumber);
\r
265 GpioConfig.PortADR &= ~(1 << GPIONumber);
\r
266 vGalileoGPIOWrite(GPIO_SWPORTA_DR, GpioConfig.PortADR);
\r
270 /*-----------------------------------------------------------*/
\r
272 static void LegacyGpioSetLevel(uint32_t RegOffset, uint32_t GpioNum, uint8_t HighLevel)
\r
275 uint32_t legacy_gpio_base;
\r
276 uint32_t GpioNumMask;
\r
277 uint8_t Bus = LEGACY_GPIO_BUS_NUMBER;
\r
278 uint8_t Device = LEGACY_GPIO_DEVICE_NUMBER;
\r
279 uint8_t Func = LEGACY_GPIO_FUNCTION_NUMBER;
\r
281 // Get PCI Configuration IO Address
\r
283 uiGalileoLegacyGPIOPCIRead(IO_PCI_ADDRESS(Bus, Device, Func, R_QNC_LPC_GBA_BASE), B_QNC_LPC_GPA_BASE_MASK);
\r
285 // Read register (Port I/O )
\r
286 RegValue = inl(legacy_gpio_base + RegOffset);
\r
288 // Set Data and mask
\r
289 GpioNumMask = (1 << GpioNum);
\r
291 RegValue |= (GpioNumMask);
\r
293 RegValue &= ~(GpioNumMask);
\r
295 // Write the data (Port I/O )
\r
296 outl((legacy_gpio_base + RegOffset), RegValue);
\r
298 /*-----------------------------------------------------------*/
\r
300 void vGalileoLegacyGPIOInitializationForLED(void)
\r
302 // Setup multiplexers to route GPIO_SUS<5> to LED
\r
303 vGalileoRouteLEDPins();
\r
305 // Set GPIO_SUS<5> as output
\r
306 LegacyGpioSetLevel (R_QNC_GPIO_RGIO_RESUME_WELL,
\r
307 GALILEO_GEN2_FLASH_UPDATE_LED_RESUMEWELL_GPIO, GPIO_OUTPUT);
\r
309 // Set GPIO_SUS<5> level to low
\r
310 LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL,
\r
311 GALILEO_GEN2_FLASH_UPDATE_LED_RESUMEWELL_GPIO, LOW);
\r
313 /*-----------------------------------------------------------*/
\r
315 void vGalileoBlinkLEDUsingLegacyGPIO(uint32_t Level)
\r
317 LegacyGpioSetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL,
\r
318 GALILEO_GEN2_FLASH_UPDATE_LED_RESUMEWELL_GPIO, Level);
\r
320 /*-----------------------------------------------------------*/
\r
322 /*-----------------------------------------------------------------------
\r
323 * I2C support functions
\r
324 *------------------------------------------------------------------------
\r
326 static inline uint64_t rdtsc(void)
\r
330 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
\r
336 /*-----------------------------------------------------------*/
\r
338 void vMicroSecondDelay(uint32_t DelayTime)
\r
340 uint64_t diff_in_us = 0;
\r
341 uint64_t cpufreq_in_mhz = 400;
\r
342 uint64_t tsc_start = rdtsc();
\r
343 uint64_t tsc_current = tsc_start;
\r
347 diff_in_us = ((tsc_current - tsc_start) / cpufreq_in_mhz);
\r
348 tsc_current = rdtsc();
\r
350 while (diff_in_us < (uint64_t) DelayTime);
\r
352 /*-----------------------------------------------------------*/
\r
354 void vMilliSecondDelay(uint32_t DelayTime)
\r
356 vMicroSecondDelay (DelayTime * 1000);
\r
358 /*-----------------------------------------------------------*/
\r
360 static uintn_t GetI2CIoPortBaseAddress(void)
\r
362 uint8_t Bus = IOH_I2C_GPIO_BUS_NUMBER;
\r
363 uint8_t Device = IOH_I2C_GPIO_DEVICE_NUMBER;
\r
364 int8_t Func = IOH_I2C_GPIO_FUNCTION_NUMBER;
\r
365 uint32_t I2C_controller_base = MMIO_PCI_ADDRESS(Bus, Device, Func, 0);
\r
366 uintn_t I2CIoPortBaseAddress = mem_read(I2C_controller_base, R_IOH_I2C_MEMBAR, 4);
\r
367 return I2CIoPortBaseAddress;
\r
369 /*-----------------------------------------------------------*/
\r
371 static void EnableI2CMmioSpace(void)
\r
373 uint8_t Bus = IOH_I2C_GPIO_BUS_NUMBER;
\r
374 uint8_t Device = IOH_I2C_GPIO_DEVICE_NUMBER;
\r
375 uint8_t Func = IOH_I2C_GPIO_FUNCTION_NUMBER;
\r
376 uint32_t I2C_controller_base = MMIO_PCI_ADDRESS(Bus, Device, Func, 0);
\r
377 uint8_t PciCmd = mem_read(I2C_controller_base, PCI_REG_PCICMD, 1);
\r
378 mem_write(I2C_controller_base, PCI_REG_PCICMD, 1, (PciCmd | 0x7));
\r
380 /*-----------------------------------------------------------*/
\r
382 static void DisableI2CController(void)
\r
384 uintn_t I2CIoPortBaseAddress;
\r
387 uint8_t PollCount = 0;
\r
389 // Get I2C Memory Mapped registers base address.
\r
390 I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
\r
392 // Disable the I2C Controller by setting IC_ENABLE.ENABLE to zero
\r
393 Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
\r
394 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
395 Data &= ~B_I2C_REG_ENABLE;
\r
396 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
398 // Read the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled
\r
400 Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE_STATUS;
\r
401 Data = *((volatile uint32_t *) (uintn_t)(Addr)) & I2C_REG_ENABLE_STATUS;
\r
404 // Poll the IC_ENABLE_STATUS.IC_EN Bit to check if Controller is disabled, until timeout (TI2C_POLL*MAX_T_POLL_COUNT).
\r
405 if (++PollCount >= MAX_T_POLL_COUNT)
\r
407 vMicroSecondDelay(TI2C_POLL);
\r
408 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
409 Data &= I2C_REG_ENABLE_STATUS;
\r
412 // Read IC_CLR_INTR register to automatically clear the combined interrupt,
\r
413 // all individual interrupts and the IC_TX_ABRT_SOURCE register.
\r
414 if (PollCount < MAX_T_POLL_COUNT)
\r
416 Addr = I2CIoPortBaseAddress + I2C_REG_CLR_INT;
\r
417 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
420 /*-----------------------------------------------------------*/
\r
422 static void EnableI2CController(void)
\r
424 uintn_t I2CIoPortBaseAddress;
\r
428 // Get I2C Memory Mapped registers base address.
\r
429 I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
\r
431 // Enable the I2C Controller by setting IC_ENABLE.ENABLE to 1
\r
432 Addr = I2CIoPortBaseAddress + I2C_REG_ENABLE;
\r
433 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
434 Data |= B_I2C_REG_ENABLE;
\r
435 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
437 // Clear overflow and abort error status bits before transactions.
\r
438 Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_OVER;
\r
439 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
440 Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_OVER;
\r
441 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
442 Addr = I2CIoPortBaseAddress + I2C_REG_CLR_TX_ABRT;
\r
443 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
445 /*-----------------------------------------------------------*/
\r
447 static uint32_t InitializeInternal(I2C_ADDR_MODE AddrMode)
\r
449 uintn_t I2CIoPortBaseAddress;
\r
452 uint32_t Status = 0;
\r
454 // Enable access to I2C Controller MMIO space.
\r
455 EnableI2CMmioSpace ();
\r
457 // Disable I2C Controller initially
\r
458 DisableI2CController ();
\r
460 // Get I2C Memory Mapped registers base address.
\r
461 I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
\r
464 Addr = I2CIoPortBaseAddress + I2C_REG_CLR_START_DET;
\r
465 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
466 Data &= ~B_I2C_REG_CLR_START_DET;
\r
467 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
470 Addr = I2CIoPortBaseAddress + I2C_REG_CLR_STOP_DET;
\r
471 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
472 Data &= ~B_I2C_REG_CLR_STOP_DET;
\r
473 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
475 // Set addressing mode to user defined (7 or 10 bit) and
\r
476 // speed mode to that defined by PCD (standard mode default).
\r
477 Addr = I2CIoPortBaseAddress + I2C_REG_CON;
\r
478 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
480 // Set Addressing Mode
\r
481 if (AddrMode == EfiI2CSevenBitAddrMode)
\r
482 Data &= ~B_I2C_REG_CON_10BITADD_MASTER;
\r
484 Data |= B_I2C_REG_CON_10BITADD_MASTER;
\r
487 Data &= ~B_I2C_REG_CON_SPEED;
\r
489 // Default to slow mode
\r
491 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
492 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
495 /*-----------------------------------------------------------*/
\r
497 static void I2cEntry(uint16_t *SaveCmdPtr, uint32_t *SaveBar0Ptr)
\r
499 uint8_t Bus = IOH_I2C_GPIO_BUS_NUMBER;
\r
500 uint8_t Device = IOH_I2C_GPIO_DEVICE_NUMBER;
\r
501 uint8_t Func = IOH_I2C_GPIO_FUNCTION_NUMBER;
\r
502 uint32_t I2C_controller_base = MMIO_PCI_ADDRESS(Bus, Device, Func, 0);
\r
504 I2CGpioBase = mem_read(I2C_controller_base, R_IOH_I2C_MEMBAR, 4);
\r
505 *SaveBar0Ptr = I2CGpioBase;
\r
506 if (((*SaveBar0Ptr) & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0)
\r
508 mem_write(I2C_controller_base, R_IOH_I2C_MEMBAR, 4, IO_PCI_ADDRESS(Bus, Device, Func, 0));
\r
509 // also Save Cmd Register, Setup by InitializeInternal later during xfers.
\r
510 *SaveCmdPtr = mem_read(I2C_controller_base, PCI_REG_PCICMD, 1);
\r
513 /*-----------------------------------------------------------*/
\r
515 static void I2cExit(uint16_t SaveCmd, uint32_t SaveBar0)
\r
517 if ((SaveBar0 & B_IOH_I2C_GPIO_MEMBAR_ADDR_MASK) == 0)
\r
519 uint8_t Bus = IOH_I2C_GPIO_BUS_NUMBER;
\r
520 uint8_t Device = IOH_I2C_GPIO_DEVICE_NUMBER;
\r
521 uint8_t Func = IOH_I2C_GPIO_FUNCTION_NUMBER;
\r
522 uint32_t I2C_controller_base = MMIO_PCI_ADDRESS(Bus, Device, Func, 0);
\r
523 mem_write(I2C_controller_base, PCI_REG_PCICMD, 1, SaveCmd);
\r
524 mem_write(I2C_controller_base, R_IOH_I2C_MEMBAR, 4, SaveBar0);
\r
527 /*-----------------------------------------------------------*/
\r
529 static uint32_t WaitForStopDet(void)
\r
531 uintn_t I2CIoPortBaseAddress;
\r
534 uint32_t PollCount = 0;
\r
535 uint32_t Status = 0;
\r
537 // Get I2C Memory Mapped registers base address.
\r
538 I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
\r
540 // Wait for STOP Detect.
\r
541 Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
\r
544 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
545 if ((Data & I2C_REG_RAW_INTR_STAT_TX_ABRT) != 0)
\r
550 if ((Data & I2C_REG_RAW_INTR_STAT_TX_OVER) != 0)
\r
555 if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0)
\r
560 if ((Data & I2C_REG_RAW_INTR_STAT_STOP_DET) != 0)
\r
565 vMicroSecondDelay(TI2C_POLL);
\r
567 if (PollCount >= MAX_STOP_DET_POLL_COUNT)
\r
576 /*-----------------------------------------------------------*/
\r
578 uint32_t WriteMultipleByte(uintn_t I2CAddress, uint8_t *WriteBuffer, uintn_t Length)
\r
580 uintn_t I2CIoPortBaseAddress;
\r
584 uint32_t Status = 0;
\r
586 if (Length > I2C_FIFO_SIZE)
\r
587 return -1; // Routine does not handle xfers > fifo size.
\r
589 I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
\r
591 // Write to the IC_TAR register the address of the slave device to be addressed
\r
592 Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
\r
593 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
594 Data &= ~B_I2C_REG_TAR;
\r
595 Data |= I2CAddress;
\r
596 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
598 // Enable the I2C Controller
\r
599 EnableI2CController ();
\r
601 // Write the data and transfer direction to the IC_DATA_CMD register.
\r
602 // Also specify that transfer should be terminated by STOP condition.
\r
603 Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
\r
604 for (Index = 0; Index < Length; Index++)
\r
606 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
607 Data &= 0xFFFFFF00;
\r
608 Data |= (uint8_t)WriteBuffer[Index];
\r
609 Data &= ~B_I2C_REG_DATA_CMD_RW;
\r
610 if (Index == (Length-1))
\r
611 Data |= B_I2C_REG_DATA_CMD_STOP;
\r
612 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
615 // Wait for transfer completion
\r
616 Status = WaitForStopDet ();
\r
618 // Ensure I2C Controller disabled.
\r
619 DisableI2CController ();
\r
623 /*-----------------------------------------------------------*/
\r
625 static void I2CWriteMultipleBytes(I2C_DEVICE_ADDRESS SlaveAddress,
\r
626 I2C_ADDR_MODE AddrMode, uintn_t *Length, void *Buffer)
\r
628 uintn_t I2CAddress;
\r
632 if (Buffer != NULL && Length != NULL)
\r
636 I2cEntry (&SaveCmd, &SaveBar0);
\r
637 if (InitializeInternal(AddrMode) == 0)
\r
639 I2CAddress = SlaveAddress.I2CDeviceAddress;
\r
640 WriteMultipleByte(I2CAddress, Buffer, (*Length));
\r
642 I2cExit (SaveCmd, SaveBar0);
\r
645 /*-----------------------------------------------------------*/
\r
647 uint32_t ReadMultipleByte(uintn_t I2CAddress, uint8_t *Buffer,
\r
648 uintn_t WriteLength, uintn_t ReadLength)
\r
650 uintn_t I2CIoPortBaseAddress;
\r
657 if (WriteLength > I2C_FIFO_SIZE || ReadLength > I2C_FIFO_SIZE)
\r
658 return -1; // Routine does not handle xfers > fifo size.
\r
660 I2CIoPortBaseAddress = GetI2CIoPortBaseAddress ();
\r
662 // Write to the IC_TAR register the address of the slave device to be addressed
\r
663 Addr = I2CIoPortBaseAddress + I2C_REG_TAR;
\r
664 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
665 Data &= ~B_I2C_REG_TAR;
\r
666 Data |= I2CAddress;
\r
667 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
669 // Enable the I2C Controller
\r
670 EnableI2CController ();
\r
672 // Write the data (sub-addresses) to the IC_DATA_CMD register.
\r
673 Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
\r
674 for (Index = 0; Index < WriteLength; Index++)
\r
676 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
677 Data &= 0xFFFFFF00;
\r
678 Data |= (uint8_t)Buffer[Index];
\r
679 Data &= ~B_I2C_REG_DATA_CMD_RW;
\r
680 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
683 // Issue Read Transfers for each byte (Restart issued when write/read bit changed).
\r
684 for (Index = 0; Index < ReadLength; Index++)
\r
686 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
687 Data |= B_I2C_REG_DATA_CMD_RW;
\r
688 // Issue a STOP for last read transfer.
\r
689 if (Index == (ReadLength-1))
\r
690 Data |= B_I2C_REG_DATA_CMD_STOP;
\r
691 *((volatile uint32_t *) (uintn_t)(Addr)) = Data;
\r
694 // Wait for STOP condition.
\r
695 Status = WaitForStopDet();
\r
698 // Poll Receive FIFO Buffer Level register until valid (upto MAX_T_POLL_COUNT times).
\r
701 Addr = I2CIoPortBaseAddress + I2C_REG_RXFLR;
\r
702 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
703 while ((Data != ReadLength) && (PollCount < MAX_T_POLL_COUNT))
\r
705 vMicroSecondDelay(TI2C_POLL);
\r
707 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
710 Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
\r
711 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
713 // If no timeout or device error then read rx data.
\r
714 if (PollCount == MAX_T_POLL_COUNT)
\r
718 else if ((Data & I2C_REG_RAW_INTR_STAT_RX_OVER) != 0)
\r
724 // Clear RX underflow before reading IC_DATA_CMD.
\r
725 Addr = I2CIoPortBaseAddress + I2C_REG_CLR_RX_UNDER;
\r
726 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
729 Addr = I2CIoPortBaseAddress + I2C_REG_DATA_CMD;
\r
730 for (Index = 0; Index < ReadLength; Index++)
\r
732 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
733 Data &= 0x000000FF;
\r
734 *(Buffer+Index) = (uint8_t)Data;
\r
736 Addr = I2CIoPortBaseAddress + I2C_REG_RAW_INTR_STAT;
\r
737 Data = *((volatile uint32_t *) (uintn_t)(Addr));
\r
738 Data &= I2C_REG_RAW_INTR_STAT_RX_UNDER;
\r
750 // Ensure I2C Controller disabled.
\r
751 DisableI2CController ();
\r
755 /*-----------------------------------------------------------*/
\r
757 static void I2CReadMultipleBytes(I2C_DEVICE_ADDRESS SlaveAddress, I2C_ADDR_MODE AddrMode,
\r
758 uintn_t *WriteLength, uintn_t *ReadLength, void *Buffer )
\r
760 uintn_t I2CAddress;
\r
764 if (Buffer != NULL && WriteLength != NULL && ReadLength != NULL)
\r
768 I2cEntry (&SaveCmd, &SaveBar0);
\r
769 if (InitializeInternal(AddrMode) == 0)
\r
771 I2CAddress = SlaveAddress.I2CDeviceAddress;
\r
772 ReadMultipleByte(I2CAddress, Buffer, (*WriteLength), (*ReadLength));
\r
774 I2cExit (SaveCmd, SaveBar0);
\r
777 /*-----------------------------------------------------------*/
\r
779 /*-----------------------------------------------------------------------
\r
780 * Pcal9555 chips used on Galileo Gen 2 boards (see FAB-H schematic)
\r
781 *------------------------------------------------------------------------
\r
783 static void Pcal9555SetPortRegBit(uint32_t Pcal9555SlaveAddr, uint32_t GpioNum, uint8_t RegBase, uint8_t LogicOne)
\r
785 uintn_t ReadLength;
\r
786 uintn_t WriteLength;
\r
788 uint8_t *RegValuePtr;
\r
789 uint8_t GpioNumMask;
\r
791 I2C_DEVICE_ADDRESS I2cDeviceAddr;
\r
792 I2C_ADDR_MODE I2cAddrMode;
\r
794 // Set I2C address and mode.
\r
795 I2cDeviceAddr.I2CDeviceAddress = (uintn_t) Pcal9555SlaveAddr;
\r
796 I2cAddrMode = EfiI2CSevenBitAddrMode;
\r
798 // Set I2C subaddress and GPIO mask.
\r
802 GpioNumMask = (uintn_t) (1 << GpioNum);
\r
806 SubAddr = RegBase + 1;
\r
807 GpioNumMask = (uintn_t) (1 << (GpioNum - 8));
\r
810 // Output port value always at 2nd byte in Data variable.
\r
811 RegValuePtr = &Data[1];
\r
813 // On read entry - sub address at 2nd byte, on read exit - output
\r
814 // port value in 2nd byte.
\r
818 I2CReadMultipleBytes(I2cDeviceAddr, I2cAddrMode, &WriteLength, &ReadLength, &Data[1]);
\r
820 // Adjust output port bit using mask value.
\r
822 *RegValuePtr = *RegValuePtr | GpioNumMask;
\r
824 *RegValuePtr = *RegValuePtr & ~(GpioNumMask);
\r
826 // Update register. Sub address at 1st byte, value at 2nd byte.
\r
829 I2CWriteMultipleBytes(I2cDeviceAddr,I2cAddrMode, &WriteLength, Data);
\r
831 /*-----------------------------------------------------------*/
\r
833 static void PlatformPcal9555GpioPullup(uint32_t Pcal9555SlaveAddr, uint32_t GpioNum, uint32_t Enable)
\r
835 Pcal9555SetPortRegBit(Pcal9555SlaveAddr, GpioNum, PCAL9555_REG_PULL_EN_PORT0, Enable );
\r
837 /*-----------------------------------------------------------*/
\r
839 static void PlatformPcal9555GpioSetDir(uint32_t Pcal9555SlaveAddr, uint32_t GpioNum, uint32_t CfgAsInput)
\r
841 Pcal9555SetPortRegBit(Pcal9555SlaveAddr, GpioNum, PCAL9555_REG_CFG_PORT0, CfgAsInput);
\r
843 /*-----------------------------------------------------------*/
\r
845 static void PlatformPcal9555GpioSetLevel(uint32_t Pcal9555SlaveAddr, uint32_t GpioNum, uint32_t HighLevel )
\r
847 Pcal9555SetPortRegBit(Pcal9555SlaveAddr, GpioNum, PCAL9555_REG_OUT_PORT0, HighLevel );
\r
849 /*-----------------------------------------------------------*/
\r
851 /*-----------------------------------------------------------------------
\r
852 * GPIO pin routing function
\r
853 *------------------------------------------------------------------------
\r
855 static void vGalileoRouteLEDPins(void)
\r
857 // For GpioNums below values 0 to 7 are for Port0 IE. P0-0 - P0-7 and
\r
858 // values 8 to 15 are for Port1 IE. P1-0 - P1-7.
\r
859 // Disable Pull-ups / pull downs on EXP0 pin for LVL_B_PU7 signal.
\r
860 PlatformPcal9555GpioPullup (
\r
861 GALILEO_GEN2_IOEXP0_7BIT_SLAVE_ADDR, // IO Expander 0.
\r
866 // Make LVL_B_OE7_N an output pin.
\r
867 PlatformPcal9555GpioSetDir (
\r
868 GALILEO_GEN2_IOEXP0_7BIT_SLAVE_ADDR, // IO Expander 0.
\r
872 // Set level of LVL_B_OE7_N to low.
\r
873 PlatformPcal9555GpioSetLevel (
\r
874 GALILEO_GEN2_IOEXP0_7BIT_SLAVE_ADDR,
\r
878 // Make MUX8_SEL an output pin.
\r
879 PlatformPcal9555GpioSetDir (
\r
880 GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR, // IO Expander 1.
\r
884 // Set level of MUX8_SEL to low to route GPIO_SUS<5> to LED.
\r
885 PlatformPcal9555GpioSetLevel (
\r
886 GALILEO_GEN2_IOEXP1_7BIT_SLAVE_ADDR, // IO Expander 1.
\r
890 /*-----------------------------------------------------------*/
\r