1-- 2-- Copyright 2014, General Dynamics C4 Systems 3-- 4-- This software may be distributed and modified according to the terms of 5-- the GNU General Public License version 2. Note that NO WARRANTY is provided. 6-- See "LICENSE_GPLv2.txt" for details. 7-- 8-- @TAG(GD_GPL) 9-- 10 11{-# LANGUAGE EmptyDataDecls, ForeignFunctionInterface, GeneralizedNewtypeDeriving #-} 12 13module SEL4.Machine.Hardware.ARM.Exynos4210 where 14 15import Prelude hiding (Word) 16import SEL4.Machine.RegisterSet 17import SEL4.Machine.Hardware.ARM.Callbacks 18import SEL4.Machine.Hardware.GICInterface hiding (IRQ, maskInterrupt) 19import qualified SEL4.Machine.Hardware.GICInterface as GIC 20import qualified SEL4.Machine.Hardware.MCTInterface as MCT 21import Foreign.Ptr 22import Data.Bits 23 24-- Following harded coded address pair are used in getKernelDevices 25-- and will get mapped into kernel address space via mapKernelFrame 26uart = (PAddr 0x13810000, PPtr 0xfff01000) 27mct = (PAddr 0x10050000, PPtr 0xfff02000) 28l2cc = (PAddr 0x10502000, PPtr 0xfff03000) 29gicController = (PAddr 0x10480000, PPtr 0xfff04000) 30gicDistributor = (PAddr 0x10490000, PPtr 0xfff05000) 31 32gicInterfaceBase = PAddr 0x10480000 33gicDistributorBase = PAddr 0x10490000 34mctBase = PAddr 0x10050000 35 36kernelBase :: VPtr 37kernelBase = VPtr 0xe0000000 38 39physBase = 0x40000000 40physMappingOffset = 0xe0000000 - physBase 41 42ptrFromPAddr :: PAddr -> PPtr a 43ptrFromPAddr (PAddr addr) = PPtr $ addr + physMappingOffset 44 45addrFromPPtr :: PPtr a -> PAddr 46addrFromPPtr (PPtr ptr) = PAddr $ ptr - physMappingOffset 47 48pageColourBits :: Int 49pageColourBits = 0 -- qemu has no cache 50 51getMemoryRegions :: Ptr CallbackData -> IO [(PAddr, PAddr)] 52getMemoryRegions _ = return [(0x40000000, 0x40000000 + (0x8 `shiftL` 24))] 53 54getDeviceRegions :: Ptr CallbackData -> IO [(PAddr, PAddr)] 55getDeviceRegions _ = return devices 56 where devices = [(0x139D0000,0x139D0000 + (1 `shiftL` 12))] 57 58type IRQ = GIC.IRQ 59 60timerIRQ = GIC.IRQ 89 61 62 63getKernelDevices :: Ptr CallbackData -> IO [(PAddr, PPtr Word)] 64getKernelDevices _ = return devices 65 where devices = [ 66 mct,-- kernel timer 67 gicController, -- interrupt controller 68 gicDistributor, -- interrupt controller 69 uart 70 ] 71 72maskInterrupt :: Ptr CallbackData -> Bool -> IRQ -> IO () 73maskInterrupt env mask irq = do 74 callGICApi (GicState { env = env, gicDistBase = gicDistributorBase, gicIFBase = gicInterfaceBase }) 75 (GIC.maskInterrupt mask irq) 76 77-- We don't need to acknowledge interrupts explicitly because we don't use 78-- the vectored interrupt controller. 79ackInterrupt :: Ptr CallbackData -> IRQ -> IO () 80ackInterrupt env irq = callGICApi gic (GIC.ackInterrupt irq) 81 where gic = GicState { env = env, 82 gicDistBase = gicDistributorBase, 83 gicIFBase = gicInterfaceBase } 84 85foreign import ccall unsafe "qemu_run_devices" 86 runDevicesCallback :: IO () 87 88getActiveIRQ :: Ptr CallbackData -> IO (Maybe IRQ) 89getActiveIRQ env = do 90 runDevicesCallback 91 active <- callGICApi gicdata $ GIC.getActiveIRQ 92 case active of 93 Just 0x3FF -> return Nothing 94 _ -> return active 95 where gicdata = GicState { env = env, 96 gicDistBase = gicDistributorBase, 97 gicIFBase = gicInterfaceBase } 98 99 100-- FIXME: This is not accurate, need to check MCT Freq 101timerFreq :: Word 102timerFreq = 100 103 104timerLimit :: Word 105timerLimit = 1000000 `div` timerFreq 106 107configureTimer :: Ptr CallbackData -> IO IRQ 108configureTimer env = do 109 MCT.callMCTApi mctdata $ MCT.mctInit 110 return timerIRQ 111 where mctdata = MCT.MCTState { MCT.env = env, 112 MCT.mctBase = mctBase } 113 114initIRQController :: Ptr CallbackData -> IO () 115initIRQController env = callGICApi gicdata $ GIC.initIRQController 116 where gicdata = GicState { env = env, 117 gicDistBase = gicDistributorBase, 118 gicIFBase = gicInterfaceBase } 119 120resetTimer :: Ptr CallbackData -> IO () 121resetTimer env = do 122 MCT.callMCTApi mctdata $ MCT.resetTimer 123 where mctdata = MCT.MCTState { MCT.env = env, 124 MCT.mctBase = mctBase } 125 126 127isbCallback :: Ptr CallbackData -> IO () 128isbCallback _ = return () 129 130dsbCallback :: Ptr CallbackData -> IO () 131dsbCallback _ = return () 132 133dmbCallback :: Ptr CallbackData -> IO () 134dmbCallback _ = return () 135 136cacheCleanByVACallback :: Ptr CallbackData -> VPtr -> PAddr -> IO () 137cacheCleanByVACallback _cptr _mva _pa = return () 138 139cacheCleanByVA_PoUCallback :: Ptr CallbackData -> VPtr -> PAddr -> IO () 140cacheCleanByVA_PoUCallback _cptr _mva _pa = return () 141 142cacheInvalidateByVACallback :: Ptr CallbackData -> VPtr -> PAddr -> IO () 143cacheInvalidateByVACallback _cptr _mva _pa = return () 144 145cacheInvalidateByVA_ICallback :: Ptr CallbackData -> VPtr -> PAddr -> IO () 146cacheInvalidateByVA_ICallback _cptr _mva _pa = return () 147 148cacheInvalidate_I_PoUCallback :: Ptr CallbackData -> IO () 149cacheInvalidate_I_PoUCallback _ = return () 150 151cacheCleanInvalidateByVACallback :: 152 Ptr CallbackData -> VPtr -> PAddr -> IO () 153cacheCleanInvalidateByVACallback _cptr _mva _pa = return () 154 155branchFlushCallback :: Ptr CallbackData -> VPtr -> PAddr -> IO () 156branchFlushCallback _cptr _mva _pa = return () 157 158cacheClean_D_PoUCallback :: Ptr CallbackData -> IO () 159cacheClean_D_PoUCallback _ = return () 160 161cacheCleanInvalidate_D_PoCCallback :: Ptr CallbackData -> IO () 162cacheCleanInvalidate_D_PoCCallback _ = return () 163 164cacheCleanInvalidate_D_PoUCallback :: Ptr CallbackData -> IO () 165cacheCleanInvalidate_D_PoUCallback _ = return () 166 167cacheCleanInvalidateL2RangeCallback :: 168 Ptr CallbackData -> PAddr -> PAddr -> IO () 169cacheCleanInvalidateL2RangeCallback _ _ _ = return () 170 171cacheInvalidateL2RangeCallback :: Ptr CallbackData -> PAddr -> PAddr -> IO () 172cacheInvalidateL2RangeCallback _ _ _ = return () 173 174cacheCleanL2RangeCallback :: Ptr CallbackData -> PAddr -> PAddr -> IO () 175cacheCleanL2RangeCallback _ _ _ = return () 176 177-- For the ARM1136 178cacheLine :: Int 179cacheLine = 32 180 181cacheLineBits :: Int 182cacheLineBits = 5 183