cbus.c 15 KB

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