; Copyright 2010 Castle Technology Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; GET Hdr:ListOpts GET Hdr:Macros GET Hdr:System GET Hdr:Machine.<Machine> GET Hdr:ImageSize.<ImageSize> $GetIO GET Hdr:Proc GET Hdr:OSEntries GET Hdr:HALEntries GET hdr.omap3530 GET hdr.StaticWS GET hdr.GPIO AREA |Asm$$Code|, CODE, READONLY, PIC EXPORT GPIO_Init EXPORT GPIOx_SetAsOutput EXPORT GPIOx_SetOutput EXPORT GPIOx_SetAndEnableIRQ EXPORT GPIO_InitDevice IMPORT TPSRead IMPORT TPSWrite IMPORT IIC_DoOp_Poll IMPORT DebugHALPrint IMPORT DebugHALPrintReg IMPORT memcpy GPIO_Init ; Don't bother resetting the controllers, it could conflict with settings made by x-loader/u-boot Entry "v1-v3",4 ADR a1, L4_GPIO_Table MOV a2, #6 MOV a3, #0 10 LDR a4, [a1], #4 SUBS a2, a2, #1 STR a3, [a4, #GPIO_IRQENABLE1] BNE %BT10 ; Make sure the TPS GPIOs are enabled properly. ; Specifically: ; - Set the GPIO_ON bit in GPIO_CTRL LDR v1, HALInitialised CMP v1, #0 ADREQL v1, IIC_DoOp_Poll LDRNE v1, OSentries+4*OS_IICOpV MOV a1, #TPSGPIO_IIC*2 MOV a2, sp MOV a3, #1 MOV a4, #TPS_GPIO_CTRL BL TPSRead LDRB ip, [a2] TST ip, #4 ; GPIO_ON ORREQ ip, ip, #4 STREQB ip, [a2] MOVEQ a1, #TPSGPIO_IIC*2 BLEQ TPSWrite ; - For the beagleboard, set up the right pullup/down settings ; TODO - Do other platforms, and add to boardconfig LDR a1, [sb, #BoardConfig_MachID] LDR a2, =MachID_BeagleBoard CMP a1, a2 BNE %FT10 MOV a1, #TPSGPIO_IIC*2 ADR a2, Beagle_TPS_PUPD MOV a3, #5 MOV a4, #TPS_GPIOPUPCTR1 BL TPSWrite 10 EXIT Beagle_TPS_PUPD DCD 4_1010000111000120 ; 0 = PU/PD off, 1=PD, 2=PU DCD 4_0011 ; a1 = GPIO # (OMAP or TPS or TPS LED) ; a2 = initial value (zero or nonzero) GPIOx_SetAsOutput SUBS a3, a1, #GPIO_PIN_MAX BGE %FT10 ; OMAP GPIO GPIO_PrepareR a3, a4, a1 GPIO_SetAsOutput a3, a4, a1 GPIO_SetOutput a2, a3, a4 MOV pc, lr 10 ; TPS GPIO Entry "v1-v3", 4 CMP a3, #TPS_GPIO_PIN_MAX BGE %FT20 MOV a4, a3, LSR #3 ; Register offset MOV v2, a2 AND a3, a3, #&7 MOV v3, #1 MOV v3, v3, LSL a3 ; Mask value ; If HAL_Init isn't done yet, we can't use OS_IICOpV LDR v1, HALInitialised CMP v1, #0 ADREQL v1, IIC_DoOp_Poll LDRNE v1, OSentries+4*OS_IICOpV MOV a1, #TPSGPIO_IIC*2 MOV a2, sp MOV a3, #1 ADD a4, a4, #TPS_GPIODATADIR1 BL TPSRead ; TODO - Handle error! LDRB ip, [a2] ORR ip, ip, v3 STRB ip, [a2] MOV a1, #TPSGPIO_IIC*2 BL TPSWrite STRB v3, [a2] MOV a1, #TPSGPIO_IIC*2 CMP v2, #0 ADDNE a4, a4, #TPS_SETGPIODATAOUT1-TPS_GPIODATADIR1 ADDEQ a4, a4, #TPS_CLEARGPIODATAOUT1-TPS_GPIODATADIR1 BL TPSWrite EXIT 20 ; TPS LED ; First make sure the relevant PWM is configured correctly ; i.e. generate a constant signal, not timed on/off Push "a2,a3" MOV a1, #TPSLED_IIC*2 ADR a2, PWM_Value MOV a3, #2 MOVEQ a4, #TPS_PWMAON MOVNE a4, #TPS_PWMBON LDR v1, HALInitialised CMP v1, #0 ADREQL v1, IIC_DoOp_Poll LDRNE v1, OSentries+4*OS_IICOpV BL TPSWrite ; Also make sure the PWM clocks are enabled MOV a1, #&49*2 ADD a2, sp, #8 MOV a3, #1 MOV a4, #&91 ; GPBR1 BL TPSRead LDR ip, [sp, #4] CMP ip, #TPS_GPIO_PIN_MAX LDRB ip, [a2] ORREQ ip, ip, #&5 ORRNE ip, ip, #&a STRB ip, [a2] MOV a1, #&49*2 BL TPSWrite Pull "a2,a3" CMP a3, #TPS_GPIO_PIN_MAX ; Match the behaviour of Linux: ; a2=0 sets the LED*ON and LED*PWM bits ; a2!=0 clears them MOVEQ v3, #&55 ; Mask for LEDA bits MOVNE v3, #&AA ; Mask for LEDB bits CMP a2, #0 MOVNE v2, #0 ; a2!=0, don't set any bits ANDEQ v2, v3, #&33 ; a2=0, set appropriate LED*ON and LED*PWM bit MOV a1, #TPSLED_IIC*2 MOV a2, sp MOV a3, #1 MOV a4, #TPS_LEDEN ; If HAL_Init isn't done yet, we can't use OS_IICOpV BL TPSRead LDRB ip, [a2] BIC ip, ip, v3 ORR ip, ip, v2 STRB ip, [a2] MOV a1, #TPSLED_IIC*2 BL TPSWrite EXIT PWM_Value DCD &7f7f ; a1 = GPIO # (OMAP or TPS) ; a2 = value (zero or nonzero) GPIOx_SetOutput SUBS a3, a1, #GPIO_PIN_MAX BGE %FT10 ; OMAP GPIO GPIO_PrepareR a3, a4, a1 GPIO_SetOutput a2, a3, a4 MOV pc, lr 10 ; TPS GPIO Entry "v1-v2", 4 MOV a4, a3, LSR #3 ; Register offset CMP a2, #0 AND a3, a3, #&7 ADDNE a4, a4, #TPS_SETGPIODATAOUT1 MOV v1, #1 ADDEQ a4, a4, #TPS_CLEARGPIODATAOUT1 MOV v1, v1, LSL a3 ; Mask value MOV a2, sp STRB v1, [sp] MOV a1, #TPSGPIO_IIC*2 ; If HAL_Init isn't done yet, we can't use OS_IICOpV LDR v1, HALInitialised CMP v1, #0 ADREQL v1, IIC_DoOp_Poll LDRNE v1, OSentries+4*OS_IICOpV MOV a3, #1 BL TPSWrite EXIT ; a1 = GPIO # (OMAP only!) ; a2 = IRQ type flags: ; +1 = LEVELDETECT0 ; +2 = LEVELDETECT1 ; +4 = RISINGDETECT ; +8 = FALLINGDETECT GPIOx_SetAndEnableIRQ GPIO_PrepareR a3, a4, a1 MRS ip, CPSR ORR a1, ip, #I32_bit ; interrupts off MSR CPSR_c, a1 MOV a2, a2, LSL #28 MSR CPSR_f, a2 ; load into NZCV flags (MI EQ CS VS condition codes) LDR a1, [a3, #GPIO_FALLINGDETECT] BICPL a1, a1, a4 LDR a2, [a3, #GPIO_RISINGDETECT] ORRMI a1, a1, a4 STR a1, [a3, #GPIO_FALLINGDETECT] BICNE a2, a2, a4 LDR a1, [a3, #GPIO_LEVELDETECT1] ORREQ a2, a2, a4 STR a2, [a3, #GPIO_RISINGDETECT] BICCC a1, a1, a4 LDR a2, [a3, #GPIO_LEVELDETECT0] ORRCS a1, a1, a4 STR a1, [a3, #GPIO_LEVELDETECT1] BICVC a2, a2, a4 LDR a1, [a3, #GPIO_OE] ORRVS a2, a2, a4 ORR a1, a1, a4 ; set pin as input STR a2, [a3, #GPIO_LEVELDETECT0] STR a1, [a3, #GPIO_OE] STR a4, [a3, #GPIO_SETIRQENABLE1] MSR CPSR_c, ip ; interrupts restored MOV pc, lr ; Init the GPIO HAL device ; a1 = GPIOType value ; a2 = GPIORevision value GPIO_InitDevice Push "a1-a2,lr" ADRL a1, GPIOWS ADR a2, GPIOTemplate MOV a3, #HALDeviceSize BL memcpy Pull "a1-a2,lr" ADRL a3, GPIOWS STR a1, [a3, #HALDevice_GPIOType] STR a2, [a3, #HALDevice_GPIORevision] MOV a2, a3 MOV a1, #0 LDR pc, OSentries + 4*OS_AddDevice ; Tail call ; Generic HAL device used for all board types GPIOTemplate DCW HALDeviceType_Comms + HALDeviceComms_GPIO DCW HALDeviceID_GPIO_OMAP3 DCD HALDeviceBus_Peri + HALDevicePeriBus_Sonics3220 DCD 0 ; API version DCD GPIODesc ; Description DCD 0 ; Address (none) % 12 ; Reserved DCD GPIOActivate DCD GPIODeactivate DCD GPIOReset DCD GPIOSleep DCD -1 ; Device (none) DCD 0 ; TestIRQ DCD 0 ; ClearIRQ % 4 ASSERT (.-GPIOTemplate) = HALDeviceSize GPIODesc = "OMAP3 GPIO interface", 0 ALIGN ; These don't do much GPIOActivate MOV a1, #1 GPIODeactivate GPIOReset MOV pc, lr GPIOSleep MOV a1, #0 MOV pc, lr END