Statistics
| Branch: | Revision:

root / hw / misc / omap_l4.c @ a8aec295

History | View | Annotate | Download (4.3 kB)

1 2c1d9ecb cmchao
/*
2 2c1d9ecb cmchao
 * TI OMAP L4 interconnect emulation.
3 2c1d9ecb cmchao
 *
4 2c1d9ecb cmchao
 * Copyright (C) 2007-2009 Nokia Corporation
5 2c1d9ecb cmchao
 * Written by Andrzej Zaborowski <andrew@openedhand.com>
6 2c1d9ecb cmchao
 *
7 2c1d9ecb cmchao
 * This program is free software; you can redistribute it and/or
8 2c1d9ecb cmchao
 * modify it under the terms of the GNU General Public License as
9 2c1d9ecb cmchao
 * published by the Free Software Foundation; either version 2 or
10 2c1d9ecb cmchao
 * (at your option) any later version of the License.
11 2c1d9ecb cmchao
 *
12 2c1d9ecb cmchao
 * This program is distributed in the hope that it will be useful,
13 2c1d9ecb cmchao
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 2c1d9ecb cmchao
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 2c1d9ecb cmchao
 * GNU General Public License for more details.
16 2c1d9ecb cmchao
 *
17 2c1d9ecb cmchao
 * You should have received a copy of the GNU General Public License along
18 2c1d9ecb cmchao
 * with this program; if not, see <http://www.gnu.org/licenses/>.
19 2c1d9ecb cmchao
 */
20 83c9f4ca Paolo Bonzini
#include "hw/hw.h"
21 0d09e41a Paolo Bonzini
#include "hw/arm/omap.h"
22 2c1d9ecb cmchao
23 2c1d9ecb cmchao
struct omap_l4_s {
24 f3226149 Avi Kivity
    MemoryRegion *address_space;
25 a8170e5e Avi Kivity
    hwaddr base;
26 2c1d9ecb cmchao
    int ta_num;
27 2c1d9ecb cmchao
    struct omap_target_agent_s ta[0];
28 2c1d9ecb cmchao
};
29 2c1d9ecb cmchao
30 f3226149 Avi Kivity
struct omap_l4_s *omap_l4_init(MemoryRegion *address_space,
31 a8170e5e Avi Kivity
                               hwaddr base, int ta_num)
32 2c1d9ecb cmchao
{
33 7267c094 Anthony Liguori
    struct omap_l4_s *bus = g_malloc0(
34 2c1d9ecb cmchao
                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
35 2c1d9ecb cmchao
36 f3226149 Avi Kivity
    bus->address_space = address_space;
37 2c1d9ecb cmchao
    bus->ta_num = ta_num;
38 2c1d9ecb cmchao
    bus->base = base;
39 2c1d9ecb cmchao
40 2c1d9ecb cmchao
    return bus;
41 2c1d9ecb cmchao
}
42 2c1d9ecb cmchao
43 a8170e5e Avi Kivity
hwaddr omap_l4_region_base(struct omap_target_agent_s *ta,
44 f9049203 Juha Riihimäki
                                       int region)
45 f9049203 Juha Riihimäki
{
46 f9049203 Juha Riihimäki
    return ta->bus->base + ta->start[region].offset;
47 f9049203 Juha Riihimäki
}
48 f9049203 Juha Riihimäki
49 a8170e5e Avi Kivity
hwaddr omap_l4_region_size(struct omap_target_agent_s *ta,
50 f3226149 Avi Kivity
                                       int region)
51 f3226149 Avi Kivity
{
52 f3226149 Avi Kivity
    return ta->start[region].size;
53 f3226149 Avi Kivity
}
54 f3226149 Avi Kivity
55 a8170e5e Avi Kivity
static uint64_t omap_l4ta_read(void *opaque, hwaddr addr,
56 3892f842 Benoît Canet
                               unsigned size)
57 2c1d9ecb cmchao
{
58 2c1d9ecb cmchao
    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
59 2c1d9ecb cmchao
60 3892f842 Benoît Canet
    if (size != 2) {
61 3892f842 Benoît Canet
        return omap_badwidth_read16(opaque, addr);
62 3892f842 Benoît Canet
    }
63 3892f842 Benoît Canet
64 2c1d9ecb cmchao
    switch (addr) {
65 2c1d9ecb cmchao
    case 0x00:        /* COMPONENT */
66 2c1d9ecb cmchao
        return s->component;
67 2c1d9ecb cmchao
68 2c1d9ecb cmchao
    case 0x20:        /* AGENT_CONTROL */
69 2c1d9ecb cmchao
        return s->control;
70 2c1d9ecb cmchao
71 2c1d9ecb cmchao
    case 0x28:        /* AGENT_STATUS */
72 2c1d9ecb cmchao
        return s->status;
73 2c1d9ecb cmchao
    }
74 2c1d9ecb cmchao
75 2c1d9ecb cmchao
    OMAP_BAD_REG(addr);
76 2c1d9ecb cmchao
    return 0;
77 2c1d9ecb cmchao
}
78 2c1d9ecb cmchao
79 a8170e5e Avi Kivity
static void omap_l4ta_write(void *opaque, hwaddr addr,
80 3892f842 Benoît Canet
                            uint64_t value, unsigned size)
81 2c1d9ecb cmchao
{
82 2c1d9ecb cmchao
    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
83 2c1d9ecb cmchao
84 3892f842 Benoît Canet
    if (size != 4) {
85 3892f842 Benoît Canet
        return omap_badwidth_write32(opaque, addr, value);
86 3892f842 Benoît Canet
    }
87 3892f842 Benoît Canet
88 2c1d9ecb cmchao
    switch (addr) {
89 2c1d9ecb cmchao
    case 0x00:        /* COMPONENT */
90 2c1d9ecb cmchao
    case 0x28:        /* AGENT_STATUS */
91 2c1d9ecb cmchao
        OMAP_RO_REG(addr);
92 2c1d9ecb cmchao
        break;
93 2c1d9ecb cmchao
94 2c1d9ecb cmchao
    case 0x20:        /* AGENT_CONTROL */
95 2c1d9ecb cmchao
        s->control = value & 0x01000700;
96 2c1d9ecb cmchao
        if (value & 1)                                        /* OCP_RESET */
97 2c1d9ecb cmchao
            s->status &= ~1;                                /* REQ_TIMEOUT */
98 2c1d9ecb cmchao
        break;
99 2c1d9ecb cmchao
100 2c1d9ecb cmchao
    default:
101 2c1d9ecb cmchao
        OMAP_BAD_REG(addr);
102 2c1d9ecb cmchao
    }
103 2c1d9ecb cmchao
}
104 2c1d9ecb cmchao
105 3892f842 Benoît Canet
static const MemoryRegionOps omap_l4ta_ops = {
106 3892f842 Benoît Canet
    .read = omap_l4ta_read,
107 3892f842 Benoît Canet
    .write = omap_l4ta_write,
108 3892f842 Benoît Canet
    .endianness = DEVICE_NATIVE_ENDIAN,
109 2c1d9ecb cmchao
};
110 2c1d9ecb cmchao
111 2c1d9ecb cmchao
struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus,
112 2c1d9ecb cmchao
        const struct omap_l4_region_s *regions,
113 2c1d9ecb cmchao
        const struct omap_l4_agent_info_s *agents,
114 2c1d9ecb cmchao
        int cs)
115 2c1d9ecb cmchao
{
116 3892f842 Benoît Canet
    int i;
117 2c1d9ecb cmchao
    struct omap_target_agent_s *ta = NULL;
118 2c1d9ecb cmchao
    const struct omap_l4_agent_info_s *info = NULL;
119 2c1d9ecb cmchao
120 2c1d9ecb cmchao
    for (i = 0; i < bus->ta_num; i ++)
121 2c1d9ecb cmchao
        if (agents[i].ta == cs) {
122 2c1d9ecb cmchao
            ta = &bus->ta[i];
123 2c1d9ecb cmchao
            info = &agents[i];
124 2c1d9ecb cmchao
            break;
125 2c1d9ecb cmchao
        }
126 2c1d9ecb cmchao
    if (!ta) {
127 2c1d9ecb cmchao
        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
128 2c1d9ecb cmchao
        exit(-1);
129 2c1d9ecb cmchao
    }
130 2c1d9ecb cmchao
131 2c1d9ecb cmchao
    ta->bus = bus;
132 2c1d9ecb cmchao
    ta->start = &regions[info->region];
133 2c1d9ecb cmchao
    ta->regions = info->regions;
134 2c1d9ecb cmchao
135 2c1d9ecb cmchao
    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
136 2c1d9ecb cmchao
    ta->status = 0x00000000;
137 2c1d9ecb cmchao
    ta->control = 0x00000200;        /* XXX 01000200 for L4TAO */
138 2c1d9ecb cmchao
139 3892f842 Benoît Canet
    memory_region_init_io(&ta->iomem, &omap_l4ta_ops, ta, "omap.l4ta",
140 3892f842 Benoît Canet
                          omap_l4_region_size(ta, info->ta_region));
141 f44336c5 Avi Kivity
    omap_l4_attach(ta, info->ta_region, &ta->iomem);
142 2c1d9ecb cmchao
143 2c1d9ecb cmchao
    return ta;
144 2c1d9ecb cmchao
}
145 2c1d9ecb cmchao
146 a8170e5e Avi Kivity
hwaddr omap_l4_attach(struct omap_target_agent_s *ta,
147 f3226149 Avi Kivity
                                         int region, MemoryRegion *mr)
148 f3226149 Avi Kivity
{
149 a8170e5e Avi Kivity
    hwaddr base;
150 f3226149 Avi Kivity
151 f3226149 Avi Kivity
    if (region < 0 || region >= ta->regions) {
152 f3226149 Avi Kivity
        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
153 f3226149 Avi Kivity
        exit(-1);
154 f3226149 Avi Kivity
    }
155 f3226149 Avi Kivity
156 f3226149 Avi Kivity
    base = ta->bus->base + ta->start[region].offset;
157 f3226149 Avi Kivity
    if (mr) {
158 f3226149 Avi Kivity
        memory_region_add_subregion(ta->bus->address_space, base, mr);
159 f3226149 Avi Kivity
    }
160 f3226149 Avi Kivity
161 f3226149 Avi Kivity
    return base;
162 f3226149 Avi Kivity
}