chromeos_laptop.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. // SPDX-License-Identifier: GPL-2.0+
  2. // Driver to instantiate Chromebook i2c/smbus devices.
  3. //
  4. // Copyright (C) 2012 Google, Inc.
  5. // Author: Benson Leung <[email protected]>
  6. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  7. #include <linux/acpi.h>
  8. #include <linux/dmi.h>
  9. #include <linux/i2c.h>
  10. #include <linux/input.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/ioport.h>
  13. #include <linux/module.h>
  14. #include <linux/pci.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/property.h>
  17. #define ATMEL_TP_I2C_ADDR 0x4b
  18. #define ATMEL_TP_I2C_BL_ADDR 0x25
  19. #define ATMEL_TS_I2C_ADDR 0x4a
  20. #define ATMEL_TS_I2C_BL_ADDR 0x26
  21. #define CYAPA_TP_I2C_ADDR 0x67
  22. #define ELAN_TP_I2C_ADDR 0x15
  23. #define ISL_ALS_I2C_ADDR 0x44
  24. #define TAOS_ALS_I2C_ADDR 0x29
  25. static const char *i2c_adapter_names[] = {
  26. "SMBus I801 adapter",
  27. "i915 gmbus vga",
  28. "i915 gmbus panel",
  29. "Synopsys DesignWare I2C adapter",
  30. };
  31. /* Keep this enum consistent with i2c_adapter_names */
  32. enum i2c_adapter_type {
  33. I2C_ADAPTER_SMBUS = 0,
  34. I2C_ADAPTER_VGADDC,
  35. I2C_ADAPTER_PANEL,
  36. I2C_ADAPTER_DESIGNWARE,
  37. };
  38. struct i2c_peripheral {
  39. struct i2c_board_info board_info;
  40. unsigned short alt_addr;
  41. const char *dmi_name;
  42. unsigned long irqflags;
  43. struct resource irq_resource;
  44. enum i2c_adapter_type type;
  45. u32 pci_devid;
  46. const struct property_entry *properties;
  47. struct i2c_client *client;
  48. };
  49. struct acpi_peripheral {
  50. char hid[ACPI_ID_LEN];
  51. struct software_node swnode;
  52. struct i2c_client *client;
  53. };
  54. struct chromeos_laptop {
  55. /*
  56. * Note that we can't mark this pointer as const because
  57. * i2c_new_scanned_device() changes passed in I2C board info, so.
  58. */
  59. struct i2c_peripheral *i2c_peripherals;
  60. unsigned int num_i2c_peripherals;
  61. struct acpi_peripheral *acpi_peripherals;
  62. unsigned int num_acpi_peripherals;
  63. };
  64. static const struct chromeos_laptop *cros_laptop;
  65. static struct i2c_client *
  66. chromes_laptop_instantiate_i2c_device(struct i2c_adapter *adapter,
  67. struct i2c_board_info *info,
  68. unsigned short alt_addr)
  69. {
  70. const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END };
  71. struct i2c_client *client;
  72. /*
  73. * Add the i2c device. If we can't detect it at the primary
  74. * address we scan secondary addresses. In any case the client
  75. * structure gets assigned primary address.
  76. */
  77. client = i2c_new_scanned_device(adapter, info, addr_list, NULL);
  78. if (IS_ERR(client) && alt_addr) {
  79. struct i2c_board_info dummy_info = {
  80. I2C_BOARD_INFO("dummy", info->addr),
  81. };
  82. const unsigned short alt_addr_list[] = {
  83. alt_addr, I2C_CLIENT_END
  84. };
  85. struct i2c_client *dummy;
  86. dummy = i2c_new_scanned_device(adapter, &dummy_info,
  87. alt_addr_list, NULL);
  88. if (!IS_ERR(dummy)) {
  89. pr_debug("%d-%02x is probed at %02x\n",
  90. adapter->nr, info->addr, dummy->addr);
  91. i2c_unregister_device(dummy);
  92. client = i2c_new_client_device(adapter, info);
  93. }
  94. }
  95. if (IS_ERR(client)) {
  96. client = NULL;
  97. pr_debug("failed to register device %d-%02x\n",
  98. adapter->nr, info->addr);
  99. } else {
  100. pr_debug("added i2c device %d-%02x\n",
  101. adapter->nr, info->addr);
  102. }
  103. return client;
  104. }
  105. static bool chromeos_laptop_match_adapter_devid(struct device *dev, u32 devid)
  106. {
  107. struct pci_dev *pdev;
  108. if (!dev_is_pci(dev))
  109. return false;
  110. pdev = to_pci_dev(dev);
  111. return devid == pci_dev_id(pdev);
  112. }
  113. static void chromeos_laptop_check_adapter(struct i2c_adapter *adapter)
  114. {
  115. struct i2c_peripheral *i2c_dev;
  116. int i;
  117. for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
  118. i2c_dev = &cros_laptop->i2c_peripherals[i];
  119. /* Skip devices already created */
  120. if (i2c_dev->client)
  121. continue;
  122. if (strncmp(adapter->name, i2c_adapter_names[i2c_dev->type],
  123. strlen(i2c_adapter_names[i2c_dev->type])))
  124. continue;
  125. if (i2c_dev->pci_devid &&
  126. !chromeos_laptop_match_adapter_devid(adapter->dev.parent,
  127. i2c_dev->pci_devid)) {
  128. continue;
  129. }
  130. i2c_dev->client =
  131. chromes_laptop_instantiate_i2c_device(adapter,
  132. &i2c_dev->board_info,
  133. i2c_dev->alt_addr);
  134. }
  135. }
  136. static bool chromeos_laptop_adjust_client(struct i2c_client *client)
  137. {
  138. struct acpi_peripheral *acpi_dev;
  139. struct acpi_device_id acpi_ids[2] = { };
  140. int i;
  141. int error;
  142. if (!has_acpi_companion(&client->dev))
  143. return false;
  144. for (i = 0; i < cros_laptop->num_acpi_peripherals; i++) {
  145. acpi_dev = &cros_laptop->acpi_peripherals[i];
  146. memcpy(acpi_ids[0].id, acpi_dev->hid, ACPI_ID_LEN);
  147. if (acpi_match_device(acpi_ids, &client->dev)) {
  148. error = device_add_software_node(&client->dev, &acpi_dev->swnode);
  149. if (error) {
  150. dev_err(&client->dev,
  151. "failed to add properties: %d\n",
  152. error);
  153. break;
  154. }
  155. acpi_dev->client = client;
  156. return true;
  157. }
  158. }
  159. return false;
  160. }
  161. static void chromeos_laptop_detach_i2c_client(struct i2c_client *client)
  162. {
  163. struct acpi_peripheral *acpi_dev;
  164. struct i2c_peripheral *i2c_dev;
  165. int i;
  166. if (has_acpi_companion(&client->dev))
  167. for (i = 0; i < cros_laptop->num_acpi_peripherals; i++) {
  168. acpi_dev = &cros_laptop->acpi_peripherals[i];
  169. if (acpi_dev->client == client) {
  170. acpi_dev->client = NULL;
  171. return;
  172. }
  173. }
  174. else
  175. for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
  176. i2c_dev = &cros_laptop->i2c_peripherals[i];
  177. if (i2c_dev->client == client) {
  178. i2c_dev->client = NULL;
  179. return;
  180. }
  181. }
  182. }
  183. static int chromeos_laptop_i2c_notifier_call(struct notifier_block *nb,
  184. unsigned long action, void *data)
  185. {
  186. struct device *dev = data;
  187. switch (action) {
  188. case BUS_NOTIFY_ADD_DEVICE:
  189. if (dev->type == &i2c_adapter_type)
  190. chromeos_laptop_check_adapter(to_i2c_adapter(dev));
  191. else if (dev->type == &i2c_client_type)
  192. chromeos_laptop_adjust_client(to_i2c_client(dev));
  193. break;
  194. case BUS_NOTIFY_REMOVED_DEVICE:
  195. if (dev->type == &i2c_client_type)
  196. chromeos_laptop_detach_i2c_client(to_i2c_client(dev));
  197. break;
  198. }
  199. return 0;
  200. }
  201. static struct notifier_block chromeos_laptop_i2c_notifier = {
  202. .notifier_call = chromeos_laptop_i2c_notifier_call,
  203. };
  204. #define DECLARE_CROS_LAPTOP(_name) \
  205. static const struct chromeos_laptop _name __initconst = { \
  206. .i2c_peripherals = _name##_peripherals, \
  207. .num_i2c_peripherals = ARRAY_SIZE(_name##_peripherals), \
  208. }
  209. #define DECLARE_ACPI_CROS_LAPTOP(_name) \
  210. static const struct chromeos_laptop _name __initconst = { \
  211. .acpi_peripherals = _name##_peripherals, \
  212. .num_acpi_peripherals = ARRAY_SIZE(_name##_peripherals), \
  213. }
  214. static struct i2c_peripheral samsung_series_5_550_peripherals[] __initdata = {
  215. /* Touchpad. */
  216. {
  217. .board_info = {
  218. I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
  219. .flags = I2C_CLIENT_WAKE,
  220. },
  221. .dmi_name = "trackpad",
  222. .type = I2C_ADAPTER_SMBUS,
  223. },
  224. /* Light Sensor. */
  225. {
  226. .board_info = {
  227. I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
  228. },
  229. .dmi_name = "lightsensor",
  230. .type = I2C_ADAPTER_SMBUS,
  231. },
  232. };
  233. DECLARE_CROS_LAPTOP(samsung_series_5_550);
  234. static struct i2c_peripheral samsung_series_5_peripherals[] __initdata = {
  235. /* Light Sensor. */
  236. {
  237. .board_info = {
  238. I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
  239. },
  240. .type = I2C_ADAPTER_SMBUS,
  241. },
  242. };
  243. DECLARE_CROS_LAPTOP(samsung_series_5);
  244. static const int chromebook_pixel_tp_keys[] __initconst = {
  245. KEY_RESERVED,
  246. KEY_RESERVED,
  247. KEY_RESERVED,
  248. KEY_RESERVED,
  249. KEY_RESERVED,
  250. BTN_LEFT
  251. };
  252. static const struct property_entry
  253. chromebook_pixel_trackpad_props[] __initconst = {
  254. PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
  255. PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_pixel_tp_keys),
  256. { }
  257. };
  258. static const struct property_entry
  259. chromebook_atmel_touchscreen_props[] __initconst = {
  260. PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
  261. { }
  262. };
  263. static struct i2c_peripheral chromebook_pixel_peripherals[] __initdata = {
  264. /* Touch Screen. */
  265. {
  266. .board_info = {
  267. I2C_BOARD_INFO("atmel_mxt_ts",
  268. ATMEL_TS_I2C_ADDR),
  269. .flags = I2C_CLIENT_WAKE,
  270. },
  271. .dmi_name = "touchscreen",
  272. .irqflags = IRQF_TRIGGER_FALLING,
  273. .type = I2C_ADAPTER_PANEL,
  274. .alt_addr = ATMEL_TS_I2C_BL_ADDR,
  275. .properties = chromebook_atmel_touchscreen_props,
  276. },
  277. /* Touchpad. */
  278. {
  279. .board_info = {
  280. I2C_BOARD_INFO("atmel_mxt_tp",
  281. ATMEL_TP_I2C_ADDR),
  282. .flags = I2C_CLIENT_WAKE,
  283. },
  284. .dmi_name = "trackpad",
  285. .irqflags = IRQF_TRIGGER_FALLING,
  286. .type = I2C_ADAPTER_VGADDC,
  287. .alt_addr = ATMEL_TP_I2C_BL_ADDR,
  288. .properties = chromebook_pixel_trackpad_props,
  289. },
  290. /* Light Sensor. */
  291. {
  292. .board_info = {
  293. I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
  294. },
  295. .dmi_name = "lightsensor",
  296. .type = I2C_ADAPTER_PANEL,
  297. },
  298. };
  299. DECLARE_CROS_LAPTOP(chromebook_pixel);
  300. static struct i2c_peripheral hp_chromebook_14_peripherals[] __initdata = {
  301. /* Touchpad. */
  302. {
  303. .board_info = {
  304. I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
  305. .flags = I2C_CLIENT_WAKE,
  306. },
  307. .dmi_name = "trackpad",
  308. .type = I2C_ADAPTER_DESIGNWARE,
  309. },
  310. };
  311. DECLARE_CROS_LAPTOP(hp_chromebook_14);
  312. static struct i2c_peripheral dell_chromebook_11_peripherals[] __initdata = {
  313. /* Touchpad. */
  314. {
  315. .board_info = {
  316. I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
  317. .flags = I2C_CLIENT_WAKE,
  318. },
  319. .dmi_name = "trackpad",
  320. .type = I2C_ADAPTER_DESIGNWARE,
  321. },
  322. /* Elan Touchpad option. */
  323. {
  324. .board_info = {
  325. I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR),
  326. .flags = I2C_CLIENT_WAKE,
  327. },
  328. .dmi_name = "trackpad",
  329. .type = I2C_ADAPTER_DESIGNWARE,
  330. },
  331. };
  332. DECLARE_CROS_LAPTOP(dell_chromebook_11);
  333. static struct i2c_peripheral toshiba_cb35_peripherals[] __initdata = {
  334. /* Touchpad. */
  335. {
  336. .board_info = {
  337. I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
  338. .flags = I2C_CLIENT_WAKE,
  339. },
  340. .dmi_name = "trackpad",
  341. .type = I2C_ADAPTER_DESIGNWARE,
  342. },
  343. };
  344. DECLARE_CROS_LAPTOP(toshiba_cb35);
  345. static struct i2c_peripheral acer_c7_chromebook_peripherals[] __initdata = {
  346. /* Touchpad. */
  347. {
  348. .board_info = {
  349. I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
  350. .flags = I2C_CLIENT_WAKE,
  351. },
  352. .dmi_name = "trackpad",
  353. .type = I2C_ADAPTER_SMBUS,
  354. },
  355. };
  356. DECLARE_CROS_LAPTOP(acer_c7_chromebook);
  357. static struct i2c_peripheral acer_ac700_peripherals[] __initdata = {
  358. /* Light Sensor. */
  359. {
  360. .board_info = {
  361. I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR),
  362. },
  363. .type = I2C_ADAPTER_SMBUS,
  364. },
  365. };
  366. DECLARE_CROS_LAPTOP(acer_ac700);
  367. static struct i2c_peripheral acer_c720_peripherals[] __initdata = {
  368. /* Touchscreen. */
  369. {
  370. .board_info = {
  371. I2C_BOARD_INFO("atmel_mxt_ts",
  372. ATMEL_TS_I2C_ADDR),
  373. .flags = I2C_CLIENT_WAKE,
  374. },
  375. .dmi_name = "touchscreen",
  376. .irqflags = IRQF_TRIGGER_FALLING,
  377. .type = I2C_ADAPTER_DESIGNWARE,
  378. .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
  379. .alt_addr = ATMEL_TS_I2C_BL_ADDR,
  380. .properties = chromebook_atmel_touchscreen_props,
  381. },
  382. /* Touchpad. */
  383. {
  384. .board_info = {
  385. I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
  386. .flags = I2C_CLIENT_WAKE,
  387. },
  388. .dmi_name = "trackpad",
  389. .type = I2C_ADAPTER_DESIGNWARE,
  390. .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
  391. },
  392. /* Elan Touchpad option. */
  393. {
  394. .board_info = {
  395. I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR),
  396. .flags = I2C_CLIENT_WAKE,
  397. },
  398. .dmi_name = "trackpad",
  399. .type = I2C_ADAPTER_DESIGNWARE,
  400. .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)),
  401. },
  402. /* Light Sensor. */
  403. {
  404. .board_info = {
  405. I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR),
  406. },
  407. .dmi_name = "lightsensor",
  408. .type = I2C_ADAPTER_DESIGNWARE,
  409. .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)),
  410. },
  411. };
  412. DECLARE_CROS_LAPTOP(acer_c720);
  413. static struct i2c_peripheral
  414. hp_pavilion_14_chromebook_peripherals[] __initdata = {
  415. /* Touchpad. */
  416. {
  417. .board_info = {
  418. I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR),
  419. .flags = I2C_CLIENT_WAKE,
  420. },
  421. .dmi_name = "trackpad",
  422. .type = I2C_ADAPTER_SMBUS,
  423. },
  424. };
  425. DECLARE_CROS_LAPTOP(hp_pavilion_14_chromebook);
  426. static struct i2c_peripheral cr48_peripherals[] __initdata = {
  427. /* Light Sensor. */
  428. {
  429. .board_info = {
  430. I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR),
  431. },
  432. .type = I2C_ADAPTER_SMBUS,
  433. },
  434. };
  435. DECLARE_CROS_LAPTOP(cr48);
  436. static const u32 samus_touchpad_buttons[] __initconst = {
  437. KEY_RESERVED,
  438. KEY_RESERVED,
  439. KEY_RESERVED,
  440. BTN_LEFT
  441. };
  442. static const struct property_entry samus_trackpad_props[] __initconst = {
  443. PROPERTY_ENTRY_STRING("compatible", "atmel,maxtouch"),
  444. PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", samus_touchpad_buttons),
  445. { }
  446. };
  447. static struct acpi_peripheral samus_peripherals[] __initdata = {
  448. /* Touchpad */
  449. {
  450. .hid = "ATML0000",
  451. .swnode = {
  452. .properties = samus_trackpad_props,
  453. },
  454. },
  455. /* Touchsceen */
  456. {
  457. .hid = "ATML0001",
  458. .swnode = {
  459. .properties = chromebook_atmel_touchscreen_props,
  460. },
  461. },
  462. };
  463. DECLARE_ACPI_CROS_LAPTOP(samus);
  464. static struct acpi_peripheral generic_atmel_peripherals[] __initdata = {
  465. /* Touchpad */
  466. {
  467. .hid = "ATML0000",
  468. .swnode = {
  469. .properties = chromebook_pixel_trackpad_props,
  470. },
  471. },
  472. /* Touchsceen */
  473. {
  474. .hid = "ATML0001",
  475. .swnode = {
  476. .properties = chromebook_atmel_touchscreen_props,
  477. },
  478. },
  479. };
  480. DECLARE_ACPI_CROS_LAPTOP(generic_atmel);
  481. static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = {
  482. {
  483. .ident = "Samsung Series 5 550",
  484. .matches = {
  485. DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"),
  486. DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"),
  487. },
  488. .driver_data = (void *)&samsung_series_5_550,
  489. },
  490. {
  491. .ident = "Samsung Series 5",
  492. .matches = {
  493. DMI_MATCH(DMI_PRODUCT_NAME, "Alex"),
  494. },
  495. .driver_data = (void *)&samsung_series_5,
  496. },
  497. {
  498. .ident = "Chromebook Pixel",
  499. .matches = {
  500. DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
  501. DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
  502. },
  503. .driver_data = (void *)&chromebook_pixel,
  504. },
  505. {
  506. .ident = "Wolf",
  507. .matches = {
  508. DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
  509. DMI_MATCH(DMI_PRODUCT_NAME, "Wolf"),
  510. },
  511. .driver_data = (void *)&dell_chromebook_11,
  512. },
  513. {
  514. .ident = "HP Chromebook 14",
  515. .matches = {
  516. DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
  517. DMI_MATCH(DMI_PRODUCT_NAME, "Falco"),
  518. },
  519. .driver_data = (void *)&hp_chromebook_14,
  520. },
  521. {
  522. .ident = "Toshiba CB35",
  523. .matches = {
  524. DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
  525. DMI_MATCH(DMI_PRODUCT_NAME, "Leon"),
  526. },
  527. .driver_data = (void *)&toshiba_cb35,
  528. },
  529. {
  530. .ident = "Acer C7 Chromebook",
  531. .matches = {
  532. DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"),
  533. },
  534. .driver_data = (void *)&acer_c7_chromebook,
  535. },
  536. {
  537. .ident = "Acer AC700",
  538. .matches = {
  539. DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
  540. },
  541. .driver_data = (void *)&acer_ac700,
  542. },
  543. {
  544. .ident = "Acer C720",
  545. .matches = {
  546. DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
  547. },
  548. .driver_data = (void *)&acer_c720,
  549. },
  550. {
  551. .ident = "HP Pavilion 14 Chromebook",
  552. .matches = {
  553. DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"),
  554. },
  555. .driver_data = (void *)&hp_pavilion_14_chromebook,
  556. },
  557. {
  558. .ident = "Cr-48",
  559. .matches = {
  560. DMI_MATCH(DMI_PRODUCT_NAME, "Mario"),
  561. },
  562. .driver_data = (void *)&cr48,
  563. },
  564. /* Devices with peripherals incompletely described in ACPI */
  565. {
  566. .ident = "Chromebook Pro",
  567. .matches = {
  568. DMI_MATCH(DMI_SYS_VENDOR, "Google"),
  569. DMI_MATCH(DMI_PRODUCT_NAME, "Caroline"),
  570. },
  571. .driver_data = (void *)&samus,
  572. },
  573. {
  574. .ident = "Google Pixel 2 (2015)",
  575. .matches = {
  576. DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
  577. DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
  578. },
  579. .driver_data = (void *)&samus,
  580. },
  581. {
  582. .ident = "Samsung Chromebook 3",
  583. .matches = {
  584. DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
  585. DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
  586. },
  587. .driver_data = (void *)&samus,
  588. },
  589. {
  590. /*
  591. * Other Chromebooks with Atmel touch controllers:
  592. * - Winky (touchpad)
  593. * - Clapper, Expresso, Rambi, Glimmer (touchscreen)
  594. */
  595. .ident = "Other Chromebook",
  596. .matches = {
  597. /*
  598. * This will match all Google devices, not only devices
  599. * with Atmel, but we will validate that the device
  600. * actually has matching peripherals.
  601. */
  602. DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
  603. },
  604. .driver_data = (void *)&generic_atmel,
  605. },
  606. { }
  607. };
  608. MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table);
  609. static int __init chromeos_laptop_scan_peripherals(struct device *dev, void *data)
  610. {
  611. int error;
  612. if (dev->type == &i2c_adapter_type) {
  613. chromeos_laptop_check_adapter(to_i2c_adapter(dev));
  614. } else if (dev->type == &i2c_client_type) {
  615. if (chromeos_laptop_adjust_client(to_i2c_client(dev))) {
  616. /*
  617. * Now that we have needed properties re-trigger
  618. * driver probe in case driver was initialized
  619. * earlier and probe failed.
  620. */
  621. error = device_attach(dev);
  622. if (error < 0)
  623. dev_warn(dev,
  624. "%s: device_attach() failed: %d\n",
  625. __func__, error);
  626. }
  627. }
  628. return 0;
  629. }
  630. static int __init chromeos_laptop_get_irq_from_dmi(const char *dmi_name)
  631. {
  632. const struct dmi_device *dmi_dev;
  633. const struct dmi_dev_onboard *dev_data;
  634. dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, dmi_name, NULL);
  635. if (!dmi_dev) {
  636. pr_err("failed to find DMI device '%s'\n", dmi_name);
  637. return -ENOENT;
  638. }
  639. dev_data = dmi_dev->device_data;
  640. if (!dev_data) {
  641. pr_err("failed to get data from DMI for '%s'\n", dmi_name);
  642. return -EINVAL;
  643. }
  644. return dev_data->instance;
  645. }
  646. static int __init chromeos_laptop_setup_irq(struct i2c_peripheral *i2c_dev)
  647. {
  648. int irq;
  649. if (i2c_dev->dmi_name) {
  650. irq = chromeos_laptop_get_irq_from_dmi(i2c_dev->dmi_name);
  651. if (irq < 0)
  652. return irq;
  653. i2c_dev->irq_resource = (struct resource)
  654. DEFINE_RES_NAMED(irq, 1, NULL,
  655. IORESOURCE_IRQ | i2c_dev->irqflags);
  656. i2c_dev->board_info.resources = &i2c_dev->irq_resource;
  657. i2c_dev->board_info.num_resources = 1;
  658. }
  659. return 0;
  660. }
  661. static int __init
  662. chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
  663. const struct chromeos_laptop *src)
  664. {
  665. struct i2c_peripheral *i2c_peripherals;
  666. struct i2c_peripheral *i2c_dev;
  667. struct i2c_board_info *info;
  668. int i;
  669. int error;
  670. if (!src->num_i2c_peripherals)
  671. return 0;
  672. i2c_peripherals = kmemdup(src->i2c_peripherals,
  673. src->num_i2c_peripherals *
  674. sizeof(*src->i2c_peripherals),
  675. GFP_KERNEL);
  676. if (!i2c_peripherals)
  677. return -ENOMEM;
  678. for (i = 0; i < src->num_i2c_peripherals; i++) {
  679. i2c_dev = &i2c_peripherals[i];
  680. info = &i2c_dev->board_info;
  681. error = chromeos_laptop_setup_irq(i2c_dev);
  682. if (error)
  683. goto err_out;
  684. /* Create primary fwnode for the device - copies everything */
  685. if (i2c_dev->properties) {
  686. info->fwnode = fwnode_create_software_node(i2c_dev->properties, NULL);
  687. if (IS_ERR(info->fwnode)) {
  688. error = PTR_ERR(info->fwnode);
  689. goto err_out;
  690. }
  691. }
  692. }
  693. cros_laptop->i2c_peripherals = i2c_peripherals;
  694. cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals;
  695. return 0;
  696. err_out:
  697. while (--i >= 0) {
  698. i2c_dev = &i2c_peripherals[i];
  699. info = &i2c_dev->board_info;
  700. if (!IS_ERR_OR_NULL(info->fwnode))
  701. fwnode_remove_software_node(info->fwnode);
  702. }
  703. kfree(i2c_peripherals);
  704. return error;
  705. }
  706. static int __init
  707. chromeos_laptop_prepare_acpi_peripherals(struct chromeos_laptop *cros_laptop,
  708. const struct chromeos_laptop *src)
  709. {
  710. struct acpi_peripheral *acpi_peripherals;
  711. struct acpi_peripheral *acpi_dev;
  712. const struct acpi_peripheral *src_dev;
  713. int n_peripherals = 0;
  714. int i;
  715. int error;
  716. for (i = 0; i < src->num_acpi_peripherals; i++) {
  717. if (acpi_dev_present(src->acpi_peripherals[i].hid, NULL, -1))
  718. n_peripherals++;
  719. }
  720. if (!n_peripherals)
  721. return 0;
  722. acpi_peripherals = kcalloc(n_peripherals,
  723. sizeof(*src->acpi_peripherals),
  724. GFP_KERNEL);
  725. if (!acpi_peripherals)
  726. return -ENOMEM;
  727. acpi_dev = acpi_peripherals;
  728. for (i = 0; i < src->num_acpi_peripherals; i++) {
  729. src_dev = &src->acpi_peripherals[i];
  730. if (!acpi_dev_present(src_dev->hid, NULL, -1))
  731. continue;
  732. *acpi_dev = *src_dev;
  733. /* We need to deep-copy properties */
  734. if (src_dev->swnode.properties) {
  735. acpi_dev->swnode.properties =
  736. property_entries_dup(src_dev->swnode.properties);
  737. if (IS_ERR(acpi_dev->swnode.properties)) {
  738. error = PTR_ERR(acpi_dev->swnode.properties);
  739. goto err_out;
  740. }
  741. }
  742. acpi_dev++;
  743. }
  744. cros_laptop->acpi_peripherals = acpi_peripherals;
  745. cros_laptop->num_acpi_peripherals = n_peripherals;
  746. return 0;
  747. err_out:
  748. while (--i >= 0) {
  749. acpi_dev = &acpi_peripherals[i];
  750. if (!IS_ERR_OR_NULL(acpi_dev->swnode.properties))
  751. property_entries_free(acpi_dev->swnode.properties);
  752. }
  753. kfree(acpi_peripherals);
  754. return error;
  755. }
  756. static void chromeos_laptop_destroy(const struct chromeos_laptop *cros_laptop)
  757. {
  758. const struct acpi_peripheral *acpi_dev;
  759. struct i2c_peripheral *i2c_dev;
  760. int i;
  761. for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
  762. i2c_dev = &cros_laptop->i2c_peripherals[i];
  763. i2c_unregister_device(i2c_dev->client);
  764. }
  765. for (i = 0; i < cros_laptop->num_acpi_peripherals; i++) {
  766. acpi_dev = &cros_laptop->acpi_peripherals[i];
  767. if (acpi_dev->client)
  768. device_remove_software_node(&acpi_dev->client->dev);
  769. property_entries_free(acpi_dev->swnode.properties);
  770. }
  771. kfree(cros_laptop->i2c_peripherals);
  772. kfree(cros_laptop->acpi_peripherals);
  773. kfree(cros_laptop);
  774. }
  775. static struct chromeos_laptop * __init
  776. chromeos_laptop_prepare(const struct chromeos_laptop *src)
  777. {
  778. struct chromeos_laptop *cros_laptop;
  779. int error;
  780. cros_laptop = kzalloc(sizeof(*cros_laptop), GFP_KERNEL);
  781. if (!cros_laptop)
  782. return ERR_PTR(-ENOMEM);
  783. error = chromeos_laptop_prepare_i2c_peripherals(cros_laptop, src);
  784. if (!error)
  785. error = chromeos_laptop_prepare_acpi_peripherals(cros_laptop,
  786. src);
  787. if (error) {
  788. chromeos_laptop_destroy(cros_laptop);
  789. return ERR_PTR(error);
  790. }
  791. return cros_laptop;
  792. }
  793. static int __init chromeos_laptop_init(void)
  794. {
  795. const struct dmi_system_id *dmi_id;
  796. int error;
  797. dmi_id = dmi_first_match(chromeos_laptop_dmi_table);
  798. if (!dmi_id) {
  799. pr_debug("unsupported system\n");
  800. return -ENODEV;
  801. }
  802. pr_debug("DMI Matched %s\n", dmi_id->ident);
  803. cros_laptop = chromeos_laptop_prepare((void *)dmi_id->driver_data);
  804. if (IS_ERR(cros_laptop))
  805. return PTR_ERR(cros_laptop);
  806. if (!cros_laptop->num_i2c_peripherals &&
  807. !cros_laptop->num_acpi_peripherals) {
  808. pr_debug("no relevant devices detected\n");
  809. error = -ENODEV;
  810. goto err_destroy_cros_laptop;
  811. }
  812. error = bus_register_notifier(&i2c_bus_type,
  813. &chromeos_laptop_i2c_notifier);
  814. if (error) {
  815. pr_err("failed to register i2c bus notifier: %d\n",
  816. error);
  817. goto err_destroy_cros_laptop;
  818. }
  819. /*
  820. * Scan adapters that have been registered and clients that have
  821. * been created before we installed the notifier to make sure
  822. * we do not miss any devices.
  823. */
  824. i2c_for_each_dev(NULL, chromeos_laptop_scan_peripherals);
  825. return 0;
  826. err_destroy_cros_laptop:
  827. chromeos_laptop_destroy(cros_laptop);
  828. return error;
  829. }
  830. static void __exit chromeos_laptop_exit(void)
  831. {
  832. bus_unregister_notifier(&i2c_bus_type, &chromeos_laptop_i2c_notifier);
  833. chromeos_laptop_destroy(cros_laptop);
  834. }
  835. module_init(chromeos_laptop_init);
  836. module_exit(chromeos_laptop_exit);
  837. MODULE_DESCRIPTION("Chrome OS Laptop driver");
  838. MODULE_AUTHOR("Benson Leung <[email protected]>");
  839. MODULE_LICENSE("GPL");