cbus.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*
  2. * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
  3. * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
  4. * Based on reverse-engineering of a linux driver.
  5. *
  6. * Copyright (C) 2008 Nokia Corporation
  7. * Written by Andrzej Zaborowski <andrew@openedhand.com>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 or
  12. * (at your option) version 3 of the License.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  22. */
  23. #include "qemu-common.h"
  24. #include "irq.h"
  25. #include "devices.h"
  26. #include "sysemu.h"
  27. //#define DEBUG
  28. struct cbus_slave_s;
  29. struct cbus_priv_s {
  30. struct cbus_s cbus;
  31. int sel;
  32. int dat;
  33. int clk;
  34. int bit;
  35. int dir;
  36. uint16_t val;
  37. qemu_irq dat_out;
  38. int addr;
  39. int reg;
  40. int rw;
  41. enum {
  42. cbus_address,
  43. cbus_value,
  44. } cycle;
  45. struct cbus_slave_s *slave[8];
  46. };
  47. struct cbus_slave_s {
  48. void *opaque;
  49. void (*io)(void *opaque, int rw, int reg, uint16_t *val);
  50. int addr;
  51. };
  52. static void cbus_io(struct cbus_priv_s *s)
  53. {
  54. if (s->slave[s->addr])
  55. s->slave[s->addr]->io(s->slave[s->addr]->opaque,
  56. s->rw, s->reg, &s->val);
  57. else
  58. cpu_abort(cpu_single_env, "%s: bad slave address %i\n",
  59. __FUNCTION__, s->addr);
  60. }
  61. static void cbus_cycle(struct cbus_priv_s *s)
  62. {
  63. switch (s->cycle) {
  64. case cbus_address:
  65. s->addr = (s->val >> 6) & 7;
  66. s->rw = (s->val >> 5) & 1;
  67. s->reg = (s->val >> 0) & 0x1f;
  68. s->cycle = cbus_value;
  69. s->bit = 15;
  70. s->dir = !s->rw;
  71. s->val = 0;
  72. if (s->rw)
  73. cbus_io(s);
  74. break;
  75. case cbus_value:
  76. if (!s->rw)
  77. cbus_io(s);
  78. s->cycle = cbus_address;
  79. s->bit = 8;
  80. s->dir = 1;
  81. s->val = 0;
  82. break;
  83. }
  84. }
  85. static void cbus_clk(void *opaque, int line, int level)
  86. {
  87. struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
  88. if (!s->sel && level && !s->clk) {
  89. if (s->dir)
  90. s->val |= s->dat << (s->bit --);
  91. else
  92. qemu_set_irq(s->dat_out, (s->val >> (s->bit --)) & 1);
  93. if (s->bit < 0)
  94. cbus_cycle(s);
  95. }
  96. s->clk = level;
  97. }
  98. static void cbus_dat(void *opaque, int line, int level)
  99. {
  100. struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
  101. s->dat = level;
  102. }
  103. static void cbus_sel(void *opaque, int line, int level)
  104. {
  105. struct cbus_priv_s *s = (struct cbus_priv_s *) opaque;
  106. if (!level) {
  107. s->dir = 1;
  108. s->bit = 8;
  109. s->val = 0;
  110. }
  111. s->sel = level;
  112. }
  113. struct cbus_s *cbus_init(qemu_irq dat)
  114. {
  115. struct cbus_priv_s *s = (struct cbus_priv_s *) qemu_mallocz(sizeof(*s));
  116. s->dat_out = dat;
  117. s->cbus.clk = qemu_allocate_irqs(cbus_clk, s, 1)[0];
  118. s->cbus.dat = qemu_allocate_irqs(cbus_dat, s, 1)[0];
  119. s->cbus.sel = qemu_allocate_irqs(cbus_sel, s, 1)[0];
  120. s->sel = 1;
  121. s->clk = 0;
  122. s->dat = 0;
  123. return &s->cbus;
  124. }
  125. void cbus_attach(struct cbus_s *bus, void *slave_opaque)
  126. {
  127. struct cbus_slave_s *slave = (struct cbus_slave_s *) slave_opaque;
  128. struct cbus_priv_s *s = (struct cbus_priv_s *) bus;
  129. s->slave[slave->addr] = slave;
  130. }
  131. /* Retu/Vilma */
  132. struct cbus_retu_s {
  133. uint16_t irqst;
  134. uint16_t irqen;
  135. uint16_t cc[2];
  136. int channel;
  137. uint16_t result[16];
  138. uint16_t sample;
  139. uint16_t status;
  140. struct {
  141. uint16_t cal;
  142. } rtc;
  143. int is_vilma;
  144. qemu_irq irq;
  145. struct cbus_slave_s cbus;
  146. };
  147. static void retu_interrupt_update(struct cbus_retu_s *s)
  148. {
  149. qemu_set_irq(s->irq, s->irqst & ~s->irqen);
  150. }
  151. #define RETU_REG_ASICR 0x00 /* (RO) ASIC ID & revision */
  152. #define RETU_REG_IDR 0x01 /* (T) Interrupt ID */
  153. #define RETU_REG_IMR 0x02 /* (RW) Interrupt mask */
  154. #define RETU_REG_RTCDSR 0x03 /* (RW) RTC seconds register */
  155. #define RETU_REG_RTCHMR 0x04 /* (RO) RTC hours and minutes reg */
  156. #define RETU_REG_RTCHMAR 0x05 /* (RW) RTC hours and minutes set reg */
  157. #define RETU_REG_RTCCALR 0x06 /* (RW) RTC calibration register */
  158. #define RETU_REG_ADCR 0x08 /* (RW) ADC result register */
  159. #define RETU_REG_ADCSCR 0x09 /* (RW) ADC sample control register */
  160. #define RETU_REG_AFCR 0x0a /* (RW) AFC register */
  161. #define RETU_REG_ANTIFR 0x0b /* (RW) AntiF register */
  162. #define RETU_REG_CALIBR 0x0c /* (RW) CalibR register*/
  163. #define RETU_REG_CCR1 0x0d /* (RW) Common control register 1 */
  164. #define RETU_REG_CCR2 0x0e /* (RW) Common control register 2 */
  165. #define RETU_REG_RCTRL_CLR 0x0f /* (T) Regulator clear register */
  166. #define RETU_REG_RCTRL_SET 0x10 /* (T) Regulator set register */
  167. #define RETU_REG_TXCR 0x11 /* (RW) TxC register */
  168. #define RETU_REG_STATUS 0x16 /* (RO) Status register */
  169. #define RETU_REG_WATCHDOG 0x17 /* (RW) Watchdog register */
  170. #define RETU_REG_AUDTXR 0x18 /* (RW) Audio Codec Tx register */
  171. #define RETU_REG_AUDPAR 0x19 /* (RW) AudioPA register */
  172. #define RETU_REG_AUDRXR1 0x1a /* (RW) Audio receive register 1 */
  173. #define RETU_REG_AUDRXR2 0x1b /* (RW) Audio receive register 2 */
  174. #define RETU_REG_SGR1 0x1c /* (RW) */
  175. #define RETU_REG_SCR1 0x1d /* (RW) */
  176. #define RETU_REG_SGR2 0x1e /* (RW) */
  177. #define RETU_REG_SCR2 0x1f /* (RW) */
  178. /* Retu Interrupt sources */
  179. enum {
  180. retu_int_pwr = 0, /* Power button */
  181. retu_int_char = 1, /* Charger */
  182. retu_int_rtcs = 2, /* Seconds */
  183. retu_int_rtcm = 3, /* Minutes */
  184. retu_int_rtcd = 4, /* Days */
  185. retu_int_rtca = 5, /* Alarm */
  186. retu_int_hook = 6, /* Hook */
  187. retu_int_head = 7, /* Headset */
  188. retu_int_adcs = 8, /* ADC sample */
  189. };
  190. /* Retu ADC channel wiring */
  191. enum {
  192. retu_adc_bsi = 1, /* BSI */
  193. retu_adc_batt_temp = 2, /* Battery temperature */
  194. retu_adc_chg_volt = 3, /* Charger voltage */
  195. retu_adc_head_det = 4, /* Headset detection */
  196. retu_adc_hook_det = 5, /* Hook detection */
  197. retu_adc_rf_gp = 6, /* RF GP */
  198. retu_adc_tx_det = 7, /* Wideband Tx detection */
  199. retu_adc_batt_volt = 8, /* Battery voltage */
  200. retu_adc_sens = 10, /* Light sensor */
  201. retu_adc_sens_temp = 11, /* Light sensor temperature */
  202. retu_adc_bbatt_volt = 12, /* Backup battery voltage */
  203. retu_adc_self_temp = 13, /* RETU temperature */
  204. };
  205. static inline uint16_t retu_read(struct cbus_retu_s *s, int reg)
  206. {
  207. #ifdef DEBUG
  208. printf("RETU read at %02x\n", reg);
  209. #endif
  210. switch (reg) {
  211. case RETU_REG_ASICR:
  212. return 0x0215 | (s->is_vilma << 7);
  213. case RETU_REG_IDR: /* TODO: Or is this ffs(s->irqst)? */
  214. return s->irqst;
  215. case RETU_REG_IMR:
  216. return s->irqen;
  217. case RETU_REG_RTCDSR:
  218. case RETU_REG_RTCHMR:
  219. case RETU_REG_RTCHMAR:
  220. /* TODO */
  221. return 0x0000;
  222. case RETU_REG_RTCCALR:
  223. return s->rtc.cal;
  224. case RETU_REG_ADCR:
  225. return (s->channel << 10) | s->result[s->channel];
  226. case RETU_REG_ADCSCR:
  227. return s->sample;
  228. case RETU_REG_AFCR:
  229. case RETU_REG_ANTIFR:
  230. case RETU_REG_CALIBR:
  231. /* TODO */
  232. return 0x0000;
  233. case RETU_REG_CCR1:
  234. return s->cc[0];
  235. case RETU_REG_CCR2:
  236. return s->cc[1];
  237. case RETU_REG_RCTRL_CLR:
  238. case RETU_REG_RCTRL_SET:
  239. case RETU_REG_TXCR:
  240. /* TODO */
  241. return 0x0000;
  242. case RETU_REG_STATUS:
  243. return s->status;
  244. case RETU_REG_WATCHDOG:
  245. case RETU_REG_AUDTXR:
  246. case RETU_REG_AUDPAR:
  247. case RETU_REG_AUDRXR1:
  248. case RETU_REG_AUDRXR2:
  249. case RETU_REG_SGR1:
  250. case RETU_REG_SCR1:
  251. case RETU_REG_SGR2:
  252. case RETU_REG_SCR2:
  253. /* TODO */
  254. return 0x0000;
  255. default:
  256. cpu_abort(cpu_single_env, "%s: bad register %02x\n",
  257. __FUNCTION__, reg);
  258. }
  259. }
  260. static inline void retu_write(struct cbus_retu_s *s, int reg, uint16_t val)
  261. {
  262. #ifdef DEBUG
  263. printf("RETU write of %04x at %02x\n", val, reg);
  264. #endif
  265. switch (reg) {
  266. case RETU_REG_IDR:
  267. s->irqst ^= val;
  268. retu_interrupt_update(s);
  269. break;
  270. case RETU_REG_IMR:
  271. s->irqen = val;
  272. retu_interrupt_update(s);
  273. break;
  274. case RETU_REG_RTCDSR:
  275. case RETU_REG_RTCHMAR:
  276. /* TODO */
  277. break;
  278. case RETU_REG_RTCCALR:
  279. s->rtc.cal = val;
  280. break;
  281. case RETU_REG_ADCR:
  282. s->channel = (val >> 10) & 0xf;
  283. s->irqst |= 1 << retu_int_adcs;
  284. retu_interrupt_update(s);
  285. break;
  286. case RETU_REG_ADCSCR:
  287. s->sample &= ~val;
  288. break;
  289. case RETU_REG_AFCR:
  290. case RETU_REG_ANTIFR:
  291. case RETU_REG_CALIBR:
  292. case RETU_REG_CCR1:
  293. s->cc[0] = val;
  294. break;
  295. case RETU_REG_CCR2:
  296. s->cc[1] = val;
  297. break;
  298. case RETU_REG_RCTRL_CLR:
  299. case RETU_REG_RCTRL_SET:
  300. /* TODO */
  301. break;
  302. case RETU_REG_WATCHDOG:
  303. if (val == 0 && (s->cc[0] & 2))
  304. qemu_system_shutdown_request();
  305. break;
  306. case RETU_REG_TXCR:
  307. case RETU_REG_AUDTXR:
  308. case RETU_REG_AUDPAR:
  309. case RETU_REG_AUDRXR1:
  310. case RETU_REG_AUDRXR2:
  311. case RETU_REG_SGR1:
  312. case RETU_REG_SCR1:
  313. case RETU_REG_SGR2:
  314. case RETU_REG_SCR2:
  315. /* TODO */
  316. break;
  317. default:
  318. cpu_abort(cpu_single_env, "%s: bad register %02x\n",
  319. __FUNCTION__, reg);
  320. }
  321. }
  322. static void retu_io(void *opaque, int rw, int reg, uint16_t *val)
  323. {
  324. struct cbus_retu_s *s = (struct cbus_retu_s *) opaque;
  325. if (rw)
  326. *val = retu_read(s, reg);
  327. else
  328. retu_write(s, reg, *val);
  329. }
  330. void *retu_init(qemu_irq irq, int vilma)
  331. {
  332. struct cbus_retu_s *s = (struct cbus_retu_s *) qemu_mallocz(sizeof(*s));
  333. s->irq = irq;
  334. s->irqen = 0xffff;
  335. s->irqst = 0x0000;
  336. s->status = 0x0020;
  337. s->is_vilma = !!vilma;
  338. s->rtc.cal = 0x01;
  339. s->result[retu_adc_bsi] = 0x3c2;
  340. s->result[retu_adc_batt_temp] = 0x0fc;
  341. s->result[retu_adc_chg_volt] = 0x165;
  342. s->result[retu_adc_head_det] = 123;
  343. s->result[retu_adc_hook_det] = 1023;
  344. s->result[retu_adc_rf_gp] = 0x11;
  345. s->result[retu_adc_tx_det] = 0x11;
  346. s->result[retu_adc_batt_volt] = 0x250;
  347. s->result[retu_adc_sens] = 2;
  348. s->result[retu_adc_sens_temp] = 0x11;
  349. s->result[retu_adc_bbatt_volt] = 0x3d0;
  350. s->result[retu_adc_self_temp] = 0x330;
  351. s->cbus.opaque = s;
  352. s->cbus.io = retu_io;
  353. s->cbus.addr = 1;
  354. return &s->cbus;
  355. }
  356. void retu_key_event(void *retu, int state)
  357. {
  358. struct cbus_slave_s *slave = (struct cbus_slave_s *) retu;
  359. struct cbus_retu_s *s = (struct cbus_retu_s *) slave->opaque;
  360. s->irqst |= 1 << retu_int_pwr;
  361. retu_interrupt_update(s);
  362. if (state)
  363. s->status &= ~(1 << 5);
  364. else
  365. s->status |= 1 << 5;
  366. }
  367. #if 0
  368. static void retu_head_event(void *retu, int state)
  369. {
  370. struct cbus_slave_s *slave = (struct cbus_slave_s *) retu;
  371. struct cbus_retu_s *s = (struct cbus_retu_s *) slave->opaque;
  372. if ((s->cc[0] & 0x500) == 0x500) { /* TODO: Which bits? */
  373. /* TODO: reissue the interrupt every 100ms or so. */
  374. s->irqst |= 1 << retu_int_head;
  375. retu_interrupt_update(s);
  376. }
  377. if (state)
  378. s->result[retu_adc_head_det] = 50;
  379. else
  380. s->result[retu_adc_head_det] = 123;
  381. }
  382. static void retu_hook_event(void *retu, int state)
  383. {
  384. struct cbus_slave_s *slave = (struct cbus_slave_s *) retu;
  385. struct cbus_retu_s *s = (struct cbus_retu_s *) slave->opaque;
  386. if ((s->cc[0] & 0x500) == 0x500) {
  387. /* TODO: reissue the interrupt every 100ms or so. */
  388. s->irqst |= 1 << retu_int_hook;
  389. retu_interrupt_update(s);
  390. }
  391. if (state)
  392. s->result[retu_adc_hook_det] = 50;
  393. else
  394. s->result[retu_adc_hook_det] = 123;
  395. }
  396. #endif
  397. /* Tahvo/Betty */
  398. struct cbus_tahvo_s {
  399. uint16_t irqst;
  400. uint16_t irqen;
  401. uint8_t charger;
  402. uint8_t backlight;
  403. uint16_t usbr;
  404. uint16_t power;
  405. int is_betty;
  406. qemu_irq irq;
  407. struct cbus_slave_s cbus;
  408. };
  409. static void tahvo_interrupt_update(struct cbus_tahvo_s *s)
  410. {
  411. qemu_set_irq(s->irq, s->irqst & ~s->irqen);
  412. }
  413. #define TAHVO_REG_ASICR 0x00 /* (RO) ASIC ID & revision */
  414. #define TAHVO_REG_IDR 0x01 /* (T) Interrupt ID */
  415. #define TAHVO_REG_IDSR 0x02 /* (RO) Interrupt status */
  416. #define TAHVO_REG_IMR 0x03 /* (RW) Interrupt mask */
  417. #define TAHVO_REG_CHAPWMR 0x04 /* (RW) Charger PWM */
  418. #define TAHVO_REG_LEDPWMR 0x05 /* (RW) LED PWM */
  419. #define TAHVO_REG_USBR 0x06 /* (RW) USB control */
  420. #define TAHVO_REG_RCR 0x07 /* (RW) Some kind of power management */
  421. #define TAHVO_REG_CCR1 0x08 /* (RW) Common control register 1 */
  422. #define TAHVO_REG_CCR2 0x09 /* (RW) Common control register 2 */
  423. #define TAHVO_REG_TESTR1 0x0a /* (RW) Test register 1 */
  424. #define TAHVO_REG_TESTR2 0x0b /* (RW) Test register 2 */
  425. #define TAHVO_REG_NOPR 0x0c /* (RW) Number of periods */
  426. #define TAHVO_REG_FRR 0x0d /* (RO) FR */
  427. static inline uint16_t tahvo_read(struct cbus_tahvo_s *s, int reg)
  428. {
  429. #ifdef DEBUG
  430. printf("TAHVO read at %02x\n", reg);
  431. #endif
  432. switch (reg) {
  433. case TAHVO_REG_ASICR:
  434. return 0x0021 | (s->is_betty ? 0x0b00 : 0x0300); /* 22 in N810 */
  435. case TAHVO_REG_IDR:
  436. case TAHVO_REG_IDSR: /* XXX: what does this do? */
  437. return s->irqst;
  438. case TAHVO_REG_IMR:
  439. return s->irqen;
  440. case TAHVO_REG_CHAPWMR:
  441. return s->charger;
  442. case TAHVO_REG_LEDPWMR:
  443. return s->backlight;
  444. case TAHVO_REG_USBR:
  445. return s->usbr;
  446. case TAHVO_REG_RCR:
  447. return s->power;
  448. case TAHVO_REG_CCR1:
  449. case TAHVO_REG_CCR2:
  450. case TAHVO_REG_TESTR1:
  451. case TAHVO_REG_TESTR2:
  452. case TAHVO_REG_NOPR:
  453. case TAHVO_REG_FRR:
  454. return 0x0000;
  455. default:
  456. cpu_abort(cpu_single_env, "%s: bad register %02x\n",
  457. __FUNCTION__, reg);
  458. }
  459. }
  460. static inline void tahvo_write(struct cbus_tahvo_s *s, int reg, uint16_t val)
  461. {
  462. #ifdef DEBUG
  463. printf("TAHVO write of %04x at %02x\n", val, reg);
  464. #endif
  465. switch (reg) {
  466. case TAHVO_REG_IDR:
  467. s->irqst ^= val;
  468. tahvo_interrupt_update(s);
  469. break;
  470. case TAHVO_REG_IMR:
  471. s->irqen = val;
  472. tahvo_interrupt_update(s);
  473. break;
  474. case TAHVO_REG_CHAPWMR:
  475. s->charger = val;
  476. break;
  477. case TAHVO_REG_LEDPWMR:
  478. if (s->backlight != (val & 0x7f)) {
  479. s->backlight = val & 0x7f;
  480. printf("%s: LCD backlight now at %i / 127\n",
  481. __FUNCTION__, s->backlight);
  482. }
  483. break;
  484. case TAHVO_REG_USBR:
  485. s->usbr = val;
  486. break;
  487. case TAHVO_REG_RCR:
  488. s->power = val;
  489. break;
  490. case TAHVO_REG_CCR1:
  491. case TAHVO_REG_CCR2:
  492. case TAHVO_REG_TESTR1:
  493. case TAHVO_REG_TESTR2:
  494. case TAHVO_REG_NOPR:
  495. case TAHVO_REG_FRR:
  496. break;
  497. default:
  498. cpu_abort(cpu_single_env, "%s: bad register %02x\n",
  499. __FUNCTION__, reg);
  500. }
  501. }
  502. static void tahvo_io(void *opaque, int rw, int reg, uint16_t *val)
  503. {
  504. struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) opaque;
  505. if (rw)
  506. *val = tahvo_read(s, reg);
  507. else
  508. tahvo_write(s, reg, *val);
  509. }
  510. void *tahvo_init(qemu_irq irq, int betty)
  511. {
  512. struct cbus_tahvo_s *s = (struct cbus_tahvo_s *) qemu_mallocz(sizeof(*s));
  513. s->irq = irq;
  514. s->irqen = 0xffff;
  515. s->irqst = 0x0000;
  516. s->is_betty = !!betty;
  517. s->cbus.opaque = s;
  518. s->cbus.io = tahvo_io;
  519. s->cbus.addr = 2;
  520. return &s->cbus;
  521. }