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