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.h" 19 #include "pxa.h" 20 #include "sharpsl.h" 21 22 #undef REG_FMT 23 #define REG_FMT "0x%02lx" 24 25 /* SCOOP devices */ 26 27 struct ScoopInfo { 28 qemu_irq handler[16]; 29 qemu_irq *in; 30 uint16_t status; 31 uint16_t power; 32 uint32_t gpio_level; 33 uint32_t gpio_dir; 34 uint32_t prev_level; 35 36 uint16_t mcr; 37 uint16_t cdr; 38 uint16_t ccr; 39 uint16_t irr; 40 uint16_t imr; 41 uint16_t isr; 42 }; 43 44 #define SCOOP_MCR 0x00 45 #define SCOOP_CDR 0x04 46 #define SCOOP_CSR 0x08 47 #define SCOOP_CPR 0x0c 48 #define SCOOP_CCR 0x10 49 #define SCOOP_IRR_IRM 0x14 50 #define SCOOP_IMR 0x18 51 #define SCOOP_ISR 0x1c 52 #define SCOOP_GPCR 0x20 53 #define SCOOP_GPWR 0x24 54 #define SCOOP_GPRR 0x28 55 56 static inline void scoop_gpio_handler_update(ScoopInfo *s) { 57 uint32_t level, diff; 58 int bit; 59 level = s->gpio_level & s->gpio_dir; 60 61 for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { 62 bit = ffs(diff) - 1; 63 qemu_set_irq(s->handler[bit], (level >> bit) & 1); 64 } 65 66 s->prev_level = level; 67 } 68 69 static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr) 70 { 71 ScoopInfo *s = (ScoopInfo *) opaque; 72 73 switch (addr) { 74 case SCOOP_MCR: 75 return s->mcr; 76 case SCOOP_CDR: 77 return s->cdr; 78 case SCOOP_CSR: 79 return s->status; 80 case SCOOP_CPR: 81 return s->power; 82 case SCOOP_CCR: 83 return s->ccr; 84 case SCOOP_IRR_IRM: 85 return s->irr; 86 case SCOOP_IMR: 87 return s->imr; 88 case SCOOP_ISR: 89 return s->isr; 90 case SCOOP_GPCR: 91 return s->gpio_dir; 92 case SCOOP_GPWR: 93 case SCOOP_GPRR: 94 return s->gpio_level; 95 default: 96 zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); 97 } 98 99 return 0; 100 } 101 102 static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value) 103 { 104 ScoopInfo *s = (ScoopInfo *) opaque; 105 value &= 0xffff; 106 107 switch (addr) { 108 case SCOOP_MCR: 109 s->mcr = value; 110 break; 111 case SCOOP_CDR: 112 s->cdr = value; 113 break; 114 case SCOOP_CPR: 115 s->power = value; 116 if (value & 0x80) 117 s->power |= 0x8040; 118 break; 119 case SCOOP_CCR: 120 s->ccr = value; 121 break; 122 case SCOOP_IRR_IRM: 123 s->irr = value; 124 break; 125 case SCOOP_IMR: 126 s->imr = value; 127 break; 128 case SCOOP_ISR: 129 s->isr = value; 130 break; 131 case SCOOP_GPCR: 132 s->gpio_dir = value; 133 scoop_gpio_handler_update(s); 134 break; 135 case SCOOP_GPWR: 136 case SCOOP_GPRR: /* GPRR is probably R/O in real HW */ 137 s->gpio_level = value & s->gpio_dir; 138 scoop_gpio_handler_update(s); 139 break; 140 default: 141 zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); 142 } 143 } 144 145 static CPUReadMemoryFunc * const scoop_readfn[] = { 146 scoop_readb, 147 scoop_readb, 148 scoop_readb, 149 }; 150 static CPUWriteMemoryFunc * const scoop_writefn[] = { 151 scoop_writeb, 152 scoop_writeb, 153 scoop_writeb, 154 }; 155 156 void scoop_gpio_set(void *opaque, int line, int level) 157 { 158 ScoopInfo *s = (ScoopInfo *) opaque; 159 160 if (level) 161 s->gpio_level |= (1 << line); 162 else 163 s->gpio_level &= ~(1 << line); 164 } 165 166 qemu_irq *scoop_gpio_in_get(ScoopInfo *s) 167 { 168 return s->in; 169 } 170 171 void scoop_gpio_out_set(ScoopInfo *s, int line, 172 qemu_irq handler) { 173 if (line >= 16) { 174 fprintf(stderr, "No GPIO pin %i\n", line); 175 exit(-1); 176 } 177 178 s->handler[line] = handler; 179 } 180 181 static void scoop_save(QEMUFile *f, void *opaque) 182 { 183 ScoopInfo *s = (ScoopInfo *) opaque; 184 qemu_put_be16s(f, &s->status); 185 qemu_put_be16s(f, &s->power); 186 qemu_put_be32s(f, &s->gpio_level); 187 qemu_put_be32s(f, &s->gpio_dir); 188 qemu_put_be32s(f, &s->prev_level); 189 qemu_put_be16s(f, &s->mcr); 190 qemu_put_be16s(f, &s->cdr); 191 qemu_put_be16s(f, &s->ccr); 192 qemu_put_be16s(f, &s->irr); 193 qemu_put_be16s(f, &s->imr); 194 qemu_put_be16s(f, &s->isr); 195 } 196 197 static int scoop_load(QEMUFile *f, void *opaque, int version_id) 198 { 199 uint16_t dummy; 200 ScoopInfo *s = (ScoopInfo *) opaque; 201 qemu_get_be16s(f, &s->status); 202 qemu_get_be16s(f, &s->power); 203 qemu_get_be32s(f, &s->gpio_level); 204 qemu_get_be32s(f, &s->gpio_dir); 205 qemu_get_be32s(f, &s->prev_level); 206 qemu_get_be16s(f, &s->mcr); 207 qemu_get_be16s(f, &s->cdr); 208 qemu_get_be16s(f, &s->ccr); 209 qemu_get_be16s(f, &s->irr); 210 qemu_get_be16s(f, &s->imr); 211 qemu_get_be16s(f, &s->isr); 212 if (version_id < 1) 213 qemu_get_be16s(f, &dummy); 214 215 return 0; 216 } 217 218 ScoopInfo *scoop_init(PXA2xxState *cpu, 219 int instance, 220 target_phys_addr_t target_base) { 221 int iomemtype; 222 ScoopInfo *s; 223 224 s = (ScoopInfo *) 225 qemu_mallocz(sizeof(ScoopInfo)); 226 memset(s, 0, sizeof(ScoopInfo)); 227 228 s->status = 0x02; 229 s->in = qemu_allocate_irqs(scoop_gpio_set, s, 16); 230 iomemtype = cpu_register_io_memory(scoop_readfn, 231 scoop_writefn, s, DEVICE_NATIVE_ENDIAN); 232 cpu_register_physical_memory(target_base, 0x1000, iomemtype); 233 register_savevm(NULL, "scoop", instance, 1, scoop_save, scoop_load, s); 234 235 return s; 236 } 237 238 /* Write the bootloader parameters memory area. */ 239 240 #define MAGIC_CHG(a, b, c, d) ((d << 24) | (c << 16) | (b << 8) | a) 241 242 static struct __attribute__ ((__packed__)) sl_param_info { 243 uint32_t comadj_keyword; 244 int32_t comadj; 245 246 uint32_t uuid_keyword; 247 char uuid[16]; 248 249 uint32_t touch_keyword; 250 int32_t touch_xp; 251 int32_t touch_yp; 252 int32_t touch_xd; 253 int32_t touch_yd; 254 255 uint32_t adadj_keyword; 256 int32_t adadj; 257 258 uint32_t phad_keyword; 259 int32_t phadadj; 260 } zaurus_bootparam = { 261 .comadj_keyword = MAGIC_CHG('C', 'M', 'A', 'D'), 262 .comadj = 125, 263 .uuid_keyword = MAGIC_CHG('U', 'U', 'I', 'D'), 264 .uuid = { -1 }, 265 .touch_keyword = MAGIC_CHG('T', 'U', 'C', 'H'), 266 .touch_xp = -1, 267 .adadj_keyword = MAGIC_CHG('B', 'V', 'A', 'D'), 268 .adadj = -1, 269 .phad_keyword = MAGIC_CHG('P', 'H', 'A', 'D'), 270 .phadadj = 0x01, 271 }; 272 273 void sl_bootparam_write(target_phys_addr_t ptr) 274 { 275 cpu_physical_memory_write(ptr, (void *)&zaurus_bootparam, 276 sizeof(struct sl_param_info)); 277 } 278