1 /* 2 * Copyright (c) 2006-2008 Openedhand Ltd. 3 * Written by Andrzej Zaborowski <balrog@zabor.org> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 or 8 * (at your option) version 3 of the License. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 #include "hw/hw.h" 19 #include "hw/arm/sharpsl.h" 20 #include "hw/sysbus.h" 21 22 #undef REG_FMT 23 #define REG_FMT "0x%02lx" 24 25 /* SCOOP devices */ 26 27 #define TYPE_SCOOP "scoop" 28 #define SCOOP(obj) OBJECT_CHECK(ScoopInfo, (obj), TYPE_SCOOP) 29 30 typedef struct ScoopInfo ScoopInfo; 31 struct ScoopInfo { 32 SysBusDevice parent_obj; 33 34 qemu_irq handler[16]; 35 MemoryRegion iomem; 36 uint16_t status; 37 uint16_t power; 38 uint32_t gpio_level; 39 uint32_t gpio_dir; 40 uint32_t prev_level; 41 42 uint16_t mcr; 43 uint16_t cdr; 44 uint16_t ccr; 45 uint16_t irr; 46 uint16_t imr; 47 uint16_t isr; 48 }; 49 50 #define SCOOP_MCR 0x00 51 #define SCOOP_CDR 0x04 52 #define SCOOP_CSR 0x08 53 #define SCOOP_CPR 0x0c 54 #define SCOOP_CCR 0x10 55 #define SCOOP_IRR_IRM 0x14 56 #define SCOOP_IMR 0x18 57 #define SCOOP_ISR 0x1c 58 #define SCOOP_GPCR 0x20 59 #define SCOOP_GPWR 0x24 60 #define SCOOP_GPRR 0x28 61 62 static inline void scoop_gpio_handler_update(ScoopInfo *s) { 63 uint32_t level, diff; 64 int bit; 65 level = s->gpio_level & s->gpio_dir; 66 67 for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { 68 bit = ctz32(diff); 69 qemu_set_irq(s->handler[bit], (level >> bit) & 1); 70 } 71 72 s->prev_level = level; 73 } 74 75 static uint64_t scoop_read(void *opaque, hwaddr addr, 76 unsigned size) 77 { 78 ScoopInfo *s = (ScoopInfo *) opaque; 79 80 switch (addr & 0x3f) { 81 case SCOOP_MCR: 82 return s->mcr; 83 case SCOOP_CDR: 84 return s->cdr; 85 case SCOOP_CSR: 86 return s->status; 87 case SCOOP_CPR: 88 return s->power; 89 case SCOOP_CCR: 90 return s->ccr; 91 case SCOOP_IRR_IRM: 92 return s->irr; 93 case SCOOP_IMR: 94 return s->imr; 95 case SCOOP_ISR: 96 return s->isr; 97 case SCOOP_GPCR: 98 return s->gpio_dir; 99 case SCOOP_GPWR: 100 case SCOOP_GPRR: 101 return s->gpio_level; 102 default: 103 zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); 104 } 105 106 return 0; 107 } 108 109 static void scoop_write(void *opaque, hwaddr addr, 110 uint64_t value, unsigned size) 111 { 112 ScoopInfo *s = (ScoopInfo *) opaque; 113 value &= 0xffff; 114 115 switch (addr & 0x3f) { 116 case SCOOP_MCR: 117 s->mcr = value; 118 break; 119 case SCOOP_CDR: 120 s->cdr = value; 121 break; 122 case SCOOP_CPR: 123 s->power = value; 124 if (value & 0x80) 125 s->power |= 0x8040; 126 break; 127 case SCOOP_CCR: 128 s->ccr = value; 129 break; 130 case SCOOP_IRR_IRM: 131 s->irr = value; 132 break; 133 case SCOOP_IMR: 134 s->imr = value; 135 break; 136 case SCOOP_ISR: 137 s->isr = value; 138 break; 139 case SCOOP_GPCR: 140 s->gpio_dir = value; 141 scoop_gpio_handler_update(s); 142 break; 143 case SCOOP_GPWR: 144 case SCOOP_GPRR: /* GPRR is probably R/O in real HW */ 145 s->gpio_level = value & s->gpio_dir; 146 scoop_gpio_handler_update(s); 147 break; 148 default: 149 zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); 150 } 151 } 152 153 static const MemoryRegionOps scoop_ops = { 154 .read = scoop_read, 155 .write = scoop_write, 156 .endianness = DEVICE_NATIVE_ENDIAN, 157 }; 158 159 static void scoop_gpio_set(void *opaque, int line, int level) 160 { 161 ScoopInfo *s = (ScoopInfo *) opaque; 162 163 if (level) 164 s->gpio_level |= (1 << line); 165 else 166 s->gpio_level &= ~(1 << line); 167 } 168 169 static int scoop_init(SysBusDevice *sbd) 170 { 171 DeviceState *dev = DEVICE(sbd); 172 ScoopInfo *s = SCOOP(dev); 173 174 s->status = 0x02; 175 qdev_init_gpio_out(dev, s->handler, 16); 176 qdev_init_gpio_in(dev, scoop_gpio_set, 16); 177 memory_region_init_io(&s->iomem, OBJECT(s), &scoop_ops, s, "scoop", 0x1000); 178 179 sysbus_init_mmio(sbd, &s->iomem); 180 181 return 0; 182 } 183 184 static int scoop_post_load(void *opaque, int version_id) 185 { 186 ScoopInfo *s = (ScoopInfo *) opaque; 187 int i; 188 uint32_t level; 189 190 level = s->gpio_level & s->gpio_dir; 191 192 for (i = 0; i < 16; i++) { 193 qemu_set_irq(s->handler[i], (level >> i) & 1); 194 } 195 196 s->prev_level = level; 197 198 return 0; 199 } 200 201 static bool is_version_0 (void *opaque, int version_id) 202 { 203 return version_id == 0; 204 } 205 206 static bool vmstate_scoop_validate(void *opaque, int version_id) 207 { 208 ScoopInfo *s = opaque; 209 210 return !(s->prev_level & 0xffff0000) && 211 !(s->gpio_level & 0xffff0000) && 212 !(s->gpio_dir & 0xffff0000); 213 } 214 215 static const VMStateDescription vmstate_scoop_regs = { 216 .name = "scoop", 217 .version_id = 1, 218 .minimum_version_id = 0, 219 .post_load = scoop_post_load, 220 .fields = (VMStateField[]) { 221 VMSTATE_UINT16(status, ScoopInfo), 222 VMSTATE_UINT16(power, ScoopInfo), 223 VMSTATE_UINT32(gpio_level, ScoopInfo), 224 VMSTATE_UINT32(gpio_dir, ScoopInfo), 225 VMSTATE_UINT32(prev_level, ScoopInfo), 226 VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate), 227 VMSTATE_UINT16(mcr, ScoopInfo), 228 VMSTATE_UINT16(cdr, ScoopInfo), 229 VMSTATE_UINT16(ccr, ScoopInfo), 230 VMSTATE_UINT16(irr, ScoopInfo), 231 VMSTATE_UINT16(imr, ScoopInfo), 232 VMSTATE_UINT16(isr, ScoopInfo), 233 VMSTATE_UNUSED_TEST(is_version_0, 2), 234 VMSTATE_END_OF_LIST(), 235 }, 236 }; 237 238 static void scoop_sysbus_class_init(ObjectClass *klass, void *data) 239 { 240 DeviceClass *dc = DEVICE_CLASS(klass); 241 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 242 243 k->init = scoop_init; 244 dc->desc = "Scoop2 Sharp custom ASIC"; 245 dc->vmsd = &vmstate_scoop_regs; 246 } 247 248 static const TypeInfo scoop_sysbus_info = { 249 .name = TYPE_SCOOP, 250 .parent = TYPE_SYS_BUS_DEVICE, 251 .instance_size = sizeof(ScoopInfo), 252 .class_init = scoop_sysbus_class_init, 253 }; 254 255 static void scoop_register_types(void) 256 { 257 type_register_static(&scoop_sysbus_info); 258 } 259 260 type_init(scoop_register_types) 261 262 /* Write the bootloader parameters memory area. */ 263 264 #define MAGIC_CHG(a, b, c, d) ((d << 24) | (c << 16) | (b << 8) | a) 265 266 static struct QEMU_PACKED sl_param_info { 267 uint32_t comadj_keyword; 268 int32_t comadj; 269 270 uint32_t uuid_keyword; 271 char uuid[16]; 272 273 uint32_t touch_keyword; 274 int32_t touch_xp; 275 int32_t touch_yp; 276 int32_t touch_xd; 277 int32_t touch_yd; 278 279 uint32_t adadj_keyword; 280 int32_t adadj; 281 282 uint32_t phad_keyword; 283 int32_t phadadj; 284 } zaurus_bootparam = { 285 .comadj_keyword = MAGIC_CHG('C', 'M', 'A', 'D'), 286 .comadj = 125, 287 .uuid_keyword = MAGIC_CHG('U', 'U', 'I', 'D'), 288 .uuid = { -1 }, 289 .touch_keyword = MAGIC_CHG('T', 'U', 'C', 'H'), 290 .touch_xp = -1, 291 .adadj_keyword = MAGIC_CHG('B', 'V', 'A', 'D'), 292 .adadj = -1, 293 .phad_keyword = MAGIC_CHG('P', 'H', 'A', 'D'), 294 .phadadj = 0x01, 295 }; 296 297 void sl_bootparam_write(hwaddr ptr) 298 { 299 cpu_physical_memory_write(ptr, &zaurus_bootparam, 300 sizeof(struct sl_param_info)); 301 } 302