2
0

omap_gpio.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. /*
  2. * TI OMAP processors GPIO emulation.
  3. *
  4. * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org>
  5. * Copyright (C) 2007-2009 Nokia Corporation
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 or
  10. * (at your option) version 3 of the License.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "hw.h"
  21. #include "omap.h"
  22. #include "sysbus.h"
  23. struct omap_gpio_s {
  24. qemu_irq irq;
  25. qemu_irq handler[16];
  26. uint16_t inputs;
  27. uint16_t outputs;
  28. uint16_t dir;
  29. uint16_t edge;
  30. uint16_t mask;
  31. uint16_t ints;
  32. uint16_t pins;
  33. };
  34. struct omap_gpif_s {
  35. SysBusDevice busdev;
  36. int mpu_model;
  37. void *clk;
  38. struct omap_gpio_s omap1;
  39. };
  40. /* General-Purpose I/O of OMAP1 */
  41. static void omap_gpio_set(void *opaque, int line, int level)
  42. {
  43. struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
  44. uint16_t prev = s->inputs;
  45. if (level)
  46. s->inputs |= 1 << line;
  47. else
  48. s->inputs &= ~(1 << line);
  49. if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
  50. (1 << line) & s->dir & ~s->mask) {
  51. s->ints |= 1 << line;
  52. qemu_irq_raise(s->irq);
  53. }
  54. }
  55. static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
  56. {
  57. struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  58. int offset = addr & OMAP_MPUI_REG_MASK;
  59. switch (offset) {
  60. case 0x00: /* DATA_INPUT */
  61. return s->inputs & s->pins;
  62. case 0x04: /* DATA_OUTPUT */
  63. return s->outputs;
  64. case 0x08: /* DIRECTION_CONTROL */
  65. return s->dir;
  66. case 0x0c: /* INTERRUPT_CONTROL */
  67. return s->edge;
  68. case 0x10: /* INTERRUPT_MASK */
  69. return s->mask;
  70. case 0x14: /* INTERRUPT_STATUS */
  71. return s->ints;
  72. case 0x18: /* PIN_CONTROL (not in OMAP310) */
  73. OMAP_BAD_REG(addr);
  74. return s->pins;
  75. }
  76. OMAP_BAD_REG(addr);
  77. return 0;
  78. }
  79. static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
  80. uint32_t value)
  81. {
  82. struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  83. int offset = addr & OMAP_MPUI_REG_MASK;
  84. uint16_t diff;
  85. int ln;
  86. switch (offset) {
  87. case 0x00: /* DATA_INPUT */
  88. OMAP_RO_REG(addr);
  89. return;
  90. case 0x04: /* DATA_OUTPUT */
  91. diff = (s->outputs ^ value) & ~s->dir;
  92. s->outputs = value;
  93. while ((ln = ffs(diff))) {
  94. ln --;
  95. if (s->handler[ln])
  96. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  97. diff &= ~(1 << ln);
  98. }
  99. break;
  100. case 0x08: /* DIRECTION_CONTROL */
  101. diff = s->outputs & (s->dir ^ value);
  102. s->dir = value;
  103. value = s->outputs & ~s->dir;
  104. while ((ln = ffs(diff))) {
  105. ln --;
  106. if (s->handler[ln])
  107. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  108. diff &= ~(1 << ln);
  109. }
  110. break;
  111. case 0x0c: /* INTERRUPT_CONTROL */
  112. s->edge = value;
  113. break;
  114. case 0x10: /* INTERRUPT_MASK */
  115. s->mask = value;
  116. break;
  117. case 0x14: /* INTERRUPT_STATUS */
  118. s->ints &= ~value;
  119. if (!s->ints)
  120. qemu_irq_lower(s->irq);
  121. break;
  122. case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
  123. OMAP_BAD_REG(addr);
  124. s->pins = value;
  125. break;
  126. default:
  127. OMAP_BAD_REG(addr);
  128. return;
  129. }
  130. }
  131. /* *Some* sources say the memory region is 32-bit. */
  132. static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
  133. omap_badwidth_read16,
  134. omap_gpio_read,
  135. omap_badwidth_read16,
  136. };
  137. static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
  138. omap_badwidth_write16,
  139. omap_gpio_write,
  140. omap_badwidth_write16,
  141. };
  142. static void omap_gpio_reset(struct omap_gpio_s *s)
  143. {
  144. s->inputs = 0;
  145. s->outputs = ~0;
  146. s->dir = ~0;
  147. s->edge = ~0;
  148. s->mask = ~0;
  149. s->ints = 0;
  150. s->pins = ~0;
  151. }
  152. struct omap2_gpio_s {
  153. qemu_irq irq[2];
  154. qemu_irq wkup;
  155. qemu_irq *handler;
  156. uint8_t revision;
  157. uint8_t config[2];
  158. uint32_t inputs;
  159. uint32_t outputs;
  160. uint32_t dir;
  161. uint32_t level[2];
  162. uint32_t edge[2];
  163. uint32_t mask[2];
  164. uint32_t wumask;
  165. uint32_t ints[2];
  166. uint32_t debounce;
  167. uint8_t delay;
  168. };
  169. struct omap2_gpif_s {
  170. SysBusDevice busdev;
  171. int mpu_model;
  172. void *iclk;
  173. void *fclk[6];
  174. int modulecount;
  175. struct omap2_gpio_s *modules;
  176. qemu_irq *handler;
  177. int autoidle;
  178. int gpo;
  179. };
  180. /* General-Purpose Interface of OMAP2/3 */
  181. static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
  182. int line)
  183. {
  184. qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
  185. }
  186. static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
  187. {
  188. if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */
  189. return;
  190. if (!(s->config[0] & (3 << 3))) /* Force Idle */
  191. return;
  192. if (!(s->wumask & (1 << line)))
  193. return;
  194. qemu_irq_raise(s->wkup);
  195. }
  196. static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
  197. uint32_t diff)
  198. {
  199. int ln;
  200. s->outputs ^= diff;
  201. diff &= ~s->dir;
  202. while ((ln = ffs(diff))) {
  203. ln --;
  204. qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
  205. diff &= ~(1 << ln);
  206. }
  207. }
  208. static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
  209. {
  210. s->ints[line] |= s->dir &
  211. ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
  212. omap2_gpio_module_int_update(s, line);
  213. }
  214. static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
  215. {
  216. s->ints[0] |= 1 << line;
  217. omap2_gpio_module_int_update(s, 0);
  218. s->ints[1] |= 1 << line;
  219. omap2_gpio_module_int_update(s, 1);
  220. omap2_gpio_module_wake(s, line);
  221. }
  222. static void omap2_gpio_set(void *opaque, int line, int level)
  223. {
  224. struct omap2_gpif_s *p = opaque;
  225. struct omap2_gpio_s *s = &p->modules[line >> 5];
  226. line &= 31;
  227. if (level) {
  228. if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
  229. omap2_gpio_module_int(s, line);
  230. s->inputs |= 1 << line;
  231. } else {
  232. if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
  233. omap2_gpio_module_int(s, line);
  234. s->inputs &= ~(1 << line);
  235. }
  236. }
  237. static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
  238. {
  239. s->config[0] = 0;
  240. s->config[1] = 2;
  241. s->ints[0] = 0;
  242. s->ints[1] = 0;
  243. s->mask[0] = 0;
  244. s->mask[1] = 0;
  245. s->wumask = 0;
  246. s->dir = ~0;
  247. s->level[0] = 0;
  248. s->level[1] = 0;
  249. s->edge[0] = 0;
  250. s->edge[1] = 0;
  251. s->debounce = 0;
  252. s->delay = 0;
  253. }
  254. static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
  255. {
  256. struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
  257. switch (addr) {
  258. case 0x00: /* GPIO_REVISION */
  259. return s->revision;
  260. case 0x10: /* GPIO_SYSCONFIG */
  261. return s->config[0];
  262. case 0x14: /* GPIO_SYSSTATUS */
  263. return 0x01;
  264. case 0x18: /* GPIO_IRQSTATUS1 */
  265. return s->ints[0];
  266. case 0x1c: /* GPIO_IRQENABLE1 */
  267. case 0x60: /* GPIO_CLEARIRQENABLE1 */
  268. case 0x64: /* GPIO_SETIRQENABLE1 */
  269. return s->mask[0];
  270. case 0x20: /* GPIO_WAKEUPENABLE */
  271. case 0x80: /* GPIO_CLEARWKUENA */
  272. case 0x84: /* GPIO_SETWKUENA */
  273. return s->wumask;
  274. case 0x28: /* GPIO_IRQSTATUS2 */
  275. return s->ints[1];
  276. case 0x2c: /* GPIO_IRQENABLE2 */
  277. case 0x70: /* GPIO_CLEARIRQENABLE2 */
  278. case 0x74: /* GPIO_SETIREQNEABLE2 */
  279. return s->mask[1];
  280. case 0x30: /* GPIO_CTRL */
  281. return s->config[1];
  282. case 0x34: /* GPIO_OE */
  283. return s->dir;
  284. case 0x38: /* GPIO_DATAIN */
  285. return s->inputs;
  286. case 0x3c: /* GPIO_DATAOUT */
  287. case 0x90: /* GPIO_CLEARDATAOUT */
  288. case 0x94: /* GPIO_SETDATAOUT */
  289. return s->outputs;
  290. case 0x40: /* GPIO_LEVELDETECT0 */
  291. return s->level[0];
  292. case 0x44: /* GPIO_LEVELDETECT1 */
  293. return s->level[1];
  294. case 0x48: /* GPIO_RISINGDETECT */
  295. return s->edge[0];
  296. case 0x4c: /* GPIO_FALLINGDETECT */
  297. return s->edge[1];
  298. case 0x50: /* GPIO_DEBOUNCENABLE */
  299. return s->debounce;
  300. case 0x54: /* GPIO_DEBOUNCINGTIME */
  301. return s->delay;
  302. }
  303. OMAP_BAD_REG(addr);
  304. return 0;
  305. }
  306. static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
  307. uint32_t value)
  308. {
  309. struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
  310. uint32_t diff;
  311. int ln;
  312. switch (addr) {
  313. case 0x00: /* GPIO_REVISION */
  314. case 0x14: /* GPIO_SYSSTATUS */
  315. case 0x38: /* GPIO_DATAIN */
  316. OMAP_RO_REG(addr);
  317. break;
  318. case 0x10: /* GPIO_SYSCONFIG */
  319. if (((value >> 3) & 3) == 3)
  320. fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
  321. if (value & 2)
  322. omap2_gpio_module_reset(s);
  323. s->config[0] = value & 0x1d;
  324. break;
  325. case 0x18: /* GPIO_IRQSTATUS1 */
  326. if (s->ints[0] & value) {
  327. s->ints[0] &= ~value;
  328. omap2_gpio_module_level_update(s, 0);
  329. }
  330. break;
  331. case 0x1c: /* GPIO_IRQENABLE1 */
  332. s->mask[0] = value;
  333. omap2_gpio_module_int_update(s, 0);
  334. break;
  335. case 0x20: /* GPIO_WAKEUPENABLE */
  336. s->wumask = value;
  337. break;
  338. case 0x28: /* GPIO_IRQSTATUS2 */
  339. if (s->ints[1] & value) {
  340. s->ints[1] &= ~value;
  341. omap2_gpio_module_level_update(s, 1);
  342. }
  343. break;
  344. case 0x2c: /* GPIO_IRQENABLE2 */
  345. s->mask[1] = value;
  346. omap2_gpio_module_int_update(s, 1);
  347. break;
  348. case 0x30: /* GPIO_CTRL */
  349. s->config[1] = value & 7;
  350. break;
  351. case 0x34: /* GPIO_OE */
  352. diff = s->outputs & (s->dir ^ value);
  353. s->dir = value;
  354. value = s->outputs & ~s->dir;
  355. while ((ln = ffs(diff))) {
  356. diff &= ~(1 <<-- ln);
  357. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  358. }
  359. omap2_gpio_module_level_update(s, 0);
  360. omap2_gpio_module_level_update(s, 1);
  361. break;
  362. case 0x3c: /* GPIO_DATAOUT */
  363. omap2_gpio_module_out_update(s, s->outputs ^ value);
  364. break;
  365. case 0x40: /* GPIO_LEVELDETECT0 */
  366. s->level[0] = value;
  367. omap2_gpio_module_level_update(s, 0);
  368. omap2_gpio_module_level_update(s, 1);
  369. break;
  370. case 0x44: /* GPIO_LEVELDETECT1 */
  371. s->level[1] = value;
  372. omap2_gpio_module_level_update(s, 0);
  373. omap2_gpio_module_level_update(s, 1);
  374. break;
  375. case 0x48: /* GPIO_RISINGDETECT */
  376. s->edge[0] = value;
  377. break;
  378. case 0x4c: /* GPIO_FALLINGDETECT */
  379. s->edge[1] = value;
  380. break;
  381. case 0x50: /* GPIO_DEBOUNCENABLE */
  382. s->debounce = value;
  383. break;
  384. case 0x54: /* GPIO_DEBOUNCINGTIME */
  385. s->delay = value;
  386. break;
  387. case 0x60: /* GPIO_CLEARIRQENABLE1 */
  388. s->mask[0] &= ~value;
  389. omap2_gpio_module_int_update(s, 0);
  390. break;
  391. case 0x64: /* GPIO_SETIRQENABLE1 */
  392. s->mask[0] |= value;
  393. omap2_gpio_module_int_update(s, 0);
  394. break;
  395. case 0x70: /* GPIO_CLEARIRQENABLE2 */
  396. s->mask[1] &= ~value;
  397. omap2_gpio_module_int_update(s, 1);
  398. break;
  399. case 0x74: /* GPIO_SETIREQNEABLE2 */
  400. s->mask[1] |= value;
  401. omap2_gpio_module_int_update(s, 1);
  402. break;
  403. case 0x80: /* GPIO_CLEARWKUENA */
  404. s->wumask &= ~value;
  405. break;
  406. case 0x84: /* GPIO_SETWKUENA */
  407. s->wumask |= value;
  408. break;
  409. case 0x90: /* GPIO_CLEARDATAOUT */
  410. omap2_gpio_module_out_update(s, s->outputs & value);
  411. break;
  412. case 0x94: /* GPIO_SETDATAOUT */
  413. omap2_gpio_module_out_update(s, ~s->outputs & value);
  414. break;
  415. default:
  416. OMAP_BAD_REG(addr);
  417. return;
  418. }
  419. }
  420. static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
  421. {
  422. return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3);
  423. }
  424. static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
  425. uint32_t value)
  426. {
  427. uint32_t cur = 0;
  428. uint32_t mask = 0xffff;
  429. switch (addr & ~3) {
  430. case 0x00: /* GPIO_REVISION */
  431. case 0x14: /* GPIO_SYSSTATUS */
  432. case 0x38: /* GPIO_DATAIN */
  433. OMAP_RO_REG(addr);
  434. break;
  435. case 0x10: /* GPIO_SYSCONFIG */
  436. case 0x1c: /* GPIO_IRQENABLE1 */
  437. case 0x20: /* GPIO_WAKEUPENABLE */
  438. case 0x2c: /* GPIO_IRQENABLE2 */
  439. case 0x30: /* GPIO_CTRL */
  440. case 0x34: /* GPIO_OE */
  441. case 0x3c: /* GPIO_DATAOUT */
  442. case 0x40: /* GPIO_LEVELDETECT0 */
  443. case 0x44: /* GPIO_LEVELDETECT1 */
  444. case 0x48: /* GPIO_RISINGDETECT */
  445. case 0x4c: /* GPIO_FALLINGDETECT */
  446. case 0x50: /* GPIO_DEBOUNCENABLE */
  447. case 0x54: /* GPIO_DEBOUNCINGTIME */
  448. cur = omap2_gpio_module_read(opaque, addr & ~3) &
  449. ~(mask << ((addr & 3) << 3));
  450. /* Fall through. */
  451. case 0x18: /* GPIO_IRQSTATUS1 */
  452. case 0x28: /* GPIO_IRQSTATUS2 */
  453. case 0x60: /* GPIO_CLEARIRQENABLE1 */
  454. case 0x64: /* GPIO_SETIRQENABLE1 */
  455. case 0x70: /* GPIO_CLEARIRQENABLE2 */
  456. case 0x74: /* GPIO_SETIREQNEABLE2 */
  457. case 0x80: /* GPIO_CLEARWKUENA */
  458. case 0x84: /* GPIO_SETWKUENA */
  459. case 0x90: /* GPIO_CLEARDATAOUT */
  460. case 0x94: /* GPIO_SETDATAOUT */
  461. value <<= (addr & 3) << 3;
  462. omap2_gpio_module_write(opaque, addr, cur | value);
  463. break;
  464. default:
  465. OMAP_BAD_REG(addr);
  466. return;
  467. }
  468. }
  469. static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
  470. omap2_gpio_module_readp,
  471. omap2_gpio_module_readp,
  472. omap2_gpio_module_read,
  473. };
  474. static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
  475. omap2_gpio_module_writep,
  476. omap2_gpio_module_writep,
  477. omap2_gpio_module_write,
  478. };
  479. static void omap_gpif_reset(DeviceState *dev)
  480. {
  481. struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
  482. sysbus_from_qdev(dev));
  483. omap_gpio_reset(&s->omap1);
  484. }
  485. static void omap2_gpif_reset(DeviceState *dev)
  486. {
  487. int i;
  488. struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
  489. sysbus_from_qdev(dev));
  490. for (i = 0; i < s->modulecount; i++) {
  491. omap2_gpio_module_reset(&s->modules[i]);
  492. }
  493. s->autoidle = 0;
  494. s->gpo = 0;
  495. }
  496. static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
  497. {
  498. struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
  499. switch (addr) {
  500. case 0x00: /* IPGENERICOCPSPL_REVISION */
  501. return 0x18;
  502. case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
  503. return s->autoidle;
  504. case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
  505. return 0x01;
  506. case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
  507. return 0x00;
  508. case 0x40: /* IPGENERICOCPSPL_GPO */
  509. return s->gpo;
  510. case 0x50: /* IPGENERICOCPSPL_GPI */
  511. return 0x00;
  512. }
  513. OMAP_BAD_REG(addr);
  514. return 0;
  515. }
  516. static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
  517. uint32_t value)
  518. {
  519. struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
  520. switch (addr) {
  521. case 0x00: /* IPGENERICOCPSPL_REVISION */
  522. case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
  523. case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
  524. case 0x50: /* IPGENERICOCPSPL_GPI */
  525. OMAP_RO_REG(addr);
  526. break;
  527. case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
  528. if (value & (1 << 1)) /* SOFTRESET */
  529. omap2_gpif_reset(&s->busdev.qdev);
  530. s->autoidle = value & 1;
  531. break;
  532. case 0x40: /* IPGENERICOCPSPL_GPO */
  533. s->gpo = value & 1;
  534. break;
  535. default:
  536. OMAP_BAD_REG(addr);
  537. return;
  538. }
  539. }
  540. static CPUReadMemoryFunc * const omap2_gpif_top_readfn[] = {
  541. omap2_gpif_top_read,
  542. omap2_gpif_top_read,
  543. omap2_gpif_top_read,
  544. };
  545. static CPUWriteMemoryFunc * const omap2_gpif_top_writefn[] = {
  546. omap2_gpif_top_write,
  547. omap2_gpif_top_write,
  548. omap2_gpif_top_write,
  549. };
  550. static int omap_gpio_init(SysBusDevice *dev)
  551. {
  552. struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
  553. if (!s->clk) {
  554. hw_error("omap-gpio: clk not connected\n");
  555. }
  556. qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
  557. qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
  558. sysbus_init_irq(dev, &s->omap1.irq);
  559. sysbus_init_mmio(dev, 0x1000,
  560. cpu_register_io_memory(omap_gpio_readfn,
  561. omap_gpio_writefn,
  562. &s->omap1,
  563. DEVICE_NATIVE_ENDIAN));
  564. return 0;
  565. }
  566. static int omap2_gpio_init(SysBusDevice *dev)
  567. {
  568. int i;
  569. struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
  570. if (!s->iclk) {
  571. hw_error("omap2-gpio: iclk not connected\n");
  572. }
  573. if (s->mpu_model < omap3430) {
  574. s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
  575. sysbus_init_mmio(dev, 0x1000,
  576. cpu_register_io_memory(omap2_gpif_top_readfn,
  577. omap2_gpif_top_writefn, s,
  578. DEVICE_NATIVE_ENDIAN));
  579. } else {
  580. s->modulecount = 6;
  581. }
  582. s->modules = g_malloc0(s->modulecount * sizeof(struct omap2_gpio_s));
  583. s->handler = g_malloc0(s->modulecount * 32 * sizeof(qemu_irq));
  584. qdev_init_gpio_in(&dev->qdev, omap2_gpio_set, s->modulecount * 32);
  585. qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
  586. for (i = 0; i < s->modulecount; i++) {
  587. struct omap2_gpio_s *m = &s->modules[i];
  588. if (!s->fclk[i]) {
  589. hw_error("omap2-gpio: fclk%d not connected\n", i);
  590. }
  591. m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
  592. m->handler = &s->handler[i * 32];
  593. sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
  594. sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
  595. sysbus_init_irq(dev, &m->wkup);
  596. sysbus_init_mmio(dev, 0x1000,
  597. cpu_register_io_memory(omap2_gpio_module_readfn,
  598. omap2_gpio_module_writefn,
  599. m, DEVICE_NATIVE_ENDIAN));
  600. }
  601. return 0;
  602. }
  603. /* Using qdev pointer properties for the clocks is not ideal.
  604. * qdev should support a generic means of defining a 'port' with
  605. * an arbitrary interface for connecting two devices. Then we
  606. * could reframe the omap clock API in terms of clock ports,
  607. * and get some type safety. For now the best qdev provides is
  608. * passing an arbitrary pointer.
  609. * (It's not possible to pass in the string which is the clock
  610. * name, because this device does not have the necessary information
  611. * (ie the struct omap_mpu_state_s*) to do the clockname to pointer
  612. * translation.)
  613. */
  614. static SysBusDeviceInfo omap_gpio_info = {
  615. .init = omap_gpio_init,
  616. .qdev.name = "omap-gpio",
  617. .qdev.size = sizeof(struct omap_gpif_s),
  618. .qdev.reset = omap_gpif_reset,
  619. .qdev.props = (Property[]) {
  620. DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
  621. DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk),
  622. DEFINE_PROP_END_OF_LIST()
  623. }
  624. };
  625. static SysBusDeviceInfo omap2_gpio_info = {
  626. .init = omap2_gpio_init,
  627. .qdev.name = "omap2-gpio",
  628. .qdev.size = sizeof(struct omap2_gpif_s),
  629. .qdev.reset = omap2_gpif_reset,
  630. .qdev.props = (Property[]) {
  631. DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
  632. DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk),
  633. DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]),
  634. DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]),
  635. DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]),
  636. DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]),
  637. DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]),
  638. DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]),
  639. DEFINE_PROP_END_OF_LIST()
  640. }
  641. };
  642. static void omap_gpio_register_device(void)
  643. {
  644. sysbus_register_withprop(&omap_gpio_info);
  645. sysbus_register_withprop(&omap2_gpio_info);
  646. }
  647. device_init(omap_gpio_register_device)