1 /* 2 * TI OMAP SDRAM controller emulation. 3 * 4 * Copyright (C) 2007-2008 Nokia Corporation 5 * Written by Andrzej Zaborowski <andrew@openedhand.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 or 10 * (at your option) any later version of the License. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 #include "qemu/osdep.h" 21 #include "hw/hw.h" 22 #include "hw/arm/omap.h" 23 24 /* SDRAM Controller Subsystem */ 25 struct omap_sdrc_s { 26 MemoryRegion iomem; 27 uint8_t config; 28 }; 29 30 void omap_sdrc_reset(struct omap_sdrc_s *s) 31 { 32 s->config = 0x10; 33 } 34 35 static 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: /* SDRC_REVISION */ 46 return 0x20; 47 48 case 0x10: /* SDRC_SYSCONFIG */ 49 return s->config; 50 51 case 0x14: /* SDRC_SYSSTATUS */ 52 return 1; /* RESETDONE */ 53 54 case 0x40: /* SDRC_CS_CFG */ 55 case 0x44: /* SDRC_SHARING */ 56 case 0x48: /* SDRC_ERR_ADDR */ 57 case 0x4c: /* SDRC_ERR_TYPE */ 58 case 0x60: /* SDRC_DLLA_SCTRL */ 59 case 0x64: /* SDRC_DLLA_STATUS */ 60 case 0x68: /* SDRC_DLLB_CTRL */ 61 case 0x6c: /* SDRC_DLLB_STATUS */ 62 case 0x70: /* SDRC_POWER */ 63 case 0x80: /* SDRC_MCFG_0 */ 64 case 0x84: /* SDRC_MR_0 */ 65 case 0x88: /* SDRC_EMR1_0 */ 66 case 0x8c: /* SDRC_EMR2_0 */ 67 case 0x90: /* SDRC_EMR3_0 */ 68 case 0x94: /* SDRC_DCDL1_CTRL */ 69 case 0x98: /* SDRC_DCDL2_CTRL */ 70 case 0x9c: /* SDRC_ACTIM_CTRLA_0 */ 71 case 0xa0: /* SDRC_ACTIM_CTRLB_0 */ 72 case 0xa4: /* SDRC_RFR_CTRL_0 */ 73 case 0xa8: /* SDRC_MANUAL_0 */ 74 case 0xb0: /* SDRC_MCFG_1 */ 75 case 0xb4: /* SDRC_MR_1 */ 76 case 0xb8: /* SDRC_EMR1_1 */ 77 case 0xbc: /* SDRC_EMR2_1 */ 78 case 0xc0: /* SDRC_EMR3_1 */ 79 case 0xc4: /* SDRC_ACTIM_CTRLA_1 */ 80 case 0xc8: /* SDRC_ACTIM_CTRLB_1 */ 81 case 0xd4: /* SDRC_RFR_CTRL_1 */ 82 case 0xd8: /* SDRC_MANUAL_1 */ 83 return 0x00; 84 } 85 86 OMAP_BAD_REG(addr); 87 return 0; 88 } 89 90 static 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: /* SDRC_REVISION */ 102 case 0x14: /* SDRC_SYSSTATUS */ 103 case 0x48: /* SDRC_ERR_ADDR */ 104 case 0x64: /* SDRC_DLLA_STATUS */ 105 case 0x6c: /* SDRC_DLLB_STATUS */ 106 OMAP_RO_REG(addr); 107 return; 108 109 case 0x10: /* SDRC_SYSCONFIG */ 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: /* SDRC_CS_CFG */ 119 case 0x44: /* SDRC_SHARING */ 120 case 0x4c: /* SDRC_ERR_TYPE */ 121 case 0x60: /* SDRC_DLLA_SCTRL */ 122 case 0x68: /* SDRC_DLLB_CTRL */ 123 case 0x70: /* SDRC_POWER */ 124 case 0x80: /* SDRC_MCFG_0 */ 125 case 0x84: /* SDRC_MR_0 */ 126 case 0x88: /* SDRC_EMR1_0 */ 127 case 0x8c: /* SDRC_EMR2_0 */ 128 case 0x90: /* SDRC_EMR3_0 */ 129 case 0x94: /* SDRC_DCDL1_CTRL */ 130 case 0x98: /* SDRC_DCDL2_CTRL */ 131 case 0x9c: /* SDRC_ACTIM_CTRLA_0 */ 132 case 0xa0: /* SDRC_ACTIM_CTRLB_0 */ 133 case 0xa4: /* SDRC_RFR_CTRL_0 */ 134 case 0xa8: /* SDRC_MANUAL_0 */ 135 case 0xb0: /* SDRC_MCFG_1 */ 136 case 0xb4: /* SDRC_MR_1 */ 137 case 0xb8: /* SDRC_EMR1_1 */ 138 case 0xbc: /* SDRC_EMR2_1 */ 139 case 0xc0: /* SDRC_EMR3_1 */ 140 case 0xc4: /* SDRC_ACTIM_CTRLA_1 */ 141 case 0xc8: /* SDRC_ACTIM_CTRLB_1 */ 142 case 0xd4: /* SDRC_RFR_CTRL_1 */ 143 case 0xd8: /* SDRC_MANUAL_1 */ 144 break; 145 146 default: 147 OMAP_BAD_REG(addr); 148 return; 149 } 150 } 151 152 static const MemoryRegionOps omap_sdrc_ops = { 153 .read = omap_sdrc_read, 154 .write = omap_sdrc_write, 155 .endianness = DEVICE_NATIVE_ENDIAN, 156 }; 157 158 struct 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