1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "hw/hw.h"
22#include "hw/arm/omap.h"
23
24
25struct omap_sdrc_s {
26 MemoryRegion iomem;
27 uint8_t config;
28};
29
30void omap_sdrc_reset(struct omap_sdrc_s *s)
31{
32 s->config = 0x10;
33}
34
35static uint64_t omap_sdrc_read(void *opaque, hwaddr addr,
36 unsigned size)
37{
38 struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
39
40 if (size != 4) {
41 return omap_badwidth_read32(opaque, addr);
42 }
43
44 switch (addr) {
45 case 0x00:
46 return 0x20;
47
48 case 0x10:
49 return s->config;
50
51 case 0x14:
52 return 1;
53
54 case 0x40:
55 case 0x44:
56 case 0x48:
57 case 0x4c:
58 case 0x60:
59 case 0x64:
60 case 0x68:
61 case 0x6c:
62 case 0x70:
63 case 0x80:
64 case 0x84:
65 case 0x88:
66 case 0x8c:
67 case 0x90:
68 case 0x94:
69 case 0x98:
70 case 0x9c:
71 case 0xa0:
72 case 0xa4:
73 case 0xa8:
74 case 0xb0:
75 case 0xb4:
76 case 0xb8:
77 case 0xbc:
78 case 0xc0:
79 case 0xc4:
80 case 0xc8:
81 case 0xd4:
82 case 0xd8:
83 return 0x00;
84 }
85
86 OMAP_BAD_REG(addr);
87 return 0;
88}
89
90static void omap_sdrc_write(void *opaque, hwaddr addr,
91 uint64_t value, unsigned size)
92{
93 struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
94
95 if (size != 4) {
96 omap_badwidth_write32(opaque, addr, value);
97 return;
98 }
99
100 switch (addr) {
101 case 0x00:
102 case 0x14:
103 case 0x48:
104 case 0x64:
105 case 0x6c:
106 OMAP_RO_REG(addr);
107 return;
108
109 case 0x10:
110 if ((value >> 3) != 0x2)
111 fprintf(stderr, "%s: bad SDRAM idle mode %i\n",
112 __func__, (unsigned)value >> 3);
113 if (value & 2)
114 omap_sdrc_reset(s);
115 s->config = value & 0x18;
116 break;
117
118 case 0x40:
119 case 0x44:
120 case 0x4c:
121 case 0x60:
122 case 0x68:
123 case 0x70:
124 case 0x80:
125 case 0x84:
126 case 0x88:
127 case 0x8c:
128 case 0x90:
129 case 0x94:
130 case 0x98:
131 case 0x9c:
132 case 0xa0:
133 case 0xa4:
134 case 0xa8:
135 case 0xb0:
136 case 0xb4:
137 case 0xb8:
138 case 0xbc:
139 case 0xc0:
140 case 0xc4:
141 case 0xc8:
142 case 0xd4:
143 case 0xd8:
144 break;
145
146 default:
147 OMAP_BAD_REG(addr);
148 return;
149 }
150}
151
152static const MemoryRegionOps omap_sdrc_ops = {
153 .read = omap_sdrc_read,
154 .write = omap_sdrc_write,
155 .endianness = DEVICE_NATIVE_ENDIAN,
156};
157
158struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem,
159 hwaddr base)
160{
161 struct omap_sdrc_s *s = g_new0(struct omap_sdrc_s, 1);
162
163 omap_sdrc_reset(s);
164
165 memory_region_init_io(&s->iomem, NULL, &omap_sdrc_ops, s, "omap.sdrc", 0x1000);
166 memory_region_add_subregion(sysmem, base, &s->iomem);
167
168 return s;
169}
170