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