2
0

cbus.c 15 KB

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