xref: /openbmc/qemu/hw/misc/lasi.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
1  /*
2   * HP-PARISC Lasi chipset emulation.
3   *
4   * (C) 2019 by Helge Deller <deller@gmx.de>
5   *
6   * This work is licensed under the GNU GPL license version 2 or later.
7   *
8   * Documentation available at:
9   * https://parisc.wiki.kernel.org/images-parisc/7/79/Lasi_ers.pdf
10   */
11  
12  #include "qemu/osdep.h"
13  #include "qemu/units.h"
14  #include "qemu/log.h"
15  #include "qapi/error.h"
16  #include "trace.h"
17  #include "hw/irq.h"
18  #include "sysemu/sysemu.h"
19  #include "sysemu/runstate.h"
20  #include "migration/vmstate.h"
21  #include "qom/object.h"
22  #include "hw/misc/lasi.h"
23  
24  
lasi_chip_mem_valid(void * opaque,hwaddr addr,unsigned size,bool is_write,MemTxAttrs attrs)25  static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
26                                  unsigned size, bool is_write,
27                                  MemTxAttrs attrs)
28  {
29      bool ret = false;
30  
31      switch (addr) {
32      case LASI_IRR:
33      case LASI_IMR:
34      case LASI_IPR:
35      case LASI_ICR:
36      case LASI_IAR:
37  
38      case LASI_LPT:
39      case LASI_AUDIO:
40      case LASI_AUDIO + 4:
41      case LASI_UART:
42      case LASI_LAN:
43      case LASI_LAN + 12: /* LASI LAN MAC */
44      case LASI_RTC:
45      case LASI_FDC:
46  
47      case LASI_PCR ... LASI_AMR:
48          ret = true;
49      }
50  
51      trace_lasi_chip_mem_valid(addr, ret);
52      return ret;
53  }
54  
lasi_chip_read_with_attrs(void * opaque,hwaddr addr,uint64_t * data,unsigned size,MemTxAttrs attrs)55  static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
56                                               uint64_t *data, unsigned size,
57                                               MemTxAttrs attrs)
58  {
59      LasiState *s = opaque;
60      MemTxResult ret = MEMTX_OK;
61      uint32_t val;
62  
63      switch (addr) {
64      case LASI_IRR:
65          val = s->irr;
66          break;
67      case LASI_IMR:
68          val = s->imr;
69          break;
70      case LASI_IPR:
71          val = s->ipr;
72          /* Any read to IPR clears the register.  */
73          s->ipr = 0;
74          break;
75      case LASI_ICR:
76          val = s->icr & ICR_BUS_ERROR_BIT; /* bus_error */
77          break;
78      case LASI_IAR:
79          val = s->iar;
80          break;
81  
82      case LASI_LPT:
83      case LASI_UART:
84      case LASI_LAN:
85      case LASI_LAN + 12:
86      case LASI_FDC:
87          val = 0;
88          break;
89      case LASI_RTC:
90          val = time(NULL);
91          val += s->rtc_ref;
92          break;
93  
94      case LASI_PCR:
95      case LASI_VER:      /* only version 0 existed. */
96      case LASI_IORESET:
97          val = 0;
98          break;
99      case LASI_ERRLOG:
100          val = s->errlog;
101          break;
102      case LASI_AMR:
103          val = s->amr;
104          break;
105  
106      default:
107          /* Controlled by lasi_chip_mem_valid above. */
108          g_assert_not_reached();
109      }
110  
111      trace_lasi_chip_read(addr, val);
112  
113      *data = val;
114      return ret;
115  }
116  
lasi_chip_write_with_attrs(void * opaque,hwaddr addr,uint64_t val,unsigned size,MemTxAttrs attrs)117  static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
118                                                uint64_t val, unsigned size,
119                                                MemTxAttrs attrs)
120  {
121      LasiState *s = opaque;
122  
123      trace_lasi_chip_write(addr, val);
124  
125      switch (addr) {
126      case LASI_IRR:
127          /* read-only.  */
128          break;
129      case LASI_IMR:
130          s->imr = val;
131          if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff)) {
132              qemu_log_mask(LOG_GUEST_ERROR,
133                  "LASI: tried to set invalid %lx IMR value.\n",
134                  (unsigned long) val);
135          }
136          break;
137      case LASI_IPR:
138          /* Any write to IPR clears the register. */
139          s->ipr = 0;
140          break;
141      case LASI_ICR:
142          s->icr = val;
143          /* if (val & ICR_TOC_BIT) issue_toc(); */
144          break;
145      case LASI_IAR:
146          s->iar = val;
147          break;
148  
149      case LASI_LPT:
150          /* XXX: reset parallel port */
151          break;
152      case LASI_AUDIO:
153      case LASI_AUDIO + 4:
154          /* XXX: reset audio port */
155          break;
156      case LASI_UART:
157          /* XXX: reset serial port */
158          break;
159      case LASI_LAN:
160          /* XXX: reset LAN card */
161          break;
162      case LASI_FDC:
163          /* XXX: reset Floppy controller */
164          break;
165      case LASI_RTC:
166          s->rtc_ref = val - time(NULL);
167          break;
168  
169      case LASI_PCR:
170          if (val == 0x02) { /* immediately power off */
171              qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
172          }
173          break;
174      case LASI_ERRLOG:
175          s->errlog = val;
176          break;
177      case LASI_VER:
178          /* read-only.  */
179          break;
180      case LASI_IORESET:
181          break;  /* XXX: TODO: Reset various devices. */
182      case LASI_AMR:
183          s->amr = val;
184          break;
185  
186      default:
187          /* Controlled by lasi_chip_mem_valid above. */
188          g_assert_not_reached();
189      }
190      return MEMTX_OK;
191  }
192  
193  static const MemoryRegionOps lasi_chip_ops = {
194      .read_with_attrs = lasi_chip_read_with_attrs,
195      .write_with_attrs = lasi_chip_write_with_attrs,
196      .endianness = DEVICE_BIG_ENDIAN,
197      .valid = {
198          .min_access_size = 1,
199          .max_access_size = 4,
200          .accepts = lasi_chip_mem_valid,
201      },
202      .impl = {
203          .min_access_size = 1,
204          .max_access_size = 4,
205      },
206  };
207  
208  static const VMStateDescription vmstate_lasi = {
209      .name = "Lasi",
210      .version_id = 2,
211      .minimum_version_id = 1,
212      .fields = (const VMStateField[]) {
213          VMSTATE_UINT32(irr, LasiState),
214          VMSTATE_UINT32(imr, LasiState),
215          VMSTATE_UINT32(ipr, LasiState),
216          VMSTATE_UINT32(icr, LasiState),
217          VMSTATE_UINT32(iar, LasiState),
218          VMSTATE_UINT32(errlog, LasiState),
219          VMSTATE_UINT32(amr, LasiState),
220          VMSTATE_UINT32_V(rtc_ref, LasiState, 2),
221          VMSTATE_END_OF_LIST()
222      }
223  };
224  
225  
lasi_set_irq(void * opaque,int irq,int level)226  static void lasi_set_irq(void *opaque, int irq, int level)
227  {
228      LasiState *s = opaque;
229      uint32_t bit = 1u << irq;
230  
231      if (level) {
232          s->ipr |= bit;
233          if (bit & s->imr) {
234              uint32_t iar = s->iar;
235              s->irr |= bit;
236              if ((s->icr & ICR_BUS_ERROR_BIT) == 0) {
237                  stl_be_phys(&address_space_memory, iar & -32, iar & 31);
238              }
239          }
240      }
241  }
242  
lasi_reset(DeviceState * dev)243  static void lasi_reset(DeviceState *dev)
244  {
245      LasiState *s = LASI_CHIP(dev);
246  
247      s->iar = 0xFFFB0000 + 3; /* CPU_HPA + 3 */
248  
249      /* Real time clock (RTC), it's only one 32-bit counter @9000 */
250      s->rtc_ref = 0;
251  }
252  
lasi_init(Object * obj)253  static void lasi_init(Object *obj)
254  {
255      LasiState *s = LASI_CHIP(obj);
256      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
257  
258      memory_region_init_io(&s->this_mem, OBJECT(s), &lasi_chip_ops,
259                            s, "lasi", 0x100000);
260  
261      sysbus_init_mmio(sbd, &s->this_mem);
262  
263      qdev_init_gpio_in(DEVICE(obj), lasi_set_irq, LASI_IRQS);
264  }
265  
lasi_class_init(ObjectClass * klass,void * data)266  static void lasi_class_init(ObjectClass *klass, void *data)
267  {
268      DeviceClass *dc = DEVICE_CLASS(klass);
269  
270      device_class_set_legacy_reset(dc, lasi_reset);
271      dc->vmsd = &vmstate_lasi;
272  }
273  
274  static const TypeInfo lasi_pcihost_info = {
275      .name          = TYPE_LASI_CHIP,
276      .parent        = TYPE_SYS_BUS_DEVICE,
277      .instance_init = lasi_init,
278      .instance_size = sizeof(LasiState),
279      .class_init    = lasi_class_init,
280  };
281  
lasi_register_types(void)282  static void lasi_register_types(void)
283  {
284      type_register_static(&lasi_pcihost_info);
285  }
286  
287  type_init(lasi_register_types)
288