omap_gpio.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  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. /* General-Purpose I/O */
  23. struct omap_gpio_s {
  24. qemu_irq irq;
  25. qemu_irq *in;
  26. qemu_irq handler[16];
  27. uint16_t inputs;
  28. uint16_t outputs;
  29. uint16_t dir;
  30. uint16_t edge;
  31. uint16_t mask;
  32. uint16_t ints;
  33. uint16_t pins;
  34. };
  35. static void omap_gpio_set(void *opaque, int line, int level)
  36. {
  37. struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  38. uint16_t prev = s->inputs;
  39. if (level)
  40. s->inputs |= 1 << line;
  41. else
  42. s->inputs &= ~(1 << line);
  43. if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) &
  44. (1 << line) & s->dir & ~s->mask) {
  45. s->ints |= 1 << line;
  46. qemu_irq_raise(s->irq);
  47. }
  48. }
  49. static uint32_t omap_gpio_read(void *opaque, target_phys_addr_t addr)
  50. {
  51. struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  52. int offset = addr & OMAP_MPUI_REG_MASK;
  53. switch (offset) {
  54. case 0x00: /* DATA_INPUT */
  55. return s->inputs & s->pins;
  56. case 0x04: /* DATA_OUTPUT */
  57. return s->outputs;
  58. case 0x08: /* DIRECTION_CONTROL */
  59. return s->dir;
  60. case 0x0c: /* INTERRUPT_CONTROL */
  61. return s->edge;
  62. case 0x10: /* INTERRUPT_MASK */
  63. return s->mask;
  64. case 0x14: /* INTERRUPT_STATUS */
  65. return s->ints;
  66. case 0x18: /* PIN_CONTROL (not in OMAP310) */
  67. OMAP_BAD_REG(addr);
  68. return s->pins;
  69. }
  70. OMAP_BAD_REG(addr);
  71. return 0;
  72. }
  73. static void omap_gpio_write(void *opaque, target_phys_addr_t addr,
  74. uint32_t value)
  75. {
  76. struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
  77. int offset = addr & OMAP_MPUI_REG_MASK;
  78. uint16_t diff;
  79. int ln;
  80. switch (offset) {
  81. case 0x00: /* DATA_INPUT */
  82. OMAP_RO_REG(addr);
  83. return;
  84. case 0x04: /* DATA_OUTPUT */
  85. diff = (s->outputs ^ value) & ~s->dir;
  86. s->outputs = value;
  87. while ((ln = ffs(diff))) {
  88. ln --;
  89. if (s->handler[ln])
  90. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  91. diff &= ~(1 << ln);
  92. }
  93. break;
  94. case 0x08: /* DIRECTION_CONTROL */
  95. diff = s->outputs & (s->dir ^ value);
  96. s->dir = value;
  97. value = s->outputs & ~s->dir;
  98. while ((ln = ffs(diff))) {
  99. ln --;
  100. if (s->handler[ln])
  101. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  102. diff &= ~(1 << ln);
  103. }
  104. break;
  105. case 0x0c: /* INTERRUPT_CONTROL */
  106. s->edge = value;
  107. break;
  108. case 0x10: /* INTERRUPT_MASK */
  109. s->mask = value;
  110. break;
  111. case 0x14: /* INTERRUPT_STATUS */
  112. s->ints &= ~value;
  113. if (!s->ints)
  114. qemu_irq_lower(s->irq);
  115. break;
  116. case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */
  117. OMAP_BAD_REG(addr);
  118. s->pins = value;
  119. break;
  120. default:
  121. OMAP_BAD_REG(addr);
  122. return;
  123. }
  124. }
  125. /* *Some* sources say the memory region is 32-bit. */
  126. static CPUReadMemoryFunc * const omap_gpio_readfn[] = {
  127. omap_badwidth_read16,
  128. omap_gpio_read,
  129. omap_badwidth_read16,
  130. };
  131. static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
  132. omap_badwidth_write16,
  133. omap_gpio_write,
  134. omap_badwidth_write16,
  135. };
  136. void omap_gpio_reset(struct omap_gpio_s *s)
  137. {
  138. s->inputs = 0;
  139. s->outputs = ~0;
  140. s->dir = ~0;
  141. s->edge = ~0;
  142. s->mask = ~0;
  143. s->ints = 0;
  144. s->pins = ~0;
  145. }
  146. struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
  147. qemu_irq irq, omap_clk clk)
  148. {
  149. int iomemtype;
  150. struct omap_gpio_s *s = (struct omap_gpio_s *)
  151. qemu_mallocz(sizeof(struct omap_gpio_s));
  152. s->irq = irq;
  153. s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
  154. omap_gpio_reset(s);
  155. iomemtype = cpu_register_io_memory(omap_gpio_readfn,
  156. omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
  157. cpu_register_physical_memory(base, 0x1000, iomemtype);
  158. return s;
  159. }
  160. qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
  161. {
  162. return s->in;
  163. }
  164. void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
  165. {
  166. if (line >= 16 || line < 0)
  167. hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
  168. s->handler[line] = handler;
  169. }
  170. /* General-Purpose Interface of OMAP2 */
  171. struct omap2_gpio_s {
  172. qemu_irq irq[2];
  173. qemu_irq wkup;
  174. qemu_irq *in;
  175. qemu_irq handler[32];
  176. uint8_t config[2];
  177. uint32_t inputs;
  178. uint32_t outputs;
  179. uint32_t dir;
  180. uint32_t level[2];
  181. uint32_t edge[2];
  182. uint32_t mask[2];
  183. uint32_t wumask;
  184. uint32_t ints[2];
  185. uint32_t debounce;
  186. uint8_t delay;
  187. };
  188. static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
  189. int line)
  190. {
  191. qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
  192. }
  193. static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line)
  194. {
  195. if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */
  196. return;
  197. if (!(s->config[0] & (3 << 3))) /* Force Idle */
  198. return;
  199. if (!(s->wumask & (1 << line)))
  200. return;
  201. qemu_irq_raise(s->wkup);
  202. }
  203. static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s,
  204. uint32_t diff)
  205. {
  206. int ln;
  207. s->outputs ^= diff;
  208. diff &= ~s->dir;
  209. while ((ln = ffs(diff))) {
  210. ln --;
  211. qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1);
  212. diff &= ~(1 << ln);
  213. }
  214. }
  215. static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line)
  216. {
  217. s->ints[line] |= s->dir &
  218. ((s->inputs & s->level[1]) | (~s->inputs & s->level[0]));
  219. omap2_gpio_module_int_update(s, line);
  220. }
  221. static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
  222. {
  223. s->ints[0] |= 1 << line;
  224. omap2_gpio_module_int_update(s, 0);
  225. s->ints[1] |= 1 << line;
  226. omap2_gpio_module_int_update(s, 1);
  227. omap2_gpio_module_wake(s, line);
  228. }
  229. static void omap2_gpio_module_set(void *opaque, int line, int level)
  230. {
  231. struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
  232. if (level) {
  233. if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
  234. omap2_gpio_module_int(s, line);
  235. s->inputs |= 1 << line;
  236. } else {
  237. if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0]))
  238. omap2_gpio_module_int(s, line);
  239. s->inputs &= ~(1 << line);
  240. }
  241. }
  242. static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
  243. {
  244. s->config[0] = 0;
  245. s->config[1] = 2;
  246. s->ints[0] = 0;
  247. s->ints[1] = 0;
  248. s->mask[0] = 0;
  249. s->mask[1] = 0;
  250. s->wumask = 0;
  251. s->dir = ~0;
  252. s->level[0] = 0;
  253. s->level[1] = 0;
  254. s->edge[0] = 0;
  255. s->edge[1] = 0;
  256. s->debounce = 0;
  257. s->delay = 0;
  258. }
  259. static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
  260. {
  261. struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
  262. switch (addr) {
  263. case 0x00: /* GPIO_REVISION */
  264. return 0x18;
  265. case 0x10: /* GPIO_SYSCONFIG */
  266. return s->config[0];
  267. case 0x14: /* GPIO_SYSSTATUS */
  268. return 0x01;
  269. case 0x18: /* GPIO_IRQSTATUS1 */
  270. return s->ints[0];
  271. case 0x1c: /* GPIO_IRQENABLE1 */
  272. case 0x60: /* GPIO_CLEARIRQENABLE1 */
  273. case 0x64: /* GPIO_SETIRQENABLE1 */
  274. return s->mask[0];
  275. case 0x20: /* GPIO_WAKEUPENABLE */
  276. case 0x80: /* GPIO_CLEARWKUENA */
  277. case 0x84: /* GPIO_SETWKUENA */
  278. return s->wumask;
  279. case 0x28: /* GPIO_IRQSTATUS2 */
  280. return s->ints[1];
  281. case 0x2c: /* GPIO_IRQENABLE2 */
  282. case 0x70: /* GPIO_CLEARIRQENABLE2 */
  283. case 0x74: /* GPIO_SETIREQNEABLE2 */
  284. return s->mask[1];
  285. case 0x30: /* GPIO_CTRL */
  286. return s->config[1];
  287. case 0x34: /* GPIO_OE */
  288. return s->dir;
  289. case 0x38: /* GPIO_DATAIN */
  290. return s->inputs;
  291. case 0x3c: /* GPIO_DATAOUT */
  292. case 0x90: /* GPIO_CLEARDATAOUT */
  293. case 0x94: /* GPIO_SETDATAOUT */
  294. return s->outputs;
  295. case 0x40: /* GPIO_LEVELDETECT0 */
  296. return s->level[0];
  297. case 0x44: /* GPIO_LEVELDETECT1 */
  298. return s->level[1];
  299. case 0x48: /* GPIO_RISINGDETECT */
  300. return s->edge[0];
  301. case 0x4c: /* GPIO_FALLINGDETECT */
  302. return s->edge[1];
  303. case 0x50: /* GPIO_DEBOUNCENABLE */
  304. return s->debounce;
  305. case 0x54: /* GPIO_DEBOUNCINGTIME */
  306. return s->delay;
  307. }
  308. OMAP_BAD_REG(addr);
  309. return 0;
  310. }
  311. static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
  312. uint32_t value)
  313. {
  314. struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
  315. uint32_t diff;
  316. int ln;
  317. switch (addr) {
  318. case 0x00: /* GPIO_REVISION */
  319. case 0x14: /* GPIO_SYSSTATUS */
  320. case 0x38: /* GPIO_DATAIN */
  321. OMAP_RO_REG(addr);
  322. break;
  323. case 0x10: /* GPIO_SYSCONFIG */
  324. if (((value >> 3) & 3) == 3)
  325. fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__);
  326. if (value & 2)
  327. omap2_gpio_module_reset(s);
  328. s->config[0] = value & 0x1d;
  329. break;
  330. case 0x18: /* GPIO_IRQSTATUS1 */
  331. if (s->ints[0] & value) {
  332. s->ints[0] &= ~value;
  333. omap2_gpio_module_level_update(s, 0);
  334. }
  335. break;
  336. case 0x1c: /* GPIO_IRQENABLE1 */
  337. s->mask[0] = value;
  338. omap2_gpio_module_int_update(s, 0);
  339. break;
  340. case 0x20: /* GPIO_WAKEUPENABLE */
  341. s->wumask = value;
  342. break;
  343. case 0x28: /* GPIO_IRQSTATUS2 */
  344. if (s->ints[1] & value) {
  345. s->ints[1] &= ~value;
  346. omap2_gpio_module_level_update(s, 1);
  347. }
  348. break;
  349. case 0x2c: /* GPIO_IRQENABLE2 */
  350. s->mask[1] = value;
  351. omap2_gpio_module_int_update(s, 1);
  352. break;
  353. case 0x30: /* GPIO_CTRL */
  354. s->config[1] = value & 7;
  355. break;
  356. case 0x34: /* GPIO_OE */
  357. diff = s->outputs & (s->dir ^ value);
  358. s->dir = value;
  359. value = s->outputs & ~s->dir;
  360. while ((ln = ffs(diff))) {
  361. diff &= ~(1 <<-- ln);
  362. qemu_set_irq(s->handler[ln], (value >> ln) & 1);
  363. }
  364. omap2_gpio_module_level_update(s, 0);
  365. omap2_gpio_module_level_update(s, 1);
  366. break;
  367. case 0x3c: /* GPIO_DATAOUT */
  368. omap2_gpio_module_out_update(s, s->outputs ^ value);
  369. break;
  370. case 0x40: /* GPIO_LEVELDETECT0 */
  371. s->level[0] = value;
  372. omap2_gpio_module_level_update(s, 0);
  373. omap2_gpio_module_level_update(s, 1);
  374. break;
  375. case 0x44: /* GPIO_LEVELDETECT1 */
  376. s->level[1] = value;
  377. omap2_gpio_module_level_update(s, 0);
  378. omap2_gpio_module_level_update(s, 1);
  379. break;
  380. case 0x48: /* GPIO_RISINGDETECT */
  381. s->edge[0] = value;
  382. break;
  383. case 0x4c: /* GPIO_FALLINGDETECT */
  384. s->edge[1] = value;
  385. break;
  386. case 0x50: /* GPIO_DEBOUNCENABLE */
  387. s->debounce = value;
  388. break;
  389. case 0x54: /* GPIO_DEBOUNCINGTIME */
  390. s->delay = value;
  391. break;
  392. case 0x60: /* GPIO_CLEARIRQENABLE1 */
  393. s->mask[0] &= ~value;
  394. omap2_gpio_module_int_update(s, 0);
  395. break;
  396. case 0x64: /* GPIO_SETIRQENABLE1 */
  397. s->mask[0] |= value;
  398. omap2_gpio_module_int_update(s, 0);
  399. break;
  400. case 0x70: /* GPIO_CLEARIRQENABLE2 */
  401. s->mask[1] &= ~value;
  402. omap2_gpio_module_int_update(s, 1);
  403. break;
  404. case 0x74: /* GPIO_SETIREQNEABLE2 */
  405. s->mask[1] |= value;
  406. omap2_gpio_module_int_update(s, 1);
  407. break;
  408. case 0x80: /* GPIO_CLEARWKUENA */
  409. s->wumask &= ~value;
  410. break;
  411. case 0x84: /* GPIO_SETWKUENA */
  412. s->wumask |= value;
  413. break;
  414. case 0x90: /* GPIO_CLEARDATAOUT */
  415. omap2_gpio_module_out_update(s, s->outputs & value);
  416. break;
  417. case 0x94: /* GPIO_SETDATAOUT */
  418. omap2_gpio_module_out_update(s, ~s->outputs & value);
  419. break;
  420. default:
  421. OMAP_BAD_REG(addr);
  422. return;
  423. }
  424. }
  425. static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
  426. {
  427. return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
  428. }
  429. static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
  430. uint32_t value)
  431. {
  432. uint32_t cur = 0;
  433. uint32_t mask = 0xffff;
  434. switch (addr & ~3) {
  435. case 0x00: /* GPIO_REVISION */
  436. case 0x14: /* GPIO_SYSSTATUS */
  437. case 0x38: /* GPIO_DATAIN */
  438. OMAP_RO_REG(addr);
  439. break;
  440. case 0x10: /* GPIO_SYSCONFIG */
  441. case 0x1c: /* GPIO_IRQENABLE1 */
  442. case 0x20: /* GPIO_WAKEUPENABLE */
  443. case 0x2c: /* GPIO_IRQENABLE2 */
  444. case 0x30: /* GPIO_CTRL */
  445. case 0x34: /* GPIO_OE */
  446. case 0x3c: /* GPIO_DATAOUT */
  447. case 0x40: /* GPIO_LEVELDETECT0 */
  448. case 0x44: /* GPIO_LEVELDETECT1 */
  449. case 0x48: /* GPIO_RISINGDETECT */
  450. case 0x4c: /* GPIO_FALLINGDETECT */
  451. case 0x50: /* GPIO_DEBOUNCENABLE */
  452. case 0x54: /* GPIO_DEBOUNCINGTIME */
  453. cur = omap2_gpio_module_read(opaque, addr & ~3) &
  454. ~(mask << ((addr & 3) << 3));
  455. /* Fall through. */
  456. case 0x18: /* GPIO_IRQSTATUS1 */
  457. case 0x28: /* GPIO_IRQSTATUS2 */
  458. case 0x60: /* GPIO_CLEARIRQENABLE1 */
  459. case 0x64: /* GPIO_SETIRQENABLE1 */
  460. case 0x70: /* GPIO_CLEARIRQENABLE2 */
  461. case 0x74: /* GPIO_SETIREQNEABLE2 */
  462. case 0x80: /* GPIO_CLEARWKUENA */
  463. case 0x84: /* GPIO_SETWKUENA */
  464. case 0x90: /* GPIO_CLEARDATAOUT */
  465. case 0x94: /* GPIO_SETDATAOUT */
  466. value <<= (addr & 3) << 3;
  467. omap2_gpio_module_write(opaque, addr, cur | value);
  468. break;
  469. default:
  470. OMAP_BAD_REG(addr);
  471. return;
  472. }
  473. }
  474. static CPUReadMemoryFunc * const omap2_gpio_module_readfn[] = {
  475. omap2_gpio_module_readp,
  476. omap2_gpio_module_readp,
  477. omap2_gpio_module_read,
  478. };
  479. static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
  480. omap2_gpio_module_writep,
  481. omap2_gpio_module_writep,
  482. omap2_gpio_module_write,
  483. };
  484. static void omap2_gpio_module_init(struct omap2_gpio_s *s,
  485. struct omap_target_agent_s *ta, int region,
  486. qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
  487. omap_clk fclk, omap_clk iclk)
  488. {
  489. int iomemtype;
  490. s->irq[0] = mpu;
  491. s->irq[1] = dsp;
  492. s->wkup = wkup;
  493. s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
  494. iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
  495. omap2_gpio_module_writefn, s);
  496. omap_l4_attach(ta, region, iomemtype);
  497. }
  498. struct omap_gpif_s {
  499. struct omap2_gpio_s module[5];
  500. int modules;
  501. int autoidle;
  502. int gpo;
  503. };
  504. void omap_gpif_reset(struct omap_gpif_s *s)
  505. {
  506. int i;
  507. for (i = 0; i < s->modules; i ++)
  508. omap2_gpio_module_reset(s->module + i);
  509. s->autoidle = 0;
  510. s->gpo = 0;
  511. }
  512. static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
  513. {
  514. struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
  515. switch (addr) {
  516. case 0x00: /* IPGENERICOCPSPL_REVISION */
  517. return 0x18;
  518. case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
  519. return s->autoidle;
  520. case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
  521. return 0x01;
  522. case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
  523. return 0x00;
  524. case 0x40: /* IPGENERICOCPSPL_GPO */
  525. return s->gpo;
  526. case 0x50: /* IPGENERICOCPSPL_GPI */
  527. return 0x00;
  528. }
  529. OMAP_BAD_REG(addr);
  530. return 0;
  531. }
  532. static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
  533. uint32_t value)
  534. {
  535. struct omap_gpif_s *s = (struct omap_gpif_s *) opaque;
  536. switch (addr) {
  537. case 0x00: /* IPGENERICOCPSPL_REVISION */
  538. case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */
  539. case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */
  540. case 0x50: /* IPGENERICOCPSPL_GPI */
  541. OMAP_RO_REG(addr);
  542. break;
  543. case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
  544. if (value & (1 << 1)) /* SOFTRESET */
  545. omap_gpif_reset(s);
  546. s->autoidle = value & 1;
  547. break;
  548. case 0x40: /* IPGENERICOCPSPL_GPO */
  549. s->gpo = value & 1;
  550. break;
  551. default:
  552. OMAP_BAD_REG(addr);
  553. return;
  554. }
  555. }
  556. static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = {
  557. omap_gpif_top_read,
  558. omap_gpif_top_read,
  559. omap_gpif_top_read,
  560. };
  561. static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = {
  562. omap_gpif_top_write,
  563. omap_gpif_top_write,
  564. omap_gpif_top_write,
  565. };
  566. struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
  567. qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
  568. {
  569. int iomemtype, i;
  570. struct omap_gpif_s *s = (struct omap_gpif_s *)
  571. qemu_mallocz(sizeof(struct omap_gpif_s));
  572. int region[4] = { 0, 2, 4, 5 };
  573. s->modules = modules;
  574. for (i = 0; i < modules; i ++)
  575. omap2_gpio_module_init(s->module + i, ta, region[i],
  576. irq[i], NULL, NULL, fclk[i], iclk);
  577. omap_gpif_reset(s);
  578. iomemtype = l4_register_io_memory(omap_gpif_top_readfn,
  579. omap_gpif_top_writefn, s);
  580. omap_l4_attach(ta, 1, iomemtype);
  581. return s;
  582. }
  583. qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start)
  584. {
  585. if (start >= s->modules * 32 || start < 0)
  586. hw_error("%s: No GPIO line %i\n", __FUNCTION__, start);
  587. return s->module[start >> 5].in + (start & 31);
  588. }
  589. void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler)
  590. {
  591. if (line >= s->modules * 32 || line < 0)
  592. hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
  593. s->module[line >> 5].handler[line & 31] = handler;
  594. }