OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.swp.api/] [openmcapi/] [1.0/] [libmcapi/] [shm/] [linux/] [kmod/] [mv78xx0.c] - Blame information for rev 145

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 145 lanttu
/*
2
 * Copyright (c) 2010, Mentor Graphics Corporation
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * Alternatively, this software may be distributed under the terms of the
18
 * GNU General Public License ("GPL") version 2 as published by the Free
19
 * Software Foundation.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
 * POSSIBILITY OF SUCH DAMAGE.
32
 */
33
 
34
#include <linux/kernel.h>
35
#include <linux/mm.h>
36
#include <linux/io.h>
37
#include <linux/module.h>
38
#include <linux/platform_device.h>
39
 
40
#include <asm/io.h>
41
#include <asm/pgtable.h>
42
 
43
#include "mcomm.h"
44
#include "mcomm_dev.h"
45
 
46
/* extracted from the bowels of Marvell's arch/arm/mach-feroceon-mv78xx0 */
47
/* XXX add these to appropriate Linux headers */
48
#define CPU_IF_BASE(cpu)                (0xF1020000 + ((cpu) << 14))
49
#define AHB_TO_MBUS_BASE                CPU_IF_BASE
50
#define INBOUND_DOORBELL(cpu)   (AHB_TO_MBUS_BASE(cpu) + 0x400)
51
#define INBOUND_DOORBELL_MASK(cpu)      (AHB_TO_MBUS_BASE(cpu) + 0x404)
52
 
53
#define DOORBELL_NR 0
54
#define DOORBELL_VAL (1<<DOORBELL_NR)
55
 
56
static struct mcomm_mv78xx0_data {
57
        void __iomem *dbell[2]; /* "inbound" doorbells */
58
        void __iomem *dbell_mask;
59
        unsigned int cpu_nr;
60
} mcomm_mv78xx0_data;
61
 
62
/* MV78xx0 is a dual-core ARMv5 processor. It does not provide implicit data
63
 * cache coherence between the two cores, so to simplify software we map the
64
 * shared memory non-cacheable in both user and kernel space. */
65
 
66
static pgprot_t mcomm_mv78xx0_mmap_pgprot(struct vm_area_struct *vma)
67
{
68
        return pgprot_noncached(vma->vm_page_prot);
69
}
70
 
71
static void __iomem *mcomm_mv78xx0_ioremap(unsigned long phys_addr, size_t size)
72
{
73
        return ioremap_nocache(phys_addr, size);
74
}
75
 
76
static void mcomm_mv78xx0_notify(u32 core_nr)
77
{
78
        BUG_ON(core_nr > 1);
79
 
80
        /* set the other core's inbound doorbell */
81
        writel(DOORBELL_VAL, mcomm_mv78xx0_data.dbell[core_nr]);
82
}
83
 
84
static void mcomm_mv78xx0_ack(void)
85
{
86
        /* clear this core's inbound doorbell */
87
        writel(0x0, mcomm_mv78xx0_data.dbell[mcomm_mv78xx0_data.cpu_nr]);
88
}
89
 
90
static unsigned long mcomm_mv78xx0_cpuid(void)
91
{
92
        return mcomm_mv78xx0_data.cpu_nr;
93
}
94
 
95
static struct mcomm_platform_ops mcomm_mv78xx0_ops = {
96
        .mmap_pgprot = mcomm_mv78xx0_mmap_pgprot,
97
        .map = mcomm_mv78xx0_ioremap,
98
        .notify = mcomm_mv78xx0_notify,
99
        .ack = mcomm_mv78xx0_ack,
100
        .cpuid = mcomm_mv78xx0_cpuid,
101
};
102
 
103
 
104
static void mcomm_mv78xx0_hwinit(void)
105
{
106
        unsigned int cpu_nr;
107
        u32 reg;
108
 
109
        __asm__ __volatile__ (
110
                "mrc p15, 1, %0, c15, c1, 0 @ read control reg\n"
111
                : "=r" (reg)
112
        );
113
 
114
        cpu_nr = (reg >> 14) & 0x1;
115
 
116
        mcomm_mv78xx0_data.cpu_nr = cpu_nr;
117
        mcomm_mv78xx0_data.dbell[0] = ioremap(INBOUND_DOORBELL(0), 4);
118
        mcomm_mv78xx0_data.dbell[1] = ioremap(INBOUND_DOORBELL(1), 4);
119
        mcomm_mv78xx0_data.dbell_mask = ioremap(INBOUND_DOORBELL_MASK(cpu_nr), 4);
120
 
121
        /* Clear any pending interrupts. */
122
        writel(0x0, mcomm_mv78xx0_data.dbell[cpu_nr]);
123
 
124
        /* Enable IRQs for our doorbell bits. */
125
        writel(DOORBELL_VAL, mcomm_mv78xx0_data.dbell_mask);
126
}
127
 
128
static int __devinit mcomm_probe(struct platform_device *pdev)
129
{
130
        struct resource *mem;
131
        struct resource *irq;
132
 
133
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
134
        if (!mem)
135
                return -EINVAL;
136
 
137
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
138
        if (!irq)
139
                return -EINVAL;
140
 
141
        mcomm_mv78xx0_hwinit();
142
 
143
        return mcomm_new_region(&pdev->dev, mem, irq);
144
}
145
 
146
static void mcomm_mv78xx0_hwuninit(void)
147
{
148
        iounmap(mcomm_mv78xx0_data.dbell[0]);
149
        iounmap(mcomm_mv78xx0_data.dbell[1]);
150
 
151
        /* Disable doorbell IRQ again. */
152
        writel(0x0, mcomm_mv78xx0_data.dbell_mask);
153
        iounmap(mcomm_mv78xx0_data.dbell_mask);
154
}
155
 
156
static int mcomm_remove(struct platform_device *pdev)
157
{
158
        mcomm_remove_region(&pdev->dev);
159
        mcomm_mv78xx0_hwuninit();
160
 
161
        return 0;
162
}
163
 
164
static struct platform_driver mcomm_driver = {
165
        .probe = mcomm_probe,
166
        .remove = mcomm_remove,
167
        .driver = {
168
                   .name = "mcomm",
169
        }
170
};
171
 
172
 
173
static int __init mcomm_mv78xx0_modinit(void)
174
{
175
        int rc;
176
 
177
        rc = mcomm_init(&mcomm_mv78xx0_ops, THIS_MODULE);
178
        if (rc) {
179
                printk(KERN_ERR "%s: Failed to initialize mcomm driver.\n", __func__);
180
                goto out1;
181
        }
182
 
183
        rc = platform_driver_register(&mcomm_driver);
184
        if (rc) {
185
                printk(KERN_ERR "%s: Failed to register platform driver.\n", __func__);
186
                goto out2;
187
        }
188
 
189
        /* Finally, register an mcomm device. We can only have one, so if there's
190
         * an error we should just give up. */
191
        rc = mcomm_pdev_add();
192
        if (rc)
193
                goto out3;
194
 
195
        return 0;
196
 
197
out3:
198
        platform_driver_unregister(&mcomm_driver);
199
out2:
200
        mcomm_exit();
201
out1:
202
        return rc;
203
}
204
module_init(mcomm_mv78xx0_modinit);
205
 
206
static void mcomm_mv78xx0_modexit(void)
207
{
208
        mcomm_pdev_release();
209
        platform_driver_unregister(&mcomm_driver);
210
        mcomm_exit();
211
}
212
module_exit(mcomm_mv78xx0_modexit);
213
 
214
MODULE_LICENSE("GPL v2");
215
MODULE_AUTHOR("Hollis Blanchard <hollis_blanchard@mentor.com>");
216
MODULE_DESCRIPTION("Marvell 78xx0 platform support for multi-core shared memory channel");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.