1/**
2 * \file
3 * \brief kernel driver for the spinlock module, used for serial output
4 * see OMAP4460 TRM chapter 21 for a functional description
5 */
6
7/*
8 * Copyright (c) 2013, ETH Zurich.
9 * All rights reserved.
10 *
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
14 */
15
16#include <kernel.h>
17#include <paging_kernel_arch.h>
18#include <omap44xx_spinlock.h>
19#include <dev/omap/omap44xx_spinlock_dev.h>
20#include <maps/omap44xx_map.h>
21
22
23#define MSG(format, ...) printk( LOG_NOTE, "OMAP44xx spinlock: "format, ## __VA_ARGS__ )
24
25static omap44xx_spinlock_t spinlock;
26static bool locks_initialized;  //allows early initialization
27
28/**
29 * \brief Map the OMAP44xx spinlock device into kernel virtual memory
30 * and reset it.
31 */
32
33errval_t omap44xx_spinlock_init(void)
34{
35    if (locks_initialized) {
36	MSG("already initialized; skipping.\n");
37	return SYS_ERR_OK;
38    }
39
40    lvaddr_t base = paging_map_device(OMAP44XX_MAP_L4_CFG_SPINLOCK,
41				      OMAP44XX_MAP_L4_CFG_SPINLOCK_SIZE);
42    MSG("init base = 0x%"PRIxLVADDR"\n", base);
43    omap44xx_spinlock_initialize(&spinlock, (mackerel_addr_t)base);
44
45    // This next line to rest the module is probably not needed.
46    omap44xx_spinlock_sysconfig_softreset_wrf(&spinlock, 1);
47
48    MSG("testing spinlock: first read (should be 0): 0x%x\n",
49                omap44xx_spinlock_lock_reg_i_taken_rdf(&spinlock, 2));
50
51    MSG("testing spinlock: second read (should be 1): 0x%x\n",
52                omap44xx_spinlock_lock_reg_i_taken_rdf(&spinlock, 2));
53
54    omap44xx_spinlock_lock_reg_i_taken_wrf(&spinlock, 2, 0);//clear lock
55    locks_initialized = true;
56    MSG("init done.\n");
57    return SYS_ERR_OK;
58}
59
60/**
61 * \brief acquire an OMAP44xx spinlock.  We repeatedly read the
62 * register; 0 means we have the lock, 1 means we have to try again.
63 */
64void omap44xx_spinlock_acquire( unsigned locknumber ) {
65    assert( locknumber < OMAP44XX_SPINLOCK_NUM_LOCKS );
66    while( omap44xx_spinlock_lock_reg_i_taken_rdf(&spinlock, locknumber)) { }
67}
68
69/**
70 * \brief release an OMAP44xx spinlock.
71 */
72void omap44xx_spinlock_release( unsigned locknumber ) {
73    assert( locknumber < OMAP44XX_SPINLOCK_NUM_LOCKS );
74    omap44xx_spinlock_lock_reg_i_taken_wrf(&spinlock, locknumber, 0);
75}
76
77