allwinner-h3-sysctrl.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Allwinner H3 System Control emulation
  3. *
  4. * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "qemu/osdep.h"
  20. #include "qemu/units.h"
  21. #include "hw/sysbus.h"
  22. #include "migration/vmstate.h"
  23. #include "qemu/log.h"
  24. #include "qemu/module.h"
  25. #include "hw/misc/allwinner-h3-sysctrl.h"
  26. /* System Control register offsets */
  27. enum {
  28. REG_VER = 0x24, /* Version */
  29. REG_EMAC_PHY_CLK = 0x30, /* EMAC PHY Clock */
  30. };
  31. #define REG_INDEX(offset) (offset / sizeof(uint32_t))
  32. /* System Control register reset values */
  33. enum {
  34. REG_VER_RST = 0x0,
  35. REG_EMAC_PHY_CLK_RST = 0x58000,
  36. };
  37. static uint64_t allwinner_h3_sysctrl_read(void *opaque, hwaddr offset,
  38. unsigned size)
  39. {
  40. const AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
  41. const uint32_t idx = REG_INDEX(offset);
  42. if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
  43. qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
  44. __func__, (uint32_t)offset);
  45. return 0;
  46. }
  47. return s->regs[idx];
  48. }
  49. static void allwinner_h3_sysctrl_write(void *opaque, hwaddr offset,
  50. uint64_t val, unsigned size)
  51. {
  52. AwH3SysCtrlState *s = AW_H3_SYSCTRL(opaque);
  53. const uint32_t idx = REG_INDEX(offset);
  54. if (idx >= AW_H3_SYSCTRL_REGS_NUM) {
  55. qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
  56. __func__, (uint32_t)offset);
  57. return;
  58. }
  59. switch (offset) {
  60. case REG_VER: /* Version */
  61. break;
  62. default:
  63. s->regs[idx] = (uint32_t) val;
  64. break;
  65. }
  66. }
  67. static const MemoryRegionOps allwinner_h3_sysctrl_ops = {
  68. .read = allwinner_h3_sysctrl_read,
  69. .write = allwinner_h3_sysctrl_write,
  70. .endianness = DEVICE_LITTLE_ENDIAN,
  71. .valid = {
  72. .min_access_size = 4,
  73. .max_access_size = 4,
  74. },
  75. .impl.min_access_size = 4,
  76. };
  77. static void allwinner_h3_sysctrl_reset(DeviceState *dev)
  78. {
  79. AwH3SysCtrlState *s = AW_H3_SYSCTRL(dev);
  80. /* Set default values for registers */
  81. s->regs[REG_INDEX(REG_VER)] = REG_VER_RST;
  82. s->regs[REG_INDEX(REG_EMAC_PHY_CLK)] = REG_EMAC_PHY_CLK_RST;
  83. }
  84. static void allwinner_h3_sysctrl_init(Object *obj)
  85. {
  86. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  87. AwH3SysCtrlState *s = AW_H3_SYSCTRL(obj);
  88. /* Memory mapping */
  89. memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_h3_sysctrl_ops, s,
  90. TYPE_AW_H3_SYSCTRL, 4 * KiB);
  91. sysbus_init_mmio(sbd, &s->iomem);
  92. }
  93. static const VMStateDescription allwinner_h3_sysctrl_vmstate = {
  94. .name = "allwinner-h3-sysctrl",
  95. .version_id = 1,
  96. .minimum_version_id = 1,
  97. .fields = (const VMStateField[]) {
  98. VMSTATE_UINT32_ARRAY(regs, AwH3SysCtrlState, AW_H3_SYSCTRL_REGS_NUM),
  99. VMSTATE_END_OF_LIST()
  100. }
  101. };
  102. static void allwinner_h3_sysctrl_class_init(ObjectClass *klass, void *data)
  103. {
  104. DeviceClass *dc = DEVICE_CLASS(klass);
  105. device_class_set_legacy_reset(dc, allwinner_h3_sysctrl_reset);
  106. dc->vmsd = &allwinner_h3_sysctrl_vmstate;
  107. }
  108. static const TypeInfo allwinner_h3_sysctrl_info = {
  109. .name = TYPE_AW_H3_SYSCTRL,
  110. .parent = TYPE_SYS_BUS_DEVICE,
  111. .instance_init = allwinner_h3_sysctrl_init,
  112. .instance_size = sizeof(AwH3SysCtrlState),
  113. .class_init = allwinner_h3_sysctrl_class_init,
  114. };
  115. static void allwinner_h3_sysctrl_register(void)
  116. {
  117. type_register_static(&allwinner_h3_sysctrl_info);
  118. }
  119. type_init(allwinner_h3_sysctrl_register)