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