fsl-imx25.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
  3. *
  4. * i.MX25 SOC emulation.
  5. *
  6. * Based on hw/arm/xlnx-zynqmp.c
  7. *
  8. * Copyright (C) 2015 Xilinx Inc
  9. * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify it
  12. * under the terms of the GNU General Public License as published by the
  13. * Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful, but WITHOUT
  17. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  18. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  19. * for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, see <http://www.gnu.org/licenses/>.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "qapi/error.h"
  26. #include "cpu.h"
  27. #include "hw/arm/fsl-imx25.h"
  28. #include "sysemu/sysemu.h"
  29. #include "exec/address-spaces.h"
  30. #include "hw/qdev-properties.h"
  31. #include "chardev/char.h"
  32. static void fsl_imx25_init(Object *obj)
  33. {
  34. FslIMX25State *s = FSL_IMX25(obj);
  35. int i;
  36. object_initialize_child(obj, "cpu", &s->cpu, sizeof(s->cpu),
  37. ARM_CPU_TYPE_NAME("arm926"),
  38. &error_abort, NULL);
  39. sysbus_init_child_obj(obj, "avic", &s->avic, sizeof(s->avic),
  40. TYPE_IMX_AVIC);
  41. sysbus_init_child_obj(obj, "ccm", &s->ccm, sizeof(s->ccm), TYPE_IMX25_CCM);
  42. for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
  43. sysbus_init_child_obj(obj, "uart[*]", &s->uart[i], sizeof(s->uart[i]),
  44. TYPE_IMX_SERIAL);
  45. }
  46. for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
  47. sysbus_init_child_obj(obj, "gpt[*]", &s->gpt[i], sizeof(s->gpt[i]),
  48. TYPE_IMX25_GPT);
  49. }
  50. for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
  51. sysbus_init_child_obj(obj, "epit[*]", &s->epit[i], sizeof(s->epit[i]),
  52. TYPE_IMX_EPIT);
  53. }
  54. sysbus_init_child_obj(obj, "fec", &s->fec, sizeof(s->fec), TYPE_IMX_FEC);
  55. for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
  56. sysbus_init_child_obj(obj, "i2c[*]", &s->i2c[i], sizeof(s->i2c[i]),
  57. TYPE_IMX_I2C);
  58. }
  59. for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
  60. sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]),
  61. TYPE_IMX_GPIO);
  62. }
  63. }
  64. static void fsl_imx25_realize(DeviceState *dev, Error **errp)
  65. {
  66. FslIMX25State *s = FSL_IMX25(dev);
  67. uint8_t i;
  68. Error *err = NULL;
  69. object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
  70. if (err) {
  71. error_propagate(errp, err);
  72. return;
  73. }
  74. object_property_set_bool(OBJECT(&s->avic), true, "realized", &err);
  75. if (err) {
  76. error_propagate(errp, err);
  77. return;
  78. }
  79. sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, FSL_IMX25_AVIC_ADDR);
  80. sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
  81. qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
  82. sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
  83. qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
  84. object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
  85. if (err) {
  86. error_propagate(errp, err);
  87. return;
  88. }
  89. sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX25_CCM_ADDR);
  90. /* Initialize all UARTs */
  91. for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
  92. static const struct {
  93. hwaddr addr;
  94. unsigned int irq;
  95. } serial_table[FSL_IMX25_NUM_UARTS] = {
  96. { FSL_IMX25_UART1_ADDR, FSL_IMX25_UART1_IRQ },
  97. { FSL_IMX25_UART2_ADDR, FSL_IMX25_UART2_IRQ },
  98. { FSL_IMX25_UART3_ADDR, FSL_IMX25_UART3_IRQ },
  99. { FSL_IMX25_UART4_ADDR, FSL_IMX25_UART4_IRQ },
  100. { FSL_IMX25_UART5_ADDR, FSL_IMX25_UART5_IRQ }
  101. };
  102. qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hd(i));
  103. object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
  104. if (err) {
  105. error_propagate(errp, err);
  106. return;
  107. }
  108. sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
  109. sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
  110. qdev_get_gpio_in(DEVICE(&s->avic),
  111. serial_table[i].irq));
  112. }
  113. /* Initialize all GPT timers */
  114. for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
  115. static const struct {
  116. hwaddr addr;
  117. unsigned int irq;
  118. } gpt_table[FSL_IMX25_NUM_GPTS] = {
  119. { FSL_IMX25_GPT1_ADDR, FSL_IMX25_GPT1_IRQ },
  120. { FSL_IMX25_GPT2_ADDR, FSL_IMX25_GPT2_IRQ },
  121. { FSL_IMX25_GPT3_ADDR, FSL_IMX25_GPT3_IRQ },
  122. { FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
  123. };
  124. s->gpt[i].ccm = IMX_CCM(&s->ccm);
  125. object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err);
  126. if (err) {
  127. error_propagate(errp, err);
  128. return;
  129. }
  130. sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_table[i].addr);
  131. sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
  132. qdev_get_gpio_in(DEVICE(&s->avic),
  133. gpt_table[i].irq));
  134. }
  135. /* Initialize all EPIT timers */
  136. for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
  137. static const struct {
  138. hwaddr addr;
  139. unsigned int irq;
  140. } epit_table[FSL_IMX25_NUM_EPITS] = {
  141. { FSL_IMX25_EPIT1_ADDR, FSL_IMX25_EPIT1_IRQ },
  142. { FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
  143. };
  144. s->epit[i].ccm = IMX_CCM(&s->ccm);
  145. object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
  146. if (err) {
  147. error_propagate(errp, err);
  148. return;
  149. }
  150. sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
  151. sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
  152. qdev_get_gpio_in(DEVICE(&s->avic),
  153. epit_table[i].irq));
  154. }
  155. qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
  156. object_property_set_bool(OBJECT(&s->fec), true, "realized", &err);
  157. if (err) {
  158. error_propagate(errp, err);
  159. return;
  160. }
  161. sysbus_mmio_map(SYS_BUS_DEVICE(&s->fec), 0, FSL_IMX25_FEC_ADDR);
  162. sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0,
  163. qdev_get_gpio_in(DEVICE(&s->avic), FSL_IMX25_FEC_IRQ));
  164. /* Initialize all I2C */
  165. for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
  166. static const struct {
  167. hwaddr addr;
  168. unsigned int irq;
  169. } i2c_table[FSL_IMX25_NUM_I2CS] = {
  170. { FSL_IMX25_I2C1_ADDR, FSL_IMX25_I2C1_IRQ },
  171. { FSL_IMX25_I2C2_ADDR, FSL_IMX25_I2C2_IRQ },
  172. { FSL_IMX25_I2C3_ADDR, FSL_IMX25_I2C3_IRQ }
  173. };
  174. object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err);
  175. if (err) {
  176. error_propagate(errp, err);
  177. return;
  178. }
  179. sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
  180. sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
  181. qdev_get_gpio_in(DEVICE(&s->avic),
  182. i2c_table[i].irq));
  183. }
  184. /* Initialize all GPIOs */
  185. for (i = 0; i < FSL_IMX25_NUM_GPIOS; i++) {
  186. static const struct {
  187. hwaddr addr;
  188. unsigned int irq;
  189. } gpio_table[FSL_IMX25_NUM_GPIOS] = {
  190. { FSL_IMX25_GPIO1_ADDR, FSL_IMX25_GPIO1_IRQ },
  191. { FSL_IMX25_GPIO2_ADDR, FSL_IMX25_GPIO2_IRQ },
  192. { FSL_IMX25_GPIO3_ADDR, FSL_IMX25_GPIO3_IRQ },
  193. { FSL_IMX25_GPIO4_ADDR, FSL_IMX25_GPIO4_IRQ }
  194. };
  195. object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err);
  196. if (err) {
  197. error_propagate(errp, err);
  198. return;
  199. }
  200. sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr);
  201. /* Connect GPIO IRQ to PIC */
  202. sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0,
  203. qdev_get_gpio_in(DEVICE(&s->avic),
  204. gpio_table[i].irq));
  205. }
  206. /* initialize 2 x 16 KB ROM */
  207. memory_region_init_rom(&s->rom[0], NULL,
  208. "imx25.rom0", FSL_IMX25_ROM0_SIZE, &err);
  209. if (err) {
  210. error_propagate(errp, err);
  211. return;
  212. }
  213. memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM0_ADDR,
  214. &s->rom[0]);
  215. memory_region_init_rom(&s->rom[1], NULL,
  216. "imx25.rom1", FSL_IMX25_ROM1_SIZE, &err);
  217. if (err) {
  218. error_propagate(errp, err);
  219. return;
  220. }
  221. memory_region_add_subregion(get_system_memory(), FSL_IMX25_ROM1_ADDR,
  222. &s->rom[1]);
  223. /* initialize internal RAM (128 KB) */
  224. memory_region_init_ram(&s->iram, NULL, "imx25.iram", FSL_IMX25_IRAM_SIZE,
  225. &err);
  226. if (err) {
  227. error_propagate(errp, err);
  228. return;
  229. }
  230. memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ADDR,
  231. &s->iram);
  232. /* internal RAM (128 KB) is aliased over 128 MB - 128 KB */
  233. memory_region_init_alias(&s->iram_alias, NULL, "imx25.iram_alias",
  234. &s->iram, 0, FSL_IMX25_IRAM_ALIAS_SIZE);
  235. memory_region_add_subregion(get_system_memory(), FSL_IMX25_IRAM_ALIAS_ADDR,
  236. &s->iram_alias);
  237. }
  238. static void fsl_imx25_class_init(ObjectClass *oc, void *data)
  239. {
  240. DeviceClass *dc = DEVICE_CLASS(oc);
  241. dc->realize = fsl_imx25_realize;
  242. dc->desc = "i.MX25 SOC";
  243. /*
  244. * Reason: uses serial_hds in realize and the imx25 board does not
  245. * support multiple CPUs
  246. */
  247. dc->user_creatable = false;
  248. }
  249. static const TypeInfo fsl_imx25_type_info = {
  250. .name = TYPE_FSL_IMX25,
  251. .parent = TYPE_DEVICE,
  252. .instance_size = sizeof(FslIMX25State),
  253. .instance_init = fsl_imx25_init,
  254. .class_init = fsl_imx25_class_init,
  255. };
  256. static void fsl_imx25_register_types(void)
  257. {
  258. type_register_static(&fsl_imx25_type_info);
  259. }
  260. type_init(fsl_imx25_register_types)