s62x.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772
  1. /* s62x.c - s62x compass driver
  2. *
  3. * This software is licensed under the terms of the GNU General Public
  4. * License version 2, as published by the Free Software Foundation, and
  5. * may be copied, distributed, and modified under those terms.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/version.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/i2c.h>
  15. #include <linux/slab.h>
  16. #include <linux/irq.h>
  17. #include <linux/miscdevice.h>
  18. #include <linux/uaccess.h>
  19. #include <linux/atomic.h>
  20. #include <linux/delay.h>
  21. #include <linux/input.h>
  22. #include <linux/workqueue.h>
  23. #include <linux/kobject.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/proc_fs.h>
  26. #include <cust_mag.h>
  27. #include "mag.h"
  28. /*----------------------------------------------------------------------------*/
  29. /****** Begin of Customization ****/
  30. /* #define USE_ALTERNATE_ADDRESS //can change i2c address when the first(0x0c<<1) conflig whit other devices */
  31. /* #define FORCE_KERNEL2X_STYLE //auto fit android version(cause the different i2c flow) */
  32. /****** End of Customization ******/
  33. #define PLATFORM_DRIVER_NAME "msensor"
  34. /* The following items are for internal testing only.
  35. -USE_ALTERNATE_ADDRESS: (--)default (+*)test S
  36. +USE_ALTERNATE_ADDRESS: (--)default (+-)test S (-+)test A
  37. */
  38. /* #define _MAGIC_KPT_COMMAND */
  39. /* #define _FORCE_PROBE_ERROR */
  40. /*----------------------------------------------------------------------------*/
  41. #define S62X_I2C_ADDR1 (0x0e)
  42. #define S62X_I2C_ADDR2 (0x1e)
  43. #ifdef USE_ALTERNATE_ADDRESS
  44. #define S62X_I2C_ADDRESS S62X_I2C_ADDR2
  45. #else
  46. #define S62X_I2C_ADDRESS S62X_I2C_ADDR1
  47. #endif
  48. #define S62X_DEV_NAME "s62x"
  49. #define DRIVER_VERSION "2.0.0"
  50. /*----------------------------------------------------------------------------*/
  51. #define DEBUG 0
  52. #define S62X_DEBUG 1
  53. #define S62X_DEBUG_MSG 1
  54. #define S62X_DEBUG_FUNC 1
  55. #define S62X_DEBUG_DATA 1
  56. #define S62X_RETRY_COUNT 9
  57. #define S62X_DEFAULT_DELAY 100
  58. #if S62X_DEBUG_MSG
  59. #define SSMDBG(format, ...) pr_debug("S62X " format "\n", ## __VA_ARGS__)
  60. #else
  61. #define SSMDBG(format, ...)
  62. #endif
  63. #if S62X_DEBUG_FUNC
  64. #define SSMFUNC(func) pr_debug("S62X " func " is called\n")
  65. #else
  66. #define SSMFUNC(func)
  67. #endif
  68. #define SSMERR(format, ...) pr_err("S62X " format "\n", ## __VA_ARGS__)
  69. /* Don't change this if you don't know why! (refer comment:ticket:35:2) */
  70. #define PROJECT_ID "S628"
  71. /*----------------------------------------------------------------------------*/
  72. #define SENSOR_DATA_SIZE 6
  73. #define SENSOR_DATA_COUNT (SENSOR_DATA_SIZE/sizeof(short))
  74. #define CALIBRATION_DATA_SIZE 12
  75. #define RWBUF_SIZE 96
  76. #define S62X_BUFSIZE 96
  77. #define CONVERT_O 1
  78. #define CONVERT_O_DIV 1
  79. #define CONVERT_M 5
  80. #define CONVERT_M_DIV 28
  81. /*----------------------------------------------------------------------------*/
  82. #define SS_SENSOR_MODE_OFF 0
  83. #define SS_SENSOR_MODE_MEASURE 1
  84. /*----------------------------------------------------------------------------*/
  85. #define S62X_IDX_DEVICE_ID 0x00
  86. #define DEVICE_ID_VALUE 0x21
  87. #define S62X_IDX_DEVICE_INFO 0x01
  88. #define DEVICE_INFO_VALUE 0x10
  89. #define S62X_IDX_STA1 0x02
  90. #define STA1_DRDY 0x01
  91. #define S62X_IDX_X_LSB 0x03
  92. #define S62X_IDX_STA2 0x09
  93. #define S62X_IDX_MODE 0x0A
  94. #define MODE_TRIGGER 0x01
  95. #define S62X_IDX_I2CDIS 0x0F
  96. #define I2CDIS_CIC 0x00
  97. #define I2CDIS_ADC 0x01
  98. #define S62X_IDX_SET_RESET 0x1A
  99. #define SET_RESET_SET 0x01
  100. #define SET_RESET_RESET 0x02
  101. #define S62X_IDX_SET_RESET_CON 0x1C
  102. #define S62X_IDX_VBGSEL 0x1D
  103. #define S62X_IDX_OSC_TRIM 0x1E
  104. #define S62X_IDX_ECO1 0x1F
  105. #ifdef USE_ALTERNATE_ADDRESS
  106. #define ECO1_DEFAULT 0x44
  107. #else
  108. #define ECO1_DEFAULT 0x40
  109. #endif
  110. #define S62X_IDX_ECO2 0x20
  111. #define ECO2_MRAS_NO_RST 0x80
  112. #define S62X_IDX_CHOP 0x21
  113. #define S62X_IDX_BIAS 0x23
  114. #define S62X_IDX_LDO_SEL 0x24
  115. #define S62X_IDX_DATA_POL 0x25
  116. #define S62X_IDX_ADC_RDY_CNT 0x27
  117. #define S62X_IDX_W2 0x28
  118. #define S62X_IDX_PW_VALUE 0x35
  119. #define S62X_IDX_PROBE_OE 0x37
  120. #define PROBE_OE_WATCHDOG 0x10
  121. #define S62X_MUL_X 20
  122. #define S62X_DIV_X 28
  123. #define S62X_OFF_X 2048
  124. #define S62X_MUL_Y 20
  125. #define S62X_DIV_Y 28
  126. #define S62X_OFF_Y 2048
  127. #define S62X_MUL_Z 20
  128. #define S62X_DIV_Z 32
  129. #define S62X_OFF_Z 2048
  130. /*----------------------------------------------------------------------------*/
  131. static struct i2c_client *this_client;
  132. static short last_m_data[SENSOR_DATA_COUNT];
  133. static struct mutex last_m_data_mutex;
  134. static short sensor_data[CALIBRATION_DATA_SIZE];
  135. static struct mutex sensor_data_mutex;
  136. static DECLARE_WAIT_QUEUE_HEAD(open_wq);
  137. static short ssmd_delay = S62X_DEFAULT_DELAY;
  138. static char ssmd_status[RWBUF_SIZE];
  139. static atomic_t open_flag = ATOMIC_INIT(0);
  140. static atomic_t m_flag = ATOMIC_INIT(0);
  141. static atomic_t o_flag = ATOMIC_INIT(0);
  142. static atomic_t m_get_data;
  143. static atomic_t o_get_data;
  144. static atomic_t dev_open_count;
  145. static atomic_t init_phase = ATOMIC_INIT(2); /* 1 = id check ok, 0 = init ok */
  146. /*----------------------------------------------------------------------------*/
  147. static const struct i2c_device_id s62x_i2c_id[] = { {S62X_DEV_NAME, 0}, {} };
  148. /*
  149. static unsigned short s62x_force[] = { 0x00, S62X_I2C_ADDRESS, I2C_CLIENT_END, I2C_CLIENT_END };
  150. static const unsigned short *const s62x_forces[] = { s62x_force, NULL };
  151. */
  152. struct mag_hw mag_cust;
  153. static struct mag_hw *hw = &mag_cust;
  154. /*----------------------------------------------------------------------------*/
  155. static int s62x_i2c_probe(struct i2c_client *client,
  156. const struct i2c_device_id *id);
  157. static int s62x_i2c_remove(struct i2c_client *client);
  158. static int s62x_i2c_detect(struct i2c_client *client,
  159. struct i2c_board_info *info);
  160. static int s62x_suspend(struct i2c_client *client, pm_message_t msg);
  161. static int s62x_resume(struct i2c_client *client);
  162. static int s62x_local_init(void);
  163. static int s62x_local_remove(void);
  164. /*----------------------------------------------------------------------------*/
  165. enum SS_TRACE {
  166. SS_FUN_DEBUG = 0x01,
  167. SS_DATA_DEBUG = 0X02,
  168. SS_HWM_DEBUG = 0X04,
  169. SS_CTR_DEBUG = 0X08,
  170. SS_I2C_DEBUG = 0x10,
  171. };
  172. /*----------------------------------------------------------------------------*/
  173. struct s62x_i2c_data {
  174. struct i2c_client *client;
  175. struct mag_hw *hw;
  176. atomic_t layout;
  177. atomic_t trace;
  178. struct hwmsen_convert cvt;
  179. };
  180. #define L2CHIP(x) ((x)/10) /* layout to chip id */
  181. #define L2CVTI(x) ((x)%10) /* layout to cvt index */
  182. static const struct of_device_id msensor_of_match[] = {
  183. { .compatible = "mediatek,msensor", },
  184. {},
  185. };
  186. /*----------------------------------------------------------------------------*/
  187. static struct i2c_driver s62x_i2c_driver = {
  188. .driver = {
  189. /*.owner = THIS_MODULE, */
  190. .name = S62X_DEV_NAME,
  191. .of_match_table = msensor_of_match,
  192. },
  193. .probe = s62x_i2c_probe,
  194. .remove = s62x_i2c_remove,
  195. .detect = s62x_i2c_detect,
  196. .suspend = s62x_suspend,
  197. .resume = s62x_resume,
  198. .id_table = s62x_i2c_id,
  199. };
  200. static struct platform_driver ssm_sensor_driver = {
  201. .driver = {
  202. .name = "msensor",
  203. .of_match_table = msensor_of_match,
  204. }
  205. };
  206. static struct mag_init_info s62x_init_info = {
  207. .name = S62X_DEV_NAME,
  208. .init = s62x_local_init,
  209. .uninit = s62x_local_remove,
  210. .platform_diver_addr = &ssm_sensor_driver,
  211. };
  212. /*----------------------------------------------------------------------------*/
  213. static void s62x_power(struct mag_hw *hw, unsigned int on)
  214. {
  215. }
  216. /*----------------------------------------------------------------------------*/
  217. static int I2C_RxData(char *rxData, int length)
  218. {
  219. uint8_t loop_i;
  220. #if DEBUG
  221. int i;
  222. struct i2c_client *client = this_client;
  223. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  224. char addr = rxData[0];
  225. #endif
  226. /* Caller should check parameter validity. */
  227. if ((rxData == NULL) || (length < 1))
  228. return -EINVAL;
  229. for (loop_i = 0; loop_i < S62X_RETRY_COUNT; loop_i++) {
  230. this_client->addr =
  231. (this_client->addr & I2C_MASK_FLAG) | I2C_WR_FLAG;
  232. if (i2c_master_send
  233. (this_client, (const char *)rxData,
  234. ((length << 0X08) | 0X01))) {
  235. break;
  236. }
  237. mdelay(20);
  238. }
  239. if (loop_i >= S62X_RETRY_COUNT) {
  240. SSMERR("%s retry over %d\n", __func__, S62X_RETRY_COUNT);
  241. return -EIO;
  242. }
  243. #if DEBUG
  244. if (atomic_read(&data->trace) & SS_I2C_DEBUG) {
  245. SSMDBG("RxData len=%02x addr=%02x\n data=",
  246. length, addr);
  247. for (i = 0; i < length; i++)
  248. SSMDBG(" %02x", rxData[i]);
  249. SSMDBG("\n");
  250. }
  251. #endif
  252. return 0;
  253. }
  254. static int I2C_TxData(char *txData, int length)
  255. {
  256. uint8_t loop_i;
  257. #if DEBUG
  258. int i;
  259. struct i2c_client *client = this_client;
  260. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  261. #endif
  262. /* Caller should check parameter validity. */
  263. if ((txData == NULL) || (length < 2))
  264. return -EINVAL;
  265. this_client->addr = this_client->addr & I2C_MASK_FLAG;
  266. for (loop_i = 0; loop_i < S62X_RETRY_COUNT; loop_i++) {
  267. if (i2c_master_send(this_client, (const char *)txData, length) >
  268. 0) {
  269. break;
  270. }
  271. mdelay(10);
  272. }
  273. if (loop_i >= S62X_RETRY_COUNT) {
  274. SSMERR("%s retry over %d\n", __func__, S62X_RETRY_COUNT);
  275. return -EIO;
  276. }
  277. #if DEBUG
  278. if (atomic_read(&data->trace) & SS_I2C_DEBUG) {
  279. SSMDBG("TxData len=%02x addr=%02x\n data=",
  280. length, txData[0]);
  281. for (i = 0; i < (length - 1); i++)
  282. SSMDBG(" %02x", txData[i + 1]);
  283. SSMDBG("\n");
  284. }
  285. #endif
  286. return 0;
  287. }
  288. static int I2C_TxData2(unsigned char c1, unsigned char c2)
  289. {
  290. unsigned char data[2];
  291. data[0] = c1;
  292. data[1] = c2;
  293. return I2C_TxData(data, 2);
  294. }
  295. static int ECS_InitDevice(void)
  296. {
  297. char *err_desc = NULL;
  298. if (I2C_TxData2(S62X_IDX_BIAS, 0x00) < 0) {
  299. err_desc = "BIAS";
  300. goto end_of_func;
  301. }
  302. if (I2C_TxData2(S62X_IDX_VBGSEL, 0x70) < 0) {
  303. err_desc = "VBGSEL";
  304. goto end_of_func;
  305. }
  306. if (I2C_TxData2(S62X_IDX_OSC_TRIM, 0x00) < 0) {
  307. err_desc = "OSC_TRIM";
  308. goto end_of_func;
  309. }
  310. if (I2C_TxData2(S62X_IDX_ECO1, ECO1_DEFAULT) < 0) {
  311. err_desc = "ECO1";
  312. goto end_of_func;
  313. }
  314. if (I2C_TxData2(S62X_IDX_ECO2, 0x04) < 0) {
  315. err_desc = "ECO2";
  316. goto end_of_func;
  317. }
  318. if (I2C_TxData2(S62X_IDX_CHOP, 0x05) < 0) {
  319. err_desc = "CHOP";
  320. goto end_of_func;
  321. }
  322. if (I2C_TxData2(S62X_IDX_LDO_SEL, 0x13) < 0) {
  323. err_desc = "LDO_SEL";
  324. goto end_of_func;
  325. }
  326. if (I2C_TxData2(S62X_IDX_PW_VALUE, 0x5f) < 0) {
  327. err_desc = "PW_VALUE";
  328. goto end_of_func;
  329. }
  330. if (I2C_TxData2(S62X_IDX_SET_RESET_CON, 0x80) < 0) {
  331. err_desc = "SET_RESET_CON";
  332. goto end_of_func;
  333. }
  334. if (I2C_TxData2(S62X_IDX_DATA_POL, 0x00) < 0) {
  335. err_desc = "DATA_POL";
  336. goto end_of_func;
  337. }
  338. if (I2C_TxData2(S62X_IDX_ADC_RDY_CNT, 0x03) < 0) {
  339. err_desc = "ADC_RDY_CNT";
  340. goto end_of_func;
  341. }
  342. if (I2C_TxData2(S62X_IDX_W2, 0x20) < 0) {
  343. err_desc = "W2";
  344. goto end_of_func;
  345. }
  346. if (I2C_TxData2(S62X_IDX_PROBE_OE, 0x20 | PROBE_OE_WATCHDOG) < 0) {
  347. err_desc = "PROBE_OE";
  348. goto end_of_func;
  349. }
  350. end_of_func:
  351. if (err_desc) {
  352. SSMERR("S62X_IDX_%s failed\n", err_desc);
  353. return -EFAULT;
  354. }
  355. #if DEBUG
  356. {
  357. struct i2c_client *client = this_client;
  358. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  359. if ((atomic_read(&data->trace) & 0xF000) == 0x9000)
  360. return -EFAULT;
  361. atomic_set(&init_phase, 0);
  362. }
  363. #endif
  364. return 0;
  365. }
  366. static int ECS_SetMode_Off(void)
  367. {
  368. char *err_desc = NULL;
  369. if (I2C_TxData2(S62X_IDX_MODE, 0x00) < 0) {
  370. err_desc = "MODE";
  371. goto end_of_func;
  372. }
  373. if (I2C_TxData2(S62X_IDX_ECO2, 0x04) < 0) {
  374. err_desc = "ECO2";
  375. goto end_of_func;
  376. }
  377. if (I2C_TxData2(S62X_IDX_I2CDIS, I2CDIS_CIC) < 0) {
  378. err_desc = "ECO2";
  379. goto end_of_func;
  380. }
  381. end_of_func:
  382. if (err_desc) {
  383. SSMERR("S62X_IDX_%s failed\n", err_desc);
  384. return -EFAULT;
  385. }
  386. return 0;
  387. }
  388. static int ECS_SetMode_Measure(void)
  389. {
  390. char *err_desc = NULL;
  391. if (I2C_TxData2(S62X_IDX_I2CDIS, I2CDIS_ADC) < 0) {
  392. err_desc = "I2CDIS";
  393. goto end_of_func;
  394. }
  395. if (I2C_TxData2(S62X_IDX_ECO2, 0x04 | ECO2_MRAS_NO_RST) < 0) {
  396. err_desc = "ECO2";
  397. goto end_of_func;
  398. }
  399. if (I2C_TxData2(S62X_IDX_MODE, MODE_TRIGGER) < 0) {
  400. err_desc = "MODE";
  401. goto end_of_func;
  402. }
  403. end_of_func:
  404. if (err_desc) {
  405. SSMERR("S62X_IDX_%s failed\n", err_desc);
  406. return -EFAULT;
  407. }
  408. return 0;
  409. }
  410. static int ECS_SetMode(char mode)
  411. {
  412. int ret;
  413. switch (mode) {
  414. case SS_SENSOR_MODE_OFF:
  415. ret = ECS_SetMode_Off();
  416. break;
  417. case SS_SENSOR_MODE_MEASURE:
  418. ret = ECS_SetMode_Measure();
  419. break;
  420. default:
  421. SSMDBG("%s: Unknown mode(%d)", __func__, mode);
  422. return -EINVAL;
  423. }
  424. return ret;
  425. }
  426. static int ECS_CheckDevice(void)
  427. {
  428. char id1, id2;
  429. int err;
  430. id1 = S62X_IDX_DEVICE_ID;
  431. err = I2C_RxData(&id1, 1);
  432. if (err < 0)
  433. return err;
  434. id2 = S62X_IDX_DEVICE_INFO;
  435. err = I2C_RxData(&id2, 1);
  436. if (err < 0)
  437. return err;
  438. #if DEBUG
  439. {
  440. struct i2c_client *client = this_client;
  441. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  442. if ((atomic_read(&data->trace) & 0xF000) == 0x8000)
  443. id1 = 0x00, id2 = 0x01;
  444. else
  445. atomic_set(&init_phase, 1);
  446. }
  447. #endif
  448. if (id1 != DEVICE_ID_VALUE || id2 != DEVICE_INFO_VALUE) {
  449. SSMERR("incorrect id %02X:%02X\n", id1, id2);
  450. return -EFAULT;
  451. }
  452. return 0;
  453. }
  454. static int ECS_SaveData(short *buf)
  455. {
  456. #if DEBUG
  457. struct i2c_client *client = this_client;
  458. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  459. #endif
  460. mutex_lock(&sensor_data_mutex);
  461. memcpy(sensor_data, buf, sizeof(sensor_data));
  462. mutex_unlock(&sensor_data_mutex);
  463. #if DEBUG
  464. if (atomic_read(&data->trace) & SS_HWM_DEBUG) {
  465. SSMDBG
  466. ("Get daemon data: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d!",
  467. sensor_data[0], sensor_data[1], sensor_data[2],
  468. sensor_data[3], sensor_data[4], sensor_data[5],
  469. sensor_data[6], sensor_data[7], sensor_data[8],
  470. sensor_data[9], sensor_data[10], sensor_data[11]);
  471. }
  472. #endif
  473. return 0;
  474. }
  475. #define V(c1, c2) (int)(((((unsigned)(c1))<<8)|((unsigned)(c2)))&0x0fff)
  476. static int ECS_GetData(short *mag)
  477. {
  478. int loop_i, ret;
  479. struct i2c_client *client = this_client;
  480. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  481. short v;
  482. char buf[6];
  483. for (loop_i = 0; loop_i < S62X_RETRY_COUNT; loop_i++) {
  484. buf[0] = S62X_IDX_STA1;
  485. if (I2C_RxData(buf, 1)) {
  486. SSMERR("S62X_IDX_STA1 %s fail\n", __func__);
  487. return -1;
  488. }
  489. if (buf[0] == STA1_DRDY)
  490. break;
  491. msleep(20);
  492. }
  493. if (loop_i >= S62X_RETRY_COUNT) {
  494. SSMERR("%s retry over\n", __func__);
  495. return -1;
  496. }
  497. buf[0] = S62X_IDX_X_LSB;
  498. ret = I2C_RxData(buf, sizeof(buf));
  499. if (ret < 0) {
  500. SSMERR("S62X_IDX_X_LSB %s fail\n", __func__);
  501. return -1;
  502. }
  503. v = V(buf[1], buf[0]), mag[data->cvt.map[0]] =
  504. (data->cvt.sign[0] > 0) ? v : (4095 - v);
  505. v = V(buf[5], buf[4]), mag[data->cvt.map[1]] =
  506. (data->cvt.sign[1] > 0) ? v : (4095 - v);
  507. v = V(buf[3], buf[2]), mag[data->cvt.map[2]] =
  508. (data->cvt.sign[2] > 0) ? v : (4095 - v);
  509. /* for debug only */
  510. mutex_lock(&last_m_data_mutex);
  511. memcpy(last_m_data, mag, sizeof(last_m_data));
  512. mutex_unlock(&last_m_data_mutex);
  513. #if DEBUG
  514. if (atomic_read(&data->trace) & SS_DATA_DEBUG)
  515. SSMDBG("Get device data: (%d,%d,%d)", mag[0], mag[1], mag[2]);
  516. #endif
  517. return 0;
  518. }
  519. static int ECS_GetOpenStatus(void)
  520. {
  521. wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
  522. return atomic_read(&open_flag);
  523. }
  524. static int ECS_GetCloseStatus(void)
  525. {
  526. wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0));
  527. return atomic_read(&open_flag);
  528. }
  529. /*----------------------------------------------------------------------------*/
  530. static int ECS_ReadChipInfo(char *buf, int bufsize)
  531. {
  532. static const char * const supported_chip[] = { "S628", "S628A", "S625A" };
  533. int phase = atomic_read(&init_phase);
  534. struct i2c_client *client = this_client;
  535. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  536. unsigned chip = L2CHIP(atomic_read(&data->layout));
  537. int ret;
  538. if (!buf)
  539. return -1;
  540. if (!this_client) {
  541. *buf = 0;
  542. return -2;
  543. }
  544. if (phase != 0) {
  545. *buf = 0;
  546. return -3;
  547. }
  548. if (chip < sizeof(supported_chip) / sizeof(char *))
  549. ret = sprintf(buf, supported_chip[chip]);
  550. else
  551. ret = sprintf(buf, "?");
  552. return ret;
  553. }
  554. /*----------------------------------------------------------------------------*/
  555. static ssize_t show_daemon_value(struct device_driver *ddri, char *buf)
  556. {
  557. char strbuf[S62X_BUFSIZE];
  558. sprintf(strbuf, "s62xd");
  559. return sprintf(buf, "%s", strbuf);
  560. }
  561. /*----------------------------------------------------------------------------*/
  562. static ssize_t show_chipinfo_value(struct device_driver *ddri, char *buf)
  563. {
  564. char strbuf[S62X_BUFSIZE];
  565. ECS_ReadChipInfo(strbuf, S62X_BUFSIZE);
  566. return sprintf(buf, "%s\n", strbuf);
  567. }
  568. /*----------------------------------------------------------------------------*/
  569. static ssize_t show_sensordata_value(struct device_driver *ddri, char *buf)
  570. {
  571. short mdata[SENSOR_DATA_COUNT];
  572. mutex_lock(&last_m_data_mutex);
  573. memcpy(mdata, last_m_data, sizeof(mdata));
  574. mutex_unlock(&last_m_data_mutex);
  575. return sprintf(buf, "%d %d %d\n", mdata[0], mdata[1], mdata[2]);
  576. }
  577. /*----------------------------------------------------------------------------*/
  578. static ssize_t show_posturedata_value(struct device_driver *ddri, char *buf)
  579. {
  580. short tmp[3];
  581. tmp[0] = sensor_data[0] * CONVERT_O / CONVERT_O_DIV;
  582. tmp[1] = sensor_data[1] * CONVERT_O / CONVERT_O_DIV;
  583. tmp[2] = sensor_data[2] * CONVERT_O / CONVERT_O_DIV;
  584. return sprintf(buf, "%d, %d, %d\n", tmp[0], tmp[1], tmp[2]);
  585. }
  586. /*----------------------------------------------------------------------------*/
  587. static ssize_t show_layout_value(struct device_driver *ddri, char *buf)
  588. {
  589. struct i2c_client *client = this_client;
  590. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  591. return sprintf(buf, "(%d, %d)\n[%+2d %+2d %+2d]\n[%+2d %+2d %+2d]\n",
  592. data->hw->direction, atomic_read(&data->layout),
  593. data->cvt.sign[0], data->cvt.sign[1], data->cvt.sign[2],
  594. data->cvt.map[0], data->cvt.map[1], data->cvt.map[2]);
  595. }
  596. /*----------------------------------------------------------------------------*/
  597. static ssize_t store_layout_value(struct device_driver *ddri, const char *buf,
  598. size_t count)
  599. {
  600. struct i2c_client *client = this_client;
  601. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  602. int layout = 0;
  603. int ret;
  604. ret = kstrtoint(buf, 0, &layout);
  605. if (ret < 0)
  606. SSMERR("input err\n");
  607. if (layout == 1) {
  608. atomic_set(&data->layout, layout);
  609. if (!hwmsen_get_convert(L2CVTI(layout), &data->cvt)) {
  610. SSMERR("HWMSEN_GET_CONVERT function error!\n");
  611. } else
  612. if (!hwmsen_get_convert
  613. (L2CVTI(data->hw->direction), &data->cvt)) {
  614. SSMERR("invalid layout: %d, restore to %d\n", layout,
  615. data->hw->direction);
  616. } else {
  617. SSMERR("invalid layout: (%d, %d)\n", layout,
  618. data->hw->direction);
  619. hwmsen_get_convert(0, &data->cvt);
  620. }
  621. } else {
  622. SSMERR("invalid format = '%s'\n", buf);
  623. }
  624. return count;
  625. }
  626. /*----------------------------------------------------------------------------*/
  627. static ssize_t show_status_value(struct device_driver *ddri, char *buf)
  628. {
  629. struct i2c_client *client = this_client;
  630. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  631. ssize_t len = 0;
  632. len +=
  633. snprintf(buf + len, PAGE_SIZE - len, "VERS: %s (%s)\n",
  634. DRIVER_VERSION, ssmd_status);
  635. if (data->hw) {
  636. len +=
  637. snprintf(buf + len, PAGE_SIZE - len,
  638. "CUST: %d %d (%d %d)\n", data->hw->i2c_num,
  639. data->hw->direction, data->hw->power_id,
  640. data->hw->power_vol);
  641. } else {
  642. len += snprintf(buf + len, PAGE_SIZE - len, "CUST: NULL\n");
  643. }
  644. switch (atomic_read(&init_phase)) {
  645. case 2:
  646. len +=
  647. snprintf(buf + len, PAGE_SIZE - len, "IDCK: %d\n",
  648. ECS_CheckDevice());
  649. break;
  650. case 1:
  651. len +=
  652. snprintf(buf + len, PAGE_SIZE - len, "INIT: %d\n",
  653. ECS_InitDevice());
  654. break;
  655. case 0:
  656. len +=
  657. snprintf(buf + len, PAGE_SIZE - len, "OPEN: %d (%d/%d)\n",
  658. atomic_read(&dev_open_count),
  659. atomic_read(&m_get_data),
  660. atomic_read(&o_get_data));
  661. break;
  662. }
  663. return len;
  664. }
  665. /*----------------------------------------------------------------------------*/
  666. static ssize_t show_trace_value(struct device_driver *ddri, char *buf)
  667. {
  668. ssize_t res;
  669. struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
  670. if (NULL == obj) {
  671. SSMERR("data is null!!\n");
  672. return 0;
  673. }
  674. res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&obj->trace));
  675. return res;
  676. }
  677. /*----------------------------------------------------------------------------*/
  678. static ssize_t store_trace_value(struct device_driver *ddri, const char *buf,
  679. size_t count)
  680. {
  681. struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
  682. int trace;
  683. if (NULL == obj) {
  684. SSMERR("data is null!!\n");
  685. return 0;
  686. }
  687. if (1 == sscanf(buf, "0x%x", &trace))
  688. atomic_set(&obj->trace, trace);
  689. else
  690. SSMERR("invalid content: '%s', length = %d\n", buf, count);
  691. return count;
  692. }
  693. /*----------------------------------------------------------------------------*/
  694. static DRIVER_ATTR(daemon, S_IRUGO, show_daemon_value, NULL);
  695. static DRIVER_ATTR(chipinfo, S_IRUGO, show_chipinfo_value, NULL);
  696. static DRIVER_ATTR(sensordata, S_IRUGO, show_sensordata_value, NULL);
  697. static DRIVER_ATTR(posturedata, S_IRUGO, show_posturedata_value, NULL);
  698. static DRIVER_ATTR(status, S_IRUGO, show_status_value, NULL);
  699. static DRIVER_ATTR(layout, S_IRUGO | S_IWUSR, show_layout_value,
  700. store_layout_value);
  701. static DRIVER_ATTR(trace, S_IRUGO | S_IWUSR, show_trace_value,
  702. store_trace_value);
  703. /*----------------------------------------------------------------------------*/
  704. static struct driver_attribute *s62x_attr_list[] = {
  705. &driver_attr_daemon,
  706. &driver_attr_chipinfo,
  707. &driver_attr_sensordata,
  708. &driver_attr_posturedata,
  709. &driver_attr_status,
  710. &driver_attr_layout,
  711. &driver_attr_trace,
  712. };
  713. /*----------------------------------------------------------------------------*/
  714. static int s62x_create_attr(struct device_driver *driver)
  715. {
  716. int idx, err = 0;
  717. int num = (int)(sizeof(s62x_attr_list) / sizeof(s62x_attr_list[0]));
  718. if (driver == NULL)
  719. return -EINVAL;
  720. for (idx = 0; idx < num; idx++) {
  721. err = driver_create_file(driver, s62x_attr_list[idx]);
  722. if (err != 0) {
  723. SSMERR("driver_create_file (%s) = %d\n",
  724. s62x_attr_list[idx]->attr.name, err);
  725. break;
  726. }
  727. }
  728. return err;
  729. }
  730. /*----------------------------------------------------------------------------*/
  731. static int s62x_delete_attr(struct device_driver *driver)
  732. {
  733. int idx, err = 0;
  734. int num = (int)(sizeof(s62x_attr_list) / sizeof(s62x_attr_list[0]));
  735. if (driver == NULL)
  736. return -EINVAL;
  737. for (idx = 0; idx < num; idx++)
  738. driver_remove_file(driver, s62x_attr_list[idx]);
  739. return err;
  740. }
  741. /*----------------------------------------------------------------------------*/
  742. static int s62x_open(struct inode *inode, struct file *file)
  743. {
  744. int ret = -1;
  745. #if DEBUG
  746. struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
  747. if (atomic_read(&obj->trace) & SS_CTR_DEBUG)
  748. SSMDBG("open device node");
  749. #endif
  750. atomic_inc(&dev_open_count);
  751. ret = nonseekable_open(inode, file);
  752. return ret;
  753. }
  754. /*----------------------------------------------------------------------------*/
  755. static int s62x_release(struct inode *inode, struct file *file)
  756. {
  757. #if DEBUG
  758. struct s62x_i2c_data *obj = i2c_get_clientdata(this_client);
  759. if (atomic_read(&obj->trace) & SS_CTR_DEBUG)
  760. SSMDBG("release device node");
  761. #endif
  762. atomic_dec(&dev_open_count);
  763. return 0;
  764. }
  765. /*----------------------------------------------------------------------------*/
  766. static int factory_mode(void)
  767. {
  768. /* for factory mode (without open from the Daemon and successfully initialized) */
  769. return (atomic_read(&dev_open_count) == 1
  770. && atomic_read(&init_phase) == 0);
  771. }
  772. /*----------------------------------------------------------------------------*/
  773. static long s62x_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  774. {
  775. void __user *argp = (void __user *)arg;
  776. /* NOTE: In this function the size of "char" should be 1-byte. */
  777. short mdata[SENSOR_DATA_COUNT];
  778. char rwbuf[RWBUF_SIZE];
  779. char buff[S62X_BUFSIZE];
  780. char mode;
  781. short value[12];
  782. uint32_t enable;
  783. struct hwm_sensor_data *hwm_data;
  784. short delay;
  785. int status;
  786. int ret = -1;
  787. switch (cmd) {
  788. case ECS_IOCTL_WRITE:
  789. if (argp == NULL) {
  790. SSMDBG("invalid argument.");
  791. return -EINVAL;
  792. }
  793. if (copy_from_user(rwbuf, argp, sizeof(rwbuf))) {
  794. SSMDBG("copy_from_user failed.");
  795. return -EFAULT;
  796. }
  797. if (rwbuf[0] == 0) {
  798. memset(ssmd_status, 0, sizeof(ssmd_status));
  799. strncpy(ssmd_status, &rwbuf[1],
  800. sizeof(ssmd_status) - 1);
  801. break;
  802. }
  803. if ((rwbuf[0] < 2) || (rwbuf[0] > (RWBUF_SIZE - 1))) {
  804. SSMDBG("invalid argument.");
  805. return -EINVAL;
  806. }
  807. ret = I2C_TxData(&rwbuf[1], rwbuf[0]);
  808. if (ret < 0)
  809. return ret;
  810. break;
  811. case ECS_IOCTL_READ:
  812. if (argp == NULL) {
  813. SSMDBG("invalid argument.");
  814. return -EINVAL;
  815. }
  816. if (copy_from_user(rwbuf, argp, sizeof(rwbuf))) {
  817. SSMDBG("copy_from_user failed.");
  818. return -EFAULT;
  819. }
  820. if ((rwbuf[0] < 1) || (rwbuf[0] > (RWBUF_SIZE - 1))) {
  821. SSMDBG("invalid argument.");
  822. return -EINVAL;
  823. }
  824. ret = I2C_RxData(&rwbuf[1], rwbuf[0]);
  825. if (ret < 0)
  826. return ret;
  827. if (copy_to_user(argp, rwbuf, rwbuf[0] + 1)) {
  828. SSMDBG("copy_to_user failed.");
  829. return -EFAULT;
  830. }
  831. break;
  832. case ECS_IOCTL_SET_MODE:
  833. if (argp == NULL) {
  834. SSMDBG("invalid argument.");
  835. return -EINVAL;
  836. }
  837. if (copy_from_user(&mode, argp, sizeof(mode))) {
  838. SSMDBG("copy_from_user failed.");
  839. return -EFAULT;
  840. }
  841. ret = ECS_SetMode(mode);
  842. if (ret < 0)
  843. return ret;
  844. break;
  845. case MSENSOR_IOCTL_SET_MODE:
  846. SSMDBG("arg = %d\n", (char)arg);
  847. ret = ECS_SetMode((char)arg);
  848. if (ret < 0)
  849. return ret;
  850. break;
  851. case ECS_IOCTL_GETDATA:
  852. ret = ECS_GetData(mdata);
  853. if (ret < 0)
  854. return ret;
  855. if (copy_to_user(argp, mdata, sizeof(mdata))) {
  856. SSMDBG("copy_to_user failed.");
  857. return -EFAULT;
  858. }
  859. break;
  860. case ECS_IOCTL_SET_YPR:
  861. if (argp == NULL) {
  862. SSMDBG("invalid argument.");
  863. return -EINVAL;
  864. }
  865. if (copy_from_user(value, argp, sizeof(value))) {
  866. SSMDBG("copy_from_user failed.");
  867. return -EFAULT;
  868. }
  869. ECS_SaveData(value);
  870. break;
  871. case ECS_IOCTL_GET_OPEN_STATUS:
  872. status = ECS_GetOpenStatus();
  873. SSMDBG("ECS_GetOpenStatus returned (%d)", status);
  874. if (copy_to_user(argp, &status, sizeof(status))) {
  875. SSMDBG("copy_to_user failed.");
  876. return -EFAULT;
  877. }
  878. break;
  879. case ECS_IOCTL_GET_CLOSE_STATUS:
  880. status = ECS_GetCloseStatus();
  881. SSMDBG("ECS_GetCloseStatus returned (%d)", status);
  882. if (copy_to_user(argp, &status, sizeof(status))) {
  883. SSMDBG("copy_to_user failed.");
  884. return -EFAULT;
  885. }
  886. break;
  887. case ECS_IOCTL_GET_DELAY:
  888. delay = ssmd_delay;
  889. if (copy_to_user(argp, &delay, sizeof(delay))) {
  890. SSMDBG("copy_to_user failed.");
  891. return -EFAULT;
  892. }
  893. break;
  894. case ECS_IOCTL_GET_PROJECT_NAME:
  895. if (argp == NULL) {
  896. SSMERR("IO parameter pointer is NULL!\n");
  897. break;
  898. }
  899. sprintf(buff, PROJECT_ID);
  900. status =
  901. ECS_ReadChipInfo(buff + sizeof(PROJECT_ID),
  902. S62X_BUFSIZE - sizeof(PROJECT_ID));
  903. status =
  904. status <
  905. 0 ? sizeof(PROJECT_ID) : sizeof(PROJECT_ID) + status + 1;
  906. if (copy_to_user(argp, buff, status))
  907. return -EFAULT;
  908. break;
  909. case MSENSOR_IOCTL_READ_CHIPINFO:
  910. if (argp == NULL) {
  911. SSMERR("IO parameter pointer is NULL!\n");
  912. break;
  913. }
  914. ECS_ReadChipInfo(buff, S62X_BUFSIZE);
  915. if (copy_to_user(argp, buff, strlen(buff) + 1))
  916. return -EFAULT;
  917. break;
  918. case MSENSOR_IOCTL_READ_SENSORDATA:
  919. if (argp == NULL) {
  920. SSMERR("IO parameter pointer is NULL!\n");
  921. break;
  922. }
  923. if (factory_mode()) {
  924. ret = ECS_GetData(mdata);
  925. if (ret < 0)
  926. return -EFAULT;
  927. }
  928. mutex_lock(&last_m_data_mutex);
  929. memcpy(mdata, last_m_data, sizeof(mdata));
  930. mutex_unlock(&last_m_data_mutex);
  931. mdata[0] = mdata[0] * S62X_MUL_X / S62X_DIV_X;
  932. mdata[1] = mdata[1] * S62X_MUL_Y / S62X_DIV_Y;
  933. mdata[2] = mdata[2] * S62X_MUL_Z / S62X_DIV_Z;
  934. sprintf(buff, "%x %x %x", (int)mdata[0], (int)mdata[1],
  935. (int)mdata[2]);
  936. if (copy_to_user(argp, buff, strlen(buff) + 1))
  937. return -EFAULT;
  938. break;
  939. case MSENSOR_IOCTL_SENSOR_ENABLE:
  940. if (argp == NULL) {
  941. SSMERR("IO parameter pointer is NULL!\n");
  942. break;
  943. }
  944. if (copy_from_user(&enable, argp, sizeof(enable))) {
  945. SSMDBG("copy_from_user failed.");
  946. return -EFAULT;
  947. }
  948. SSMDBG("MSENSOR_IOCTL_SENSOR_ENABLE enable=%d", enable);
  949. if (enable == 1) {
  950. atomic_set(&o_flag, 1);
  951. atomic_set(&open_flag, 1);
  952. } else {
  953. atomic_set(&o_get_data, 0);
  954. atomic_set(&o_flag, 0);
  955. if (atomic_read(&m_flag) == 0)
  956. atomic_set(&open_flag, 0);
  957. }
  958. wake_up(&open_wq);
  959. if (factory_mode()) {
  960. int mode =
  961. enable ? SS_SENSOR_MODE_MEASURE :
  962. SS_SENSOR_MODE_OFF;
  963. SSMDBG
  964. ("MSENSOR_IOCTL_SENSOR_ENABLE SetMode(%d)\n",
  965. mode);
  966. ECS_SetMode(mode);
  967. }
  968. break;
  969. case MSENSOR_IOCTL_READ_FACTORY_SENSORDATA:
  970. if (argp == NULL) {
  971. SSMERR("IO parameter pointer is NULL!\n");
  972. break;
  973. }
  974. hwm_data = (struct hwm_sensor_data *) buff;
  975. mutex_lock(&sensor_data_mutex);
  976. hwm_data->values[0] = sensor_data[0] * CONVERT_O;
  977. hwm_data->values[1] = sensor_data[1] * CONVERT_O;
  978. hwm_data->values[2] = sensor_data[2] * CONVERT_O;
  979. hwm_data->status = sensor_data[4];
  980. hwm_data->value_divide = CONVERT_O_DIV;
  981. mutex_unlock(&sensor_data_mutex);
  982. sprintf(buff, "%x %x %x %x %x", hwm_data->values[0],
  983. hwm_data->values[1], hwm_data->values[2],
  984. hwm_data->status, hwm_data->value_divide);
  985. if (copy_to_user(argp, buff, strlen(buff) + 1))
  986. return -EFAULT;
  987. break;
  988. default:
  989. SSMERR("%s not supported = 0x%x\n", __func__, cmd);
  990. return -ENOIOCTLCMD;
  991. }
  992. return 0;
  993. }
  994. /*----------------------------------------------------------------------------*/
  995. static const struct file_operations s62x_fops = {
  996. .owner = THIS_MODULE,
  997. .open = s62x_open,
  998. .release = s62x_release,
  999. .unlocked_ioctl = s62x_ioctl,
  1000. };
  1001. /*----------------------------------------------------------------------------*/
  1002. static struct miscdevice s62x_device = {
  1003. .minor = MISC_DYNAMIC_MINOR,
  1004. .name = "msensor",
  1005. .fops = &s62x_fops,
  1006. };
  1007. /*----------------------------------------------------------------------------*/
  1008. int s62x_operate(void *self, uint32_t command, void *buff_in, int size_in,
  1009. void *buff_out, int size_out, int *actualout)
  1010. {
  1011. int err = 0;
  1012. int value;
  1013. struct hwm_sensor_data *msensor_data;
  1014. #if DEBUG
  1015. struct i2c_client *client = this_client;
  1016. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  1017. #endif
  1018. #if DEBUG
  1019. if (atomic_read(&data->trace) & SS_FUN_DEBUG)
  1020. SSMFUNC("s62x_operate");
  1021. #endif
  1022. switch (command) {
  1023. case SENSOR_DELAY:
  1024. if ((buff_in == NULL) || (size_in < sizeof(int))) {
  1025. SSMERR("Set delay parameter error!\n");
  1026. err = -EINVAL;
  1027. } else {
  1028. value = *(int *)buff_in;
  1029. if (value <= 20)
  1030. ssmd_delay = 20;
  1031. ssmd_delay = value;
  1032. }
  1033. break;
  1034. case SENSOR_ENABLE:
  1035. if ((buff_in == NULL) || (size_in < sizeof(int))) {
  1036. SSMERR("Enable sensor parameter error!\n");
  1037. err = -EINVAL;
  1038. } else {
  1039. value = *(int *)buff_in;
  1040. if (value == 1) {
  1041. atomic_set(&m_flag, 1);
  1042. atomic_set(&open_flag, 1);
  1043. } else {
  1044. atomic_set(&m_get_data, 0);
  1045. atomic_set(&m_flag, 0);
  1046. if (atomic_read(&o_flag) == 0)
  1047. atomic_set(&open_flag, 0);
  1048. }
  1049. wake_up(&open_wq);
  1050. }
  1051. break;
  1052. case SENSOR_GET_DATA:
  1053. atomic_inc(&m_get_data);
  1054. if ((buff_out == NULL) || (size_out < sizeof(struct hwm_sensor_data))) {
  1055. SSMERR("get sensor data parameter error!\n");
  1056. err = -EINVAL;
  1057. } else {
  1058. msensor_data = (struct hwm_sensor_data *) buff_out;
  1059. mutex_lock(&sensor_data_mutex);
  1060. msensor_data->values[0] = sensor_data[9] * CONVERT_M;
  1061. msensor_data->values[1] = sensor_data[10] * CONVERT_M;
  1062. msensor_data->values[2] = sensor_data[11] * CONVERT_M;
  1063. msensor_data->status = sensor_data[4];
  1064. msensor_data->value_divide = CONVERT_M_DIV;
  1065. mutex_unlock(&sensor_data_mutex);
  1066. #if DEBUG
  1067. if (atomic_read(&data->trace) & SS_HWM_DEBUG) {
  1068. SSMDBG
  1069. ("Hwm get m-sensor data: %d, %d, %d. divide %d, status %d!",
  1070. msensor_data->values[0],
  1071. msensor_data->values[1],
  1072. msensor_data->values[2],
  1073. msensor_data->value_divide,
  1074. msensor_data->status);
  1075. }
  1076. #endif
  1077. }
  1078. break;
  1079. default:
  1080. SSMERR("msensor operate function no this parameter %d!\n",
  1081. command);
  1082. err = -1;
  1083. break;
  1084. }
  1085. return err;
  1086. }
  1087. /*----------------------------------------------------------------------------*/
  1088. int s62x_orientation_operate(void *self, uint32_t command, void *buff_in,
  1089. int size_in, void *buff_out, int size_out,
  1090. int *actualout)
  1091. {
  1092. int err = 0;
  1093. int value;
  1094. struct hwm_sensor_data *osensor_data;
  1095. #if DEBUG
  1096. struct i2c_client *client = this_client;
  1097. struct s62x_i2c_data *data = i2c_get_clientdata(client);
  1098. #endif
  1099. #if DEBUG
  1100. if (atomic_read(&data->trace) & SS_FUN_DEBUG)
  1101. SSMFUNC("s62x_orientation_operate");
  1102. #endif
  1103. switch (command) {
  1104. case SENSOR_DELAY:
  1105. if ((buff_in == NULL) || (size_in < sizeof(int))) {
  1106. SSMERR("Set delay parameter error!\n");
  1107. err = -EINVAL;
  1108. } else {
  1109. value = *(int *)buff_in;
  1110. if (value <= 20)
  1111. ssmd_delay = 20;
  1112. ssmd_delay = value;
  1113. }
  1114. break;
  1115. case SENSOR_ENABLE:
  1116. if ((buff_in == NULL) || (size_in < sizeof(int))) {
  1117. SSMERR("Enable sensor parameter error!\n");
  1118. err = -EINVAL;
  1119. } else {
  1120. value = *(int *)buff_in;
  1121. if (value == 1) {
  1122. atomic_set(&o_flag, 1);
  1123. atomic_set(&open_flag, 1);
  1124. } else {
  1125. atomic_set(&o_get_data, 0);
  1126. atomic_set(&o_flag, 0);
  1127. if (atomic_read(&m_flag) == 0)
  1128. atomic_set(&open_flag, 0);
  1129. }
  1130. wake_up(&open_wq);
  1131. }
  1132. break;
  1133. case SENSOR_GET_DATA:
  1134. atomic_inc(&o_get_data);
  1135. if ((buff_out == NULL) || (size_out < sizeof(struct hwm_sensor_data))) {
  1136. SSMERR("get sensor data parameter error!\n");
  1137. err = -EINVAL;
  1138. } else {
  1139. osensor_data = (struct hwm_sensor_data *) buff_out;
  1140. mutex_lock(&sensor_data_mutex);
  1141. osensor_data->values[0] = sensor_data[0] * CONVERT_O;
  1142. osensor_data->values[1] = sensor_data[1] * CONVERT_O;
  1143. osensor_data->values[2] = sensor_data[2] * CONVERT_O;
  1144. osensor_data->status = sensor_data[4];
  1145. osensor_data->value_divide = CONVERT_O_DIV;
  1146. mutex_unlock(&sensor_data_mutex);
  1147. #if DEBUG
  1148. if (atomic_read(&data->trace) & SS_HWM_DEBUG) {
  1149. SSMDBG
  1150. ("Hwm get o-sensor data: %d, %d, %d. divide %d, status %d!",
  1151. osensor_data->values[0],
  1152. osensor_data->values[1],
  1153. osensor_data->values[2],
  1154. osensor_data->value_divide,
  1155. osensor_data->status);
  1156. }
  1157. #endif
  1158. }
  1159. break;
  1160. default:
  1161. SSMERR("gsensor operate function no this parameter %d!\n",
  1162. command);
  1163. err = -1;
  1164. break;
  1165. }
  1166. return err;
  1167. }
  1168. /*----------------------------------------------------------------------------*/
  1169. static int s62x_suspend(struct i2c_client *client, pm_message_t msg)
  1170. {
  1171. struct s62x_i2c_data *obj = i2c_get_clientdata(client);
  1172. if (msg.event == PM_EVENT_SUSPEND)
  1173. s62x_power(obj->hw, 0);
  1174. return 0;
  1175. }
  1176. /*----------------------------------------------------------------------------*/
  1177. static int s62x_resume(struct i2c_client *client)
  1178. {
  1179. struct s62x_i2c_data *obj = i2c_get_clientdata(client);
  1180. s62x_power(obj->hw, 1);
  1181. return 0;
  1182. }
  1183. /*----------------------------------------------------------------------------*/
  1184. static int s62x_i2c_detect(struct i2c_client *client,
  1185. struct i2c_board_info *info)
  1186. {
  1187. strcpy(info->type, S62X_DEV_NAME);
  1188. return 0;
  1189. }
  1190. /*----------------------------------------------------------------------------*/
  1191. #ifdef _MAGIC_KPT_COMMAND
  1192. static int magic_kpt_command(const struct i2c_client *client)
  1193. {
  1194. char cmd1[] = { 0x0A, 0x00 };
  1195. char cmd2[] = { 0x0F, 0x1B };
  1196. struct i2c_msg msg[] = {
  1197. {
  1198. .addr = S62X_I2C_ADDR1,
  1199. .flags = 0,
  1200. .len = sizeof(cmd1),
  1201. .buf = cmd1,
  1202. }
  1203. ,
  1204. {
  1205. .addr = S62X_I2C_ADDR1,
  1206. .flags = 0,
  1207. .len = sizeof(cmd2),
  1208. .buf = cmd2,
  1209. }
  1210. ,
  1211. };
  1212. return i2c_transfer(client->adapter, msg, 2);
  1213. }
  1214. #endif
  1215. /*----------------------------------------------------------------------------*/
  1216. #ifdef USE_ALTERNATE_ADDRESS
  1217. static int s62x_change_address(const struct i2c_client *client)
  1218. {
  1219. uint8_t loop_i;
  1220. char cmd[] = { S62X_IDX_ECO1, ECO1_DEFAULT };
  1221. struct i2c_msg msg[] = {
  1222. {
  1223. .addr = S62X_I2C_ADDR1,
  1224. .flags = 0,
  1225. .len = sizeof(cmd),
  1226. .buf = cmd,
  1227. }
  1228. ,
  1229. };
  1230. for (loop_i = 0; loop_i < 3; loop_i++) {
  1231. if (i2c_transfer(client->adapter, msg, 1) > 0)
  1232. return 0;
  1233. mdelay(10);
  1234. }
  1235. /* SSMERR("change address retry over %d\n", loop_i); */
  1236. return -EIO;
  1237. }
  1238. #endif
  1239. static int s62x_m_enable(int en)
  1240. {
  1241. int value = 0;
  1242. int err = 0;
  1243. value = en;
  1244. if (value == 1) {
  1245. atomic_set(&m_flag, 1);
  1246. atomic_set(&open_flag, 1);
  1247. err = ECS_SetMode(SS_SENSOR_MODE_MEASURE);
  1248. if (err < 0) {
  1249. SSMDBG("%s:ECS_SetMode on Error.\n", __func__);
  1250. return err;
  1251. }
  1252. } else {
  1253. atomic_set(&m_flag, 0);
  1254. if (atomic_read(&o_flag) == 0) {
  1255. atomic_set(&open_flag, 0);
  1256. err = ECS_SetMode(SS_SENSOR_MODE_OFF);
  1257. if (err < 0) {
  1258. SSMDBG("%s:ECS_SetMode off Error.\n", __func__);
  1259. return err;
  1260. }
  1261. }
  1262. }
  1263. wake_up(&open_wq);
  1264. return err;
  1265. }
  1266. static int s62x_m_set_delay(u64 ns)
  1267. {
  1268. int value = 0;
  1269. value = (int)ns/1000/1000;
  1270. if (value <= 20)
  1271. ssmd_delay = 20;
  1272. else
  1273. ssmd_delay = value;
  1274. return 0;
  1275. }
  1276. static int s62x_m_open_report_data(int open)
  1277. {
  1278. return 0;
  1279. }
  1280. static int s62x_m_get_data(int *x , int *y, int *z, int *status)
  1281. {
  1282. mutex_lock(&sensor_data_mutex);
  1283. *x = sensor_data[9] * CONVERT_M;
  1284. *y = sensor_data[10] * CONVERT_M;
  1285. *z = sensor_data[11] * CONVERT_M;
  1286. *status = sensor_data[4];
  1287. mutex_unlock(&sensor_data_mutex);
  1288. return 0;
  1289. }
  1290. static int s62x_o_enable(int en)
  1291. {
  1292. int value = 0;
  1293. int err = 0;
  1294. value = en;
  1295. if (value == 1) {
  1296. atomic_set(&o_flag, 1);
  1297. atomic_set(&open_flag, 1);
  1298. err = ECS_SetMode(SS_SENSOR_MODE_MEASURE);
  1299. if (err < 0) {
  1300. SSMERR("%s:ECS_SetMode on Error.\n", __func__);
  1301. return err;
  1302. }
  1303. } else {
  1304. atomic_set(&o_get_data, 0);
  1305. atomic_set(&o_flag, 0);
  1306. if (atomic_read(&m_flag) == 0)
  1307. atomic_set(&open_flag, 0);
  1308. err = ECS_SetMode(SS_SENSOR_MODE_OFF);
  1309. if (err < 0) {
  1310. SSMERR("%s:ECS_SetMode off Error.\n", __func__);
  1311. return err;
  1312. }
  1313. }
  1314. wake_up(&open_wq);
  1315. return err;
  1316. }
  1317. static int s62x_o_set_delay(u64 ns)
  1318. {
  1319. int value = 0;
  1320. value = (int)ns/1000/1000;
  1321. if (value <= 20)
  1322. ssmd_delay = 20;
  1323. else
  1324. ssmd_delay = value;
  1325. return 0;
  1326. }
  1327. static int s62x_o_open_report_data(int open)
  1328. {
  1329. return 0;
  1330. }
  1331. static int s62x_o_get_data(int *x , int *y, int *z, int *status)
  1332. {
  1333. mutex_lock(&sensor_data_mutex);
  1334. *x = sensor_data[0] * CONVERT_O;
  1335. *y = sensor_data[1] * CONVERT_O;
  1336. *z = sensor_data[2] * CONVERT_O;
  1337. *status = sensor_data[4];
  1338. mutex_unlock(&sensor_data_mutex);
  1339. return 0;
  1340. }
  1341. /*----------------------------------------------------------------------------*/
  1342. static int s62x_i2c_probe(struct i2c_client *client,
  1343. const struct i2c_device_id *id)
  1344. {
  1345. struct i2c_client *new_client;
  1346. struct s62x_i2c_data *data;
  1347. int err = 0;
  1348. struct mag_control_path ctl = {0};
  1349. struct mag_data_path mag_data = {0};
  1350. data = kmalloc(sizeof(struct s62x_i2c_data), GFP_KERNEL);
  1351. if (!data) {
  1352. err = -ENOMEM;
  1353. goto exit;
  1354. }
  1355. memset(data, 0, sizeof(struct s62x_i2c_data));
  1356. data->hw = hw;
  1357. if (hwmsen_get_convert(L2CVTI(data->hw->direction), &data->cvt)) {
  1358. SSMERR("invalid direction: %d\n", data->hw->direction);
  1359. goto exit_init_failed;
  1360. }
  1361. atomic_set(&data->layout, data->hw->direction);
  1362. atomic_set(&data->trace, 0x0000);
  1363. mutex_init(&last_m_data_mutex);
  1364. mutex_init(&sensor_data_mutex);
  1365. init_waitqueue_head(&open_wq);
  1366. data->client = client;
  1367. new_client = data->client;
  1368. i2c_set_clientdata(new_client, data);
  1369. this_client = new_client;
  1370. #ifdef _MAGIC_KPT_COMMAND
  1371. magic_kpt_command(client);
  1372. #endif
  1373. #ifdef USE_ALTERNATE_ADDRESS
  1374. err = s62x_change_address(client);
  1375. SSMERR("address change %s\n", err == 0 ? "OK" : "NG");
  1376. #endif
  1377. #ifdef _FORCE_PROBE_ERROR
  1378. SSMERR("force probe error\n");
  1379. return -1;
  1380. #endif
  1381. /* Check connection */
  1382. if (ECS_CheckDevice() != 0) {
  1383. SSMERR("check device connect error\n");
  1384. } else {
  1385. atomic_set(&init_phase, 1);
  1386. if (ECS_InitDevice() != 0)
  1387. SSMERR("init device error\n");
  1388. else
  1389. atomic_set(&init_phase, 0);
  1390. }
  1391. /* Register sysfs attribute */
  1392. err = s62x_create_attr(&(s62x_init_info.platform_diver_addr->driver));
  1393. if (err != 0) {
  1394. SSMERR("create attribute err = %d\n", err);
  1395. goto exit_sysfs_create_group_failed;
  1396. }
  1397. #ifdef ENABLE_DUALSTACK_MODE
  1398. if (atomic_read(&init_phase) == 2) {
  1399. SSMERR("dual stack mode exit\n");
  1400. goto exit_init_failed;
  1401. }
  1402. #endif
  1403. err = misc_register(&s62x_device);
  1404. if (err != 0) {
  1405. SSMERR("device register failed\n");
  1406. goto exit_misc_device_register_failed;
  1407. }
  1408. ctl.is_use_common_factory = false;
  1409. ctl.m_enable = s62x_m_enable;
  1410. ctl.m_set_delay = s62x_m_set_delay;
  1411. ctl.m_open_report_data = s62x_m_open_report_data;
  1412. ctl.o_enable = s62x_o_enable;
  1413. ctl.o_set_delay = s62x_o_set_delay;
  1414. ctl.o_open_report_data = s62x_o_open_report_data;
  1415. ctl.is_report_input_direct = false;
  1416. ctl.is_support_batch = data->hw->is_batch_supported;
  1417. err = mag_register_control_path(&ctl);
  1418. if (err) {
  1419. SSMDBG("register mag control path err\n");
  1420. goto exit_kfree;
  1421. }
  1422. mag_data.div_m = CONVERT_M_DIV;
  1423. mag_data.div_o = CONVERT_O_DIV;
  1424. mag_data.get_data_o = s62x_o_get_data;
  1425. mag_data.get_data_m = s62x_m_get_data;
  1426. err = mag_register_data_path(&mag_data);
  1427. if (err) {
  1428. SSMDBG("register data control path err\n");
  1429. goto exit_kfree;
  1430. }
  1431. SSMDBG("%s: %s", __func__, atomic_read(&init_phase) ? "NG" : "OK");
  1432. return 0;
  1433. exit_sysfs_create_group_failed:
  1434. exit_init_failed:
  1435. exit_misc_device_register_failed:
  1436. exit_kfree:
  1437. kfree(data);
  1438. exit:
  1439. SSMERR("%s: err = %d\n", __func__, err);
  1440. return err;
  1441. }
  1442. /*----------------------------------------------------------------------------*/
  1443. static int s62x_i2c_remove(struct i2c_client *client)
  1444. {
  1445. int err;
  1446. err = s62x_delete_attr(&(s62x_init_info.platform_diver_addr->driver));
  1447. if (err != 0)
  1448. SSMERR("delete_attr fail: %d\n", err);
  1449. this_client = NULL;
  1450. i2c_unregister_device(client);
  1451. kfree(i2c_get_clientdata(client));
  1452. misc_deregister(&s62x_device);
  1453. return 0;
  1454. }
  1455. /*----------------------------------------------------------------------------*/
  1456. static int s62x_local_init(void)
  1457. {
  1458. s62x_power(hw, 1);
  1459. atomic_set(&dev_open_count, 0);
  1460. if (i2c_add_driver(&s62x_i2c_driver)) {
  1461. SSMERR("add driver error\n");
  1462. return -1;
  1463. }
  1464. return 0;
  1465. }
  1466. /*----------------------------------------------------------------------------*/
  1467. static int s62x_local_remove(void)
  1468. {
  1469. s62x_power(hw, 0);
  1470. atomic_set(&dev_open_count, 0);
  1471. i2c_del_driver(&s62x_i2c_driver);
  1472. return 0;
  1473. }
  1474. /*----------------------------------------------------------------------------*/
  1475. static int __init s62x_init(void)
  1476. {
  1477. const char *name = "mediatek,s62x";
  1478. hw = get_mag_dts_func(name, hw);
  1479. if (!hw)
  1480. SSMERR("get dts info fail\n");
  1481. mag_driver_add(&s62x_init_info);
  1482. return 0;
  1483. }
  1484. /*----------------------------------------------------------------------------*/
  1485. static void __exit s62x_exit(void)
  1486. {
  1487. }
  1488. /*----------------------------------------------------------------------------*/
  1489. module_init(s62x_init);
  1490. module_exit(s62x_exit);
  1491. MODULE_DESCRIPTION("S62X Compass Driver");
  1492. MODULE_LICENSE("GPL");
  1493. MODULE_VERSION(DRIVER_VERSION);