/arch/arm/mach-msm/htc_power_supply.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase · C · 616 lines · 510 code · 84 blank · 22 comment · 73 complexity · 880cfd7455d224cc510308fb048663ec MD5 · raw file

  1. /* arch/arm/mach-msm/htc_battery.c
  2. *
  3. * Copyright (C) 2008 HTC Corporation.
  4. * Copyright (C) 2008 Google, Inc.
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. */
  16. #include <linux/init.h>
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/err.h>
  20. #include <linux/power_supply.h>
  21. #include <linux/platform_device.h>
  22. #include <mach/msm_fast_timer.h>
  23. #include <mach/msm_rpcrouter.h>
  24. #include <mach/board.h>
  25. #include <linux/workqueue.h>
  26. #include <linux/delay.h>
  27. #include <linux/gpio.h>
  28. #include <linux/switch.h>
  29. #include "board-mahimahi.h"
  30. extern void notify_usb_connected(int);
  31. static char *supply_list[] = {
  32. "battery",
  33. };
  34. static struct switch_dev dock_switch = {
  35. .name = "dock",
  36. };
  37. static int vbus_present;
  38. static int usb_status;
  39. static bool dock_mains;
  40. struct dock_state {
  41. struct mutex lock;
  42. u32 t;
  43. u32 last_edge_t[2];
  44. u32 last_edge_i[2];
  45. bool level;
  46. bool dock_connected_unknown;
  47. };
  48. static struct workqueue_struct *dock_wq;
  49. static struct work_struct dock_work;
  50. static struct wake_lock dock_work_wake_lock;
  51. static struct dock_state ds = {
  52. .lock = __MUTEX_INITIALIZER(ds.lock),
  53. };
  54. #define _GPIO_DOCK MAHIMAHI_GPIO_DOCK
  55. #define dock_out(n) gpio_direction_output(_GPIO_DOCK, n)
  56. #define dock_out2(n) gpio_set_value(_GPIO_DOCK, n)
  57. #define dock_in() gpio_direction_input(_GPIO_DOCK)
  58. #define dock_read() gpio_get_value(_GPIO_DOCK)
  59. #define MFM_DELAY_NS 10000
  60. static int dock_get_edge(struct dock_state *s, u32 timeout, u32 tmin, u32 tmax)
  61. {
  62. bool lin;
  63. bool in = s->level;
  64. u32 t;
  65. do {
  66. lin = in;
  67. in = dock_read();
  68. t = msm_read_fast_timer();
  69. if (in != lin) {
  70. s->last_edge_t[in] = t;
  71. s->last_edge_i[in] = 0;
  72. s->level = in;
  73. if ((s32)(t - tmin) < 0 || (s32)(t - tmax) > 0)
  74. return -1;
  75. return 1;
  76. }
  77. } while((s32)(t - timeout) < 0);
  78. return 0;
  79. }
  80. static bool dock_sync(struct dock_state *s, u32 timeout)
  81. {
  82. u32 t;
  83. s->level = dock_read();
  84. t = msm_read_fast_timer();
  85. if (!dock_get_edge(s, t + timeout, 0, 0))
  86. return false;
  87. s->last_edge_i[s->level] = 2;
  88. return !!dock_get_edge(s,
  89. s->last_edge_t[s->level] + MFM_DELAY_NS * 4, 0, 0);
  90. }
  91. static int dock_get_next_bit(struct dock_state *s)
  92. {
  93. u32 i = s->last_edge_i[!s->level] + ++s->last_edge_i[s->level];
  94. u32 target = s->last_edge_t[!s->level] + MFM_DELAY_NS * i;
  95. u32 timeout = target + MFM_DELAY_NS / 2;
  96. u32 tmin = target - MFM_DELAY_NS / 4;
  97. u32 tmax = target + MFM_DELAY_NS / 4;
  98. return dock_get_edge(s, timeout, tmin, tmax);
  99. }
  100. static u32 dock_get_bits(struct dock_state *s, int count, int *errp)
  101. {
  102. u32 data = 0;
  103. u32 m = 1;
  104. int ret;
  105. int err = 0;
  106. while (count--) {
  107. ret = dock_get_next_bit(s);
  108. if (ret)
  109. data |= m;
  110. if (ret < 0)
  111. err++;
  112. m <<= 1;
  113. }
  114. if (errp)
  115. *errp = err;
  116. return data;
  117. }
  118. static void dock_delay(u32 timeout)
  119. {
  120. timeout += msm_read_fast_timer();
  121. while (((s32)(msm_read_fast_timer() - timeout)) < 0)
  122. ;
  123. }
  124. static int dock_send_bits(struct dock_state *s, u32 data, int count, int period)
  125. {
  126. u32 t, t0, to;
  127. dock_out2(s->level);
  128. t = to = 0;
  129. t0 = msm_read_fast_timer();
  130. while (count--) {
  131. if (data & 1)
  132. dock_out2((s->level = !s->level));
  133. t = msm_read_fast_timer() - t0;
  134. if (t - to > period / 2) {
  135. pr_info("dock: to = %d, t = %d\n", to, t);
  136. return -EIO;
  137. }
  138. to += MFM_DELAY_NS;
  139. do {
  140. t = msm_read_fast_timer() - t0;
  141. } while (t < to);
  142. if (t - to > period / 4) {
  143. pr_info("dock: to = %d, t = %d\n", to, t);
  144. return -EIO;
  145. }
  146. data >>= 1;
  147. }
  148. return 0;
  149. }
  150. static u32 mfm_encode(u16 data, int count, bool p)
  151. {
  152. u32 mask;
  153. u32 mfm = 0;
  154. u32 clock = ~data & ~(data << 1 | !!p);
  155. for (mask = 1UL << (count - 1); mask; mask >>= 1) {
  156. mfm |= (data & mask);
  157. mfm <<= 1;
  158. mfm |= (clock & mask);
  159. }
  160. return mfm;
  161. }
  162. static u32 mfm_decode(u32 mfm)
  163. {
  164. u32 data = 0;
  165. u32 clock = 0;
  166. u32 mask = 1;
  167. while (mfm) {
  168. if (mfm & 1)
  169. clock |= mask;
  170. mfm >>= 1;
  171. if (mfm & 1)
  172. data |= mask;
  173. mfm >>= 1;
  174. mask <<= 1;
  175. }
  176. return data;
  177. }
  178. static int dock_command(struct dock_state *s, u16 cmd, int len, int retlen)
  179. {
  180. u32 mfm;
  181. int count;
  182. u32 data = cmd;
  183. int ret;
  184. int err = -1;
  185. unsigned long flags;
  186. data = data << 2 | 3; /* add 0101 mfm data*/
  187. mfm = mfm_encode(data, len, false);
  188. count = len * 2 + 2;
  189. msm_enable_fast_timer();
  190. local_irq_save(flags);
  191. ret = dock_send_bits(s, mfm, count, MFM_DELAY_NS);
  192. if (!ret) {
  193. dock_in();
  194. if (dock_sync(s, MFM_DELAY_NS * 5))
  195. ret = dock_get_bits(s, retlen * 2, &err);
  196. else
  197. ret = -1;
  198. dock_out(s->level);
  199. }
  200. local_irq_restore(flags);
  201. dock_delay((ret < 0) ? MFM_DELAY_NS * 6 : MFM_DELAY_NS * 2);
  202. msm_disable_fast_timer();
  203. if (ret < 0) {
  204. pr_warning("dock_command: %x: no response\n", cmd);
  205. return ret;
  206. }
  207. data = mfm_decode(ret);
  208. mfm = mfm_encode(data, retlen, true);
  209. if (mfm != ret || err) {
  210. pr_warning("dock_command: %x: bad response, "
  211. "data %x, mfm %x %x, err %d\n",
  212. cmd, data, mfm, ret, err);
  213. return -EIO;
  214. }
  215. return data;
  216. }
  217. static int dock_command_retry(struct dock_state *s, u16 cmd, size_t len, size_t retlen)
  218. {
  219. int retry = 20;
  220. int ret;
  221. while (retry--) {
  222. ret = dock_command(s, cmd, len, retlen);
  223. if (ret >= 0)
  224. return ret;
  225. if (retry != 19)
  226. msleep(10);
  227. }
  228. s->dock_connected_unknown = true;
  229. return -EIO;
  230. }
  231. static int dock_read_single(struct dock_state *s, int addr)
  232. {
  233. int ret = -1, last;
  234. int retry = 20;
  235. while (retry--) {
  236. last = ret;
  237. ret = dock_command_retry(s, addr << 1, 6, 8);
  238. if (ret < 0 || ret == last)
  239. return ret;
  240. }
  241. return -EIO;
  242. }
  243. static int dock_read_multi(struct dock_state *s, int addr, u8 *data, size_t len)
  244. {
  245. int ret;
  246. int i;
  247. u8 suml, sumr = -1;
  248. int retry = 20;
  249. while (retry--) {
  250. suml = 0;
  251. for (i = 0; i <= len; i++) {
  252. ret = dock_command_retry(s, (addr + i) << 1, 6, 8);
  253. if (ret < 0)
  254. return ret;
  255. if (i < len) {
  256. data[i] = ret;
  257. suml += ret;
  258. } else
  259. sumr = ret;
  260. }
  261. if (sumr == suml)
  262. return 0;
  263. pr_warning("dock_read_multi(%x): bad checksum, %x != %x\n",
  264. addr, sumr, suml);
  265. }
  266. return -EIO;
  267. }
  268. static int dock_write_byte(struct dock_state *s, int addr, u8 data)
  269. {
  270. return dock_command_retry(s, 1 | addr << 1 | data << 4, 6 + 8, 1);
  271. }
  272. static int dock_write_multi(struct dock_state *s, int addr, u8 *data, size_t len)
  273. {
  274. int ret;
  275. int i;
  276. u8 sum;
  277. int retry = 2;
  278. while (retry--) {
  279. sum = 0;
  280. for (i = 0; i < len; i++) {
  281. sum += data[i];
  282. ret = dock_write_byte(s, addr + i, data[i]);
  283. if (ret < 0)
  284. return ret;
  285. }
  286. ret = dock_write_byte(s, addr + len, sum);
  287. if (ret <= 0)
  288. return ret;
  289. }
  290. return -EIO;
  291. }
  292. static int dock_acquire(struct dock_state *s)
  293. {
  294. mutex_lock(&s->lock);
  295. dock_in();
  296. if (dock_read()) {
  297. /* Allow some time for the dock pull-down resistor to discharge
  298. * the capasitor.
  299. */
  300. msleep(20);
  301. if (dock_read()) {
  302. mutex_unlock(&s->lock);
  303. return -ENOENT;
  304. }
  305. }
  306. dock_out(0);
  307. s->level = false;
  308. return 0;
  309. }
  310. static void dock_release(struct dock_state *s)
  311. {
  312. dock_in();
  313. mutex_unlock(&s->lock);
  314. }
  315. enum {
  316. DOCK_TYPE = 0x0,
  317. DOCK_BT_ADDR = 0x1, /* - 0x7 */
  318. DOCK_PIN_CODE = 0x0,
  319. };
  320. static ssize_t bt_addr_show(struct device *dev, struct device_attribute *attr,
  321. char *buf)
  322. {
  323. int ret;
  324. u8 bt_addr[6];
  325. ret = dock_acquire(&ds);
  326. if (ret < 0)
  327. return ret;
  328. ret = dock_read_multi(&ds, DOCK_BT_ADDR, bt_addr, 6);
  329. dock_release(&ds);
  330. if (ret < 0)
  331. return ret;
  332. return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
  333. bt_addr[0], bt_addr[1], bt_addr[2],
  334. bt_addr[3], bt_addr[4], bt_addr[5]);
  335. }
  336. static DEVICE_ATTR(bt_addr, S_IRUGO | S_IWUSR, bt_addr_show, NULL);
  337. static ssize_t bt_pin_store(struct device *dev, struct device_attribute *attr,
  338. const char *buf, size_t size)
  339. {
  340. int ret, i;
  341. u8 pin[4];
  342. if (size < 4)
  343. return -EINVAL;
  344. for (i = 0; i < sizeof(pin); i++) {
  345. if ((pin[i] = buf[i] - '0') > 10)
  346. return -EINVAL;
  347. }
  348. ret = dock_acquire(&ds);
  349. if (ret < 0)
  350. return ret;
  351. ret = dock_write_multi(&ds, DOCK_PIN_CODE, pin, 4);
  352. dock_release(&ds);
  353. if (ret < 0)
  354. return ret;
  355. return size;
  356. }
  357. static DEVICE_ATTR(bt_pin, S_IRUGO | S_IWUSR, NULL, bt_pin_store);
  358. static int power_get_property(struct power_supply *psy,
  359. enum power_supply_property psp,
  360. union power_supply_propval *val)
  361. {
  362. if (psp != POWER_SUPPLY_PROP_ONLINE)
  363. return -EINVAL;
  364. if (psy->type == POWER_SUPPLY_TYPE_MAINS)
  365. val->intval = (vbus_present && (usb_status == 2 || dock_mains));
  366. else
  367. val->intval = vbus_present;
  368. return 0;
  369. }
  370. static enum power_supply_property power_properties[] = {
  371. POWER_SUPPLY_PROP_ONLINE,
  372. };
  373. static struct power_supply ac_supply = {
  374. .name = "ac",
  375. .type = POWER_SUPPLY_TYPE_MAINS,
  376. .supplied_to = supply_list,
  377. .num_supplicants = ARRAY_SIZE(supply_list),
  378. .properties = power_properties,
  379. .num_properties = ARRAY_SIZE(power_properties),
  380. .get_property = power_get_property,
  381. };
  382. static struct power_supply usb_supply = {
  383. .name = "usb",
  384. .type = POWER_SUPPLY_TYPE_USB,
  385. .supplied_to = supply_list,
  386. .num_supplicants = ARRAY_SIZE(supply_list),
  387. .properties = power_properties,
  388. .num_properties = ARRAY_SIZE(power_properties),
  389. .get_property = power_get_property,
  390. };
  391. /* rpc related */
  392. #define APP_BATT_PDEV_NAME "rs30100001:00000000"
  393. #define APP_BATT_PROG 0x30100001
  394. #define APP_BATT_VER MSM_RPC_VERS(0,0)
  395. #define HTC_PROCEDURE_BATTERY_NULL 0
  396. #define HTC_PROCEDURE_GET_BATT_LEVEL 1
  397. #define HTC_PROCEDURE_GET_BATT_INFO 2
  398. #define HTC_PROCEDURE_GET_CABLE_STATUS 3
  399. #define HTC_PROCEDURE_SET_BATT_DELTA 4
  400. static struct msm_rpc_endpoint *endpoint;
  401. struct battery_info_reply {
  402. u32 batt_id; /* Battery ID from ADC */
  403. u32 batt_vol; /* Battery voltage from ADC */
  404. u32 batt_temp; /* Battery Temperature (C) from formula and ADC */
  405. u32 batt_current; /* Battery current from ADC */
  406. u32 level; /* formula */
  407. u32 charging_source; /* 0: no cable, 1:usb, 2:AC */
  408. u32 charging_enabled; /* 0: Disable, 1: Enable */
  409. u32 full_bat; /* Full capacity of battery (mAh) */
  410. };
  411. static void dock_work_proc(struct work_struct *work)
  412. {
  413. int dockid;
  414. if (!vbus_present || dock_acquire(&ds))
  415. goto no_dock;
  416. if (ds.dock_connected_unknown) {
  417. /* force a new dock notification if a command failed */
  418. switch_set_state(&dock_switch, 0);
  419. ds.dock_connected_unknown = false;
  420. }
  421. dockid = dock_read_single(&ds, DOCK_TYPE);
  422. dock_release(&ds);
  423. pr_info("Detected dock with ID %02x\n", dockid);
  424. if (dockid >= 0) {
  425. msm_hsusb_set_vbus_state(0);
  426. dock_mains = !!(dockid & 0x80);
  427. switch_set_state(&dock_switch, (dockid & 1) ? 2 : 1);
  428. goto done;
  429. }
  430. no_dock:
  431. dock_mains = false;
  432. switch_set_state(&dock_switch, 0);
  433. msm_hsusb_set_vbus_state(vbus_present);
  434. done:
  435. power_supply_changed(&ac_supply);
  436. power_supply_changed(&usb_supply);
  437. wake_unlock(&dock_work_wake_lock);
  438. }
  439. static int htc_battery_probe(struct platform_device *pdev)
  440. {
  441. struct rpc_request_hdr req;
  442. struct htc_get_batt_info_rep {
  443. struct rpc_reply_hdr hdr;
  444. struct battery_info_reply info;
  445. } rep;
  446. int rc;
  447. endpoint = msm_rpc_connect(APP_BATT_PROG, APP_BATT_VER, 0);
  448. if (IS_ERR(endpoint)) {
  449. printk(KERN_ERR "%s: init rpc failed! rc = %ld\n",
  450. __FUNCTION__, PTR_ERR(endpoint));
  451. return PTR_ERR(endpoint);
  452. }
  453. /* must do this or we won't get cable status updates */
  454. rc = msm_rpc_call_reply(endpoint, HTC_PROCEDURE_GET_BATT_INFO,
  455. &req, sizeof(req),
  456. &rep, sizeof(rep),
  457. 5 * HZ);
  458. if (rc < 0)
  459. printk(KERN_ERR "%s: get info failed\n", __FUNCTION__);
  460. power_supply_register(&pdev->dev, &ac_supply);
  461. power_supply_register(&pdev->dev, &usb_supply);
  462. INIT_WORK(&dock_work, dock_work_proc);
  463. dock_wq = create_singlethread_workqueue("dock");
  464. return 0;
  465. }
  466. static struct platform_driver htc_battery_driver = {
  467. .probe = htc_battery_probe,
  468. .driver = {
  469. .name = APP_BATT_PDEV_NAME,
  470. .owner = THIS_MODULE,
  471. },
  472. };
  473. /* batt_mtoa server definitions */
  474. #define BATT_MTOA_PROG 0x30100000
  475. #define BATT_MTOA_VERS 0
  476. #define RPC_BATT_MTOA_NULL 0
  477. #define RPC_BATT_MTOA_SET_CHARGING_PROC 1
  478. #define RPC_BATT_MTOA_CABLE_STATUS_UPDATE_PROC 2
  479. #define RPC_BATT_MTOA_LEVEL_UPDATE_PROC 3
  480. struct rpc_batt_mtoa_cable_status_update_args {
  481. int status;
  482. };
  483. static int handle_battery_call(struct msm_rpc_server *server,
  484. struct rpc_request_hdr *req, unsigned len)
  485. {
  486. struct rpc_batt_mtoa_cable_status_update_args *args;
  487. if (req->procedure != RPC_BATT_MTOA_CABLE_STATUS_UPDATE_PROC)
  488. return 0;
  489. args = (struct rpc_batt_mtoa_cable_status_update_args *)(req + 1);
  490. args->status = be32_to_cpu(args->status);
  491. pr_info("cable_status_update: status=%d\n",args->status);
  492. args->status = !!args->status;
  493. vbus_present = args->status;
  494. wake_lock(&dock_work_wake_lock);
  495. queue_work(dock_wq, &dock_work);
  496. return 0;
  497. }
  498. void notify_usb_connected(int status)
  499. {
  500. printk("### notify_usb_connected(%d) ###\n", status);
  501. usb_status = status;
  502. power_supply_changed(&ac_supply);
  503. power_supply_changed(&usb_supply);
  504. }
  505. int is_ac_power_supplied(void)
  506. {
  507. return vbus_present && (usb_status == 2 || dock_mains);
  508. }
  509. static struct msm_rpc_server battery_server = {
  510. .prog = BATT_MTOA_PROG,
  511. .vers = BATT_MTOA_VERS,
  512. .rpc_call = handle_battery_call,
  513. };
  514. static int __init htc_battery_init(void)
  515. {
  516. int ret;
  517. gpio_request(_GPIO_DOCK, "dock");
  518. dock_in();
  519. wake_lock_init(&dock_work_wake_lock, WAKE_LOCK_SUSPEND, "dock");
  520. platform_driver_register(&htc_battery_driver);
  521. msm_rpc_create_server(&battery_server);
  522. if (switch_dev_register(&dock_switch) == 0) {
  523. ret = device_create_file(dock_switch.dev, &dev_attr_bt_addr);
  524. WARN_ON(ret);
  525. ret = device_create_file(dock_switch.dev, &dev_attr_bt_pin);
  526. WARN_ON(ret);
  527. }
  528. return 0;
  529. }
  530. module_init(htc_battery_init);
  531. MODULE_DESCRIPTION("HTC Battery Driver");
  532. MODULE_LICENSE("GPL");