omap_sdrc.c (4871B)
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 */ 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: /* SDRC_REVISION */ 45 return 0x20; 46 47 case 0x10: /* SDRC_SYSCONFIG */ 48 return s->config; 49 50 case 0x14: /* SDRC_SYSSTATUS */ 51 return 1; /* RESETDONE */ 52 53 case 0x40: /* SDRC_CS_CFG */ 54 case 0x44: /* SDRC_SHARING */ 55 case 0x48: /* SDRC_ERR_ADDR */ 56 case 0x4c: /* SDRC_ERR_TYPE */ 57 case 0x60: /* SDRC_DLLA_SCTRL */ 58 case 0x64: /* SDRC_DLLA_STATUS */ 59 case 0x68: /* SDRC_DLLB_CTRL */ 60 case 0x6c: /* SDRC_DLLB_STATUS */ 61 case 0x70: /* SDRC_POWER */ 62 case 0x80: /* SDRC_MCFG_0 */ 63 case 0x84: /* SDRC_MR_0 */ 64 case 0x88: /* SDRC_EMR1_0 */ 65 case 0x8c: /* SDRC_EMR2_0 */ 66 case 0x90: /* SDRC_EMR3_0 */ 67 case 0x94: /* SDRC_DCDL1_CTRL */ 68 case 0x98: /* SDRC_DCDL2_CTRL */ 69 case 0x9c: /* SDRC_ACTIM_CTRLA_0 */ 70 case 0xa0: /* SDRC_ACTIM_CTRLB_0 */ 71 case 0xa4: /* SDRC_RFR_CTRL_0 */ 72 case 0xa8: /* SDRC_MANUAL_0 */ 73 case 0xb0: /* SDRC_MCFG_1 */ 74 case 0xb4: /* SDRC_MR_1 */ 75 case 0xb8: /* SDRC_EMR1_1 */ 76 case 0xbc: /* SDRC_EMR2_1 */ 77 case 0xc0: /* SDRC_EMR3_1 */ 78 case 0xc4: /* SDRC_ACTIM_CTRLA_1 */ 79 case 0xc8: /* SDRC_ACTIM_CTRLB_1 */ 80 case 0xd4: /* SDRC_RFR_CTRL_1 */ 81 case 0xd8: /* SDRC_MANUAL_1 */ 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 omap_badwidth_write32(opaque, addr, value); 96 return; 97 } 98 99 switch (addr) { 100 case 0x00: /* SDRC_REVISION */ 101 case 0x14: /* SDRC_SYSSTATUS */ 102 case 0x48: /* SDRC_ERR_ADDR */ 103 case 0x64: /* SDRC_DLLA_STATUS */ 104 case 0x6c: /* SDRC_DLLB_STATUS */ 105 OMAP_RO_REG(addr); 106 return; 107 108 case 0x10: /* SDRC_SYSCONFIG */ 109 if ((value >> 3) != 0x2) 110 fprintf(stderr, "%s: bad SDRAM idle mode %i\n", 111 __func__, (unsigned)value >> 3); 112 if (value & 2) 113 omap_sdrc_reset(s); 114 s->config = value & 0x18; 115 break; 116 117 case 0x40: /* SDRC_CS_CFG */ 118 case 0x44: /* SDRC_SHARING */ 119 case 0x4c: /* SDRC_ERR_TYPE */ 120 case 0x60: /* SDRC_DLLA_SCTRL */ 121 case 0x68: /* SDRC_DLLB_CTRL */ 122 case 0x70: /* SDRC_POWER */ 123 case 0x80: /* SDRC_MCFG_0 */ 124 case 0x84: /* SDRC_MR_0 */ 125 case 0x88: /* SDRC_EMR1_0 */ 126 case 0x8c: /* SDRC_EMR2_0 */ 127 case 0x90: /* SDRC_EMR3_0 */ 128 case 0x94: /* SDRC_DCDL1_CTRL */ 129 case 0x98: /* SDRC_DCDL2_CTRL */ 130 case 0x9c: /* SDRC_ACTIM_CTRLA_0 */ 131 case 0xa0: /* SDRC_ACTIM_CTRLB_0 */ 132 case 0xa4: /* SDRC_RFR_CTRL_0 */ 133 case 0xa8: /* SDRC_MANUAL_0 */ 134 case 0xb0: /* SDRC_MCFG_1 */ 135 case 0xb4: /* SDRC_MR_1 */ 136 case 0xb8: /* SDRC_EMR1_1 */ 137 case 0xbc: /* SDRC_EMR2_1 */ 138 case 0xc0: /* SDRC_EMR3_1 */ 139 case 0xc4: /* SDRC_ACTIM_CTRLA_1 */ 140 case 0xc8: /* SDRC_ACTIM_CTRLB_1 */ 141 case 0xd4: /* SDRC_RFR_CTRL_1 */ 142 case 0xd8: /* SDRC_MANUAL_1 */ 143 break; 144 145 default: 146 OMAP_BAD_REG(addr); 147 return; 148 } 149} 150 151static const MemoryRegionOps omap_sdrc_ops = { 152 .read = omap_sdrc_read, 153 .write = omap_sdrc_write, 154 .endianness = DEVICE_NATIVE_ENDIAN, 155}; 156 157struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem, 158 hwaddr base) 159{ 160 struct omap_sdrc_s *s = g_new0(struct omap_sdrc_s, 1); 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}