intel_pmc_ipc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. /*
  2. * intel_pmc_ipc.c: Driver for the Intel PMC IPC mechanism
  3. *
  4. * (C) Copyright 2014-2015 Intel Corporation
  5. *
  6. * This driver is based on Intel SCU IPC driver(intel_scu_opc.c) by
  7. * Sreedhara DS <sreedhara.ds@intel.com>
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; version 2
  12. * of the License.
  13. *
  14. * PMC running in ARC processor communicates with other entity running in IA
  15. * core through IPC mechanism which in turn messaging between IA core ad PMC.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/delay.h>
  19. #include <linux/errno.h>
  20. #include <linux/init.h>
  21. #include <linux/device.h>
  22. #include <linux/pm.h>
  23. #include <linux/pci.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/interrupt.h>
  26. #include <linux/pm_qos.h>
  27. #include <linux/kernel.h>
  28. #include <linux/bitops.h>
  29. #include <linux/sched.h>
  30. #include <linux/atomic.h>
  31. #include <linux/notifier.h>
  32. #include <linux/suspend.h>
  33. #include <linux/acpi.h>
  34. #include <asm/intel_pmc_ipc.h>
  35. #include <linux/platform_data/itco_wdt.h>
  36. /*
  37. * IPC registers
  38. * The IA write to IPC_CMD command register triggers an interrupt to the ARC,
  39. * The ARC handles the interrupt and services it, writing optional data to
  40. * the IPC1 registers, updates the IPC_STS response register with the status.
  41. */
  42. #define IPC_CMD 0x0
  43. #define IPC_CMD_MSI 0x100
  44. #define IPC_CMD_SIZE 16
  45. #define IPC_CMD_SUBCMD 12
  46. #define IPC_STATUS 0x04
  47. #define IPC_STATUS_IRQ 0x4
  48. #define IPC_STATUS_ERR 0x2
  49. #define IPC_STATUS_BUSY 0x1
  50. #define IPC_SPTR 0x08
  51. #define IPC_DPTR 0x0C
  52. #define IPC_WRITE_BUFFER 0x80
  53. #define IPC_READ_BUFFER 0x90
  54. /*
  55. * 16-byte buffer for sending data associated with IPC command.
  56. */
  57. #define IPC_DATA_BUFFER_SIZE 16
  58. #define IPC_LOOP_CNT 3000000
  59. #define IPC_MAX_SEC 3
  60. #define IPC_TRIGGER_MODE_IRQ true
  61. /* exported resources from IFWI */
  62. #define PLAT_RESOURCE_IPC_INDEX 0
  63. #define PLAT_RESOURCE_IPC_SIZE 0x1000
  64. #define PLAT_RESOURCE_GCR_OFFSET 0x1008
  65. #define PLAT_RESOURCE_GCR_SIZE 0x4
  66. #define PLAT_RESOURCE_BIOS_DATA_INDEX 1
  67. #define PLAT_RESOURCE_BIOS_IFACE_INDEX 2
  68. #define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3
  69. #define PLAT_RESOURCE_ISP_DATA_INDEX 4
  70. #define PLAT_RESOURCE_ISP_IFACE_INDEX 5
  71. #define PLAT_RESOURCE_GTD_DATA_INDEX 6
  72. #define PLAT_RESOURCE_GTD_IFACE_INDEX 7
  73. #define PLAT_RESOURCE_ACPI_IO_INDEX 0
  74. /*
  75. * BIOS does not create an ACPI device for each PMC function,
  76. * but exports multiple resources from one ACPI device(IPC) for
  77. * multiple functions. This driver is responsible to create a
  78. * platform device and to export resources for those functions.
  79. */
  80. #define TCO_DEVICE_NAME "iTCO_wdt"
  81. #define SMI_EN_OFFSET 0x30
  82. #define SMI_EN_SIZE 4
  83. #define TCO_BASE_OFFSET 0x60
  84. #define TCO_REGS_SIZE 16
  85. #define PUNIT_DEVICE_NAME "intel_punit_ipc"
  86. #define TELEMETRY_DEVICE_NAME "intel_telemetry"
  87. #define TELEM_SSRAM_SIZE 240
  88. #define TELEM_PMC_SSRAM_OFFSET 0x1B00
  89. #define TELEM_PUNIT_SSRAM_OFFSET 0x1A00
  90. static const int iTCO_version = 3;
  91. static struct intel_pmc_ipc_dev {
  92. struct device *dev;
  93. void __iomem *ipc_base;
  94. bool irq_mode;
  95. int irq;
  96. int cmd;
  97. struct completion cmd_complete;
  98. /* The following PMC BARs share the same ACPI device with the IPC */
  99. resource_size_t acpi_io_base;
  100. int acpi_io_size;
  101. struct platform_device *tco_dev;
  102. /* gcr */
  103. resource_size_t gcr_base;
  104. int gcr_size;
  105. /* punit */
  106. struct platform_device *punit_dev;
  107. /* Telemetry */
  108. resource_size_t telem_pmc_ssram_base;
  109. resource_size_t telem_punit_ssram_base;
  110. int telem_pmc_ssram_size;
  111. int telem_punit_ssram_size;
  112. u8 telem_res_inval;
  113. struct platform_device *telemetry_dev;
  114. } ipcdev;
  115. static char *ipc_err_sources[] = {
  116. [IPC_ERR_NONE] =
  117. "no error",
  118. [IPC_ERR_CMD_NOT_SUPPORTED] =
  119. "command not supported",
  120. [IPC_ERR_CMD_NOT_SERVICED] =
  121. "command not serviced",
  122. [IPC_ERR_UNABLE_TO_SERVICE] =
  123. "unable to service",
  124. [IPC_ERR_CMD_INVALID] =
  125. "command invalid",
  126. [IPC_ERR_CMD_FAILED] =
  127. "command failed",
  128. [IPC_ERR_EMSECURITY] =
  129. "Invalid Battery",
  130. [IPC_ERR_UNSIGNEDKERNEL] =
  131. "Unsigned kernel",
  132. };
  133. /* Prevent concurrent calls to the PMC */
  134. static DEFINE_MUTEX(ipclock);
  135. static inline void ipc_send_command(u32 cmd)
  136. {
  137. ipcdev.cmd = cmd;
  138. if (ipcdev.irq_mode) {
  139. reinit_completion(&ipcdev.cmd_complete);
  140. cmd |= IPC_CMD_MSI;
  141. }
  142. writel(cmd, ipcdev.ipc_base + IPC_CMD);
  143. }
  144. static inline u32 ipc_read_status(void)
  145. {
  146. return readl(ipcdev.ipc_base + IPC_STATUS);
  147. }
  148. static inline void ipc_data_writel(u32 data, u32 offset)
  149. {
  150. writel(data, ipcdev.ipc_base + IPC_WRITE_BUFFER + offset);
  151. }
  152. static inline u8 ipc_data_readb(u32 offset)
  153. {
  154. return readb(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
  155. }
  156. static inline u32 ipc_data_readl(u32 offset)
  157. {
  158. return readl(ipcdev.ipc_base + IPC_READ_BUFFER + offset);
  159. }
  160. static int intel_pmc_ipc_check_status(void)
  161. {
  162. int status;
  163. int ret = 0;
  164. if (ipcdev.irq_mode) {
  165. if (0 == wait_for_completion_timeout(
  166. &ipcdev.cmd_complete, IPC_MAX_SEC * HZ))
  167. ret = -ETIMEDOUT;
  168. } else {
  169. int loop_count = IPC_LOOP_CNT;
  170. while ((ipc_read_status() & IPC_STATUS_BUSY) && --loop_count)
  171. udelay(1);
  172. if (loop_count == 0)
  173. ret = -ETIMEDOUT;
  174. }
  175. status = ipc_read_status();
  176. if (ret == -ETIMEDOUT) {
  177. dev_err(ipcdev.dev,
  178. "IPC timed out, TS=0x%x, CMD=0x%x\n",
  179. status, ipcdev.cmd);
  180. return ret;
  181. }
  182. if (status & IPC_STATUS_ERR) {
  183. int i;
  184. ret = -EIO;
  185. i = (status >> IPC_CMD_SIZE) & 0xFF;
  186. if (i < ARRAY_SIZE(ipc_err_sources))
  187. dev_err(ipcdev.dev,
  188. "IPC failed: %s, STS=0x%x, CMD=0x%x\n",
  189. ipc_err_sources[i], status, ipcdev.cmd);
  190. else
  191. dev_err(ipcdev.dev,
  192. "IPC failed: unknown, STS=0x%x, CMD=0x%x\n",
  193. status, ipcdev.cmd);
  194. if ((i == IPC_ERR_UNSIGNEDKERNEL) || (i == IPC_ERR_EMSECURITY))
  195. ret = -EACCES;
  196. }
  197. return ret;
  198. }
  199. /**
  200. * intel_pmc_ipc_simple_command() - Simple IPC command
  201. * @cmd: IPC command code.
  202. * @sub: IPC command sub type.
  203. *
  204. * Send a simple IPC command to PMC when don't need to specify
  205. * input/output data and source/dest pointers.
  206. *
  207. * Return: an IPC error code or 0 on success.
  208. */
  209. int intel_pmc_ipc_simple_command(int cmd, int sub)
  210. {
  211. int ret;
  212. mutex_lock(&ipclock);
  213. if (ipcdev.dev == NULL) {
  214. mutex_unlock(&ipclock);
  215. return -ENODEV;
  216. }
  217. ipc_send_command(sub << IPC_CMD_SUBCMD | cmd);
  218. ret = intel_pmc_ipc_check_status();
  219. mutex_unlock(&ipclock);
  220. return ret;
  221. }
  222. EXPORT_SYMBOL_GPL(intel_pmc_ipc_simple_command);
  223. /**
  224. * intel_pmc_ipc_raw_cmd() - IPC command with data and pointers
  225. * @cmd: IPC command code.
  226. * @sub: IPC command sub type.
  227. * @in: input data of this IPC command.
  228. * @inlen: input data length in bytes.
  229. * @out: output data of this IPC command.
  230. * @outlen: output data length in dwords.
  231. * @sptr: data writing to SPTR register.
  232. * @dptr: data writing to DPTR register.
  233. *
  234. * Send an IPC command to PMC with input/output data and source/dest pointers.
  235. *
  236. * Return: an IPC error code or 0 on success.
  237. */
  238. int intel_pmc_ipc_raw_cmd(u32 cmd, u32 sub, u8 *in, u32 inlen, u32 *out,
  239. u32 outlen, u32 dptr, u32 sptr)
  240. {
  241. u32 wbuf[4] = { 0 };
  242. int ret;
  243. int i;
  244. if (inlen > IPC_DATA_BUFFER_SIZE || outlen > IPC_DATA_BUFFER_SIZE / 4)
  245. return -EINVAL;
  246. mutex_lock(&ipclock);
  247. if (ipcdev.dev == NULL) {
  248. mutex_unlock(&ipclock);
  249. return -ENODEV;
  250. }
  251. memcpy(wbuf, in, inlen);
  252. writel(dptr, ipcdev.ipc_base + IPC_DPTR);
  253. writel(sptr, ipcdev.ipc_base + IPC_SPTR);
  254. /* The input data register is 32bit register and inlen is in Byte */
  255. for (i = 0; i < ((inlen + 3) / 4); i++)
  256. ipc_data_writel(wbuf[i], 4 * i);
  257. ipc_send_command((inlen << IPC_CMD_SIZE) |
  258. (sub << IPC_CMD_SUBCMD) | cmd);
  259. ret = intel_pmc_ipc_check_status();
  260. if (!ret) {
  261. /* out is read from 32bit register and outlen is in 32bit */
  262. for (i = 0; i < outlen; i++)
  263. *out++ = ipc_data_readl(4 * i);
  264. }
  265. mutex_unlock(&ipclock);
  266. return ret;
  267. }
  268. EXPORT_SYMBOL_GPL(intel_pmc_ipc_raw_cmd);
  269. /**
  270. * intel_pmc_ipc_command() - IPC command with input/output data
  271. * @cmd: IPC command code.
  272. * @sub: IPC command sub type.
  273. * @in: input data of this IPC command.
  274. * @inlen: input data length in bytes.
  275. * @out: output data of this IPC command.
  276. * @outlen: output data length in dwords.
  277. *
  278. * Send an IPC command to PMC with input/output data.
  279. *
  280. * Return: an IPC error code or 0 on success.
  281. */
  282. int intel_pmc_ipc_command(u32 cmd, u32 sub, u8 *in, u32 inlen,
  283. u32 *out, u32 outlen)
  284. {
  285. return intel_pmc_ipc_raw_cmd(cmd, sub, in, inlen, out, outlen, 0, 0);
  286. }
  287. EXPORT_SYMBOL_GPL(intel_pmc_ipc_command);
  288. static irqreturn_t ioc(int irq, void *dev_id)
  289. {
  290. int status;
  291. if (ipcdev.irq_mode) {
  292. status = ipc_read_status();
  293. writel(status | IPC_STATUS_IRQ, ipcdev.ipc_base + IPC_STATUS);
  294. }
  295. complete(&ipcdev.cmd_complete);
  296. return IRQ_HANDLED;
  297. }
  298. static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  299. {
  300. resource_size_t pci_resource;
  301. int ret;
  302. int len;
  303. ipcdev.dev = &pci_dev_get(pdev)->dev;
  304. ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
  305. ret = pci_enable_device(pdev);
  306. if (ret)
  307. return ret;
  308. ret = pci_request_regions(pdev, "intel_pmc_ipc");
  309. if (ret)
  310. return ret;
  311. pci_resource = pci_resource_start(pdev, 0);
  312. len = pci_resource_len(pdev, 0);
  313. if (!pci_resource || !len) {
  314. dev_err(&pdev->dev, "Failed to get resource\n");
  315. return -ENOMEM;
  316. }
  317. init_completion(&ipcdev.cmd_complete);
  318. if (request_irq(pdev->irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) {
  319. dev_err(&pdev->dev, "Failed to request irq\n");
  320. return -EBUSY;
  321. }
  322. ipcdev.ipc_base = ioremap_nocache(pci_resource, len);
  323. if (!ipcdev.ipc_base) {
  324. dev_err(&pdev->dev, "Failed to ioremap ipc base\n");
  325. free_irq(pdev->irq, &ipcdev);
  326. ret = -ENOMEM;
  327. }
  328. return ret;
  329. }
  330. static void ipc_pci_remove(struct pci_dev *pdev)
  331. {
  332. free_irq(pdev->irq, &ipcdev);
  333. pci_release_regions(pdev);
  334. pci_dev_put(pdev);
  335. iounmap(ipcdev.ipc_base);
  336. ipcdev.dev = NULL;
  337. }
  338. static const struct pci_device_id ipc_pci_ids[] = {
  339. {PCI_VDEVICE(INTEL, 0x0a94), 0},
  340. {PCI_VDEVICE(INTEL, 0x1a94), 0},
  341. { 0,}
  342. };
  343. MODULE_DEVICE_TABLE(pci, ipc_pci_ids);
  344. static struct pci_driver ipc_pci_driver = {
  345. .name = "intel_pmc_ipc",
  346. .id_table = ipc_pci_ids,
  347. .probe = ipc_pci_probe,
  348. .remove = ipc_pci_remove,
  349. };
  350. static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev,
  351. struct device_attribute *attr,
  352. const char *buf, size_t count)
  353. {
  354. int subcmd;
  355. int cmd;
  356. int ret;
  357. ret = sscanf(buf, "%d %d", &cmd, &subcmd);
  358. if (ret != 2) {
  359. dev_err(dev, "Error args\n");
  360. return -EINVAL;
  361. }
  362. ret = intel_pmc_ipc_simple_command(cmd, subcmd);
  363. if (ret) {
  364. dev_err(dev, "command %d error with %d\n", cmd, ret);
  365. return ret;
  366. }
  367. return (ssize_t)count;
  368. }
  369. static ssize_t intel_pmc_ipc_northpeak_store(struct device *dev,
  370. struct device_attribute *attr,
  371. const char *buf, size_t count)
  372. {
  373. unsigned long val;
  374. int subcmd;
  375. int ret;
  376. if (kstrtoul(buf, 0, &val))
  377. return -EINVAL;
  378. if (val)
  379. subcmd = 1;
  380. else
  381. subcmd = 0;
  382. ret = intel_pmc_ipc_simple_command(PMC_IPC_NORTHPEAK_CTRL, subcmd);
  383. if (ret) {
  384. dev_err(dev, "command north %d error with %d\n", subcmd, ret);
  385. return ret;
  386. }
  387. return (ssize_t)count;
  388. }
  389. static DEVICE_ATTR(simplecmd, S_IWUSR,
  390. NULL, intel_pmc_ipc_simple_cmd_store);
  391. static DEVICE_ATTR(northpeak, S_IWUSR,
  392. NULL, intel_pmc_ipc_northpeak_store);
  393. static struct attribute *intel_ipc_attrs[] = {
  394. &dev_attr_northpeak.attr,
  395. &dev_attr_simplecmd.attr,
  396. NULL
  397. };
  398. static const struct attribute_group intel_ipc_group = {
  399. .attrs = intel_ipc_attrs,
  400. };
  401. static struct resource punit_res_array[] = {
  402. /* Punit BIOS */
  403. {
  404. .flags = IORESOURCE_MEM,
  405. },
  406. {
  407. .flags = IORESOURCE_MEM,
  408. },
  409. /* Punit ISP */
  410. {
  411. .flags = IORESOURCE_MEM,
  412. },
  413. {
  414. .flags = IORESOURCE_MEM,
  415. },
  416. /* Punit GTD */
  417. {
  418. .flags = IORESOURCE_MEM,
  419. },
  420. {
  421. .flags = IORESOURCE_MEM,
  422. },
  423. };
  424. #define TCO_RESOURCE_ACPI_IO 0
  425. #define TCO_RESOURCE_SMI_EN_IO 1
  426. #define TCO_RESOURCE_GCR_MEM 2
  427. static struct resource tco_res[] = {
  428. /* ACPI - TCO */
  429. {
  430. .flags = IORESOURCE_IO,
  431. },
  432. /* ACPI - SMI */
  433. {
  434. .flags = IORESOURCE_IO,
  435. },
  436. /* GCS */
  437. {
  438. .flags = IORESOURCE_MEM,
  439. },
  440. };
  441. static struct itco_wdt_platform_data tco_info = {
  442. .name = "Apollo Lake SoC",
  443. .version = 3,
  444. };
  445. #define TELEMETRY_RESOURCE_PUNIT_SSRAM 0
  446. #define TELEMETRY_RESOURCE_PMC_SSRAM 1
  447. static struct resource telemetry_res[] = {
  448. /*Telemetry*/
  449. {
  450. .flags = IORESOURCE_MEM,
  451. },
  452. {
  453. .flags = IORESOURCE_MEM,
  454. },
  455. };
  456. static int ipc_create_punit_device(void)
  457. {
  458. struct platform_device *pdev;
  459. int ret;
  460. pdev = platform_device_alloc(PUNIT_DEVICE_NAME, -1);
  461. if (!pdev) {
  462. dev_err(ipcdev.dev, "Failed to alloc punit platform device\n");
  463. return -ENOMEM;
  464. }
  465. pdev->dev.parent = ipcdev.dev;
  466. ret = platform_device_add_resources(pdev, punit_res_array,
  467. ARRAY_SIZE(punit_res_array));
  468. if (ret) {
  469. dev_err(ipcdev.dev, "Failed to add platform punit resources\n");
  470. goto err;
  471. }
  472. ret = platform_device_add(pdev);
  473. if (ret) {
  474. dev_err(ipcdev.dev, "Failed to add punit platform device\n");
  475. goto err;
  476. }
  477. ipcdev.punit_dev = pdev;
  478. return 0;
  479. err:
  480. platform_device_put(pdev);
  481. return ret;
  482. }
  483. static int ipc_create_tco_device(void)
  484. {
  485. struct platform_device *pdev;
  486. struct resource *res;
  487. int ret;
  488. pdev = platform_device_alloc(TCO_DEVICE_NAME, -1);
  489. if (!pdev) {
  490. dev_err(ipcdev.dev, "Failed to alloc tco platform device\n");
  491. return -ENOMEM;
  492. }
  493. pdev->dev.parent = ipcdev.dev;
  494. res = tco_res + TCO_RESOURCE_ACPI_IO;
  495. res->start = ipcdev.acpi_io_base + TCO_BASE_OFFSET;
  496. res->end = res->start + TCO_REGS_SIZE - 1;
  497. res = tco_res + TCO_RESOURCE_SMI_EN_IO;
  498. res->start = ipcdev.acpi_io_base + SMI_EN_OFFSET;
  499. res->end = res->start + SMI_EN_SIZE - 1;
  500. res = tco_res + TCO_RESOURCE_GCR_MEM;
  501. res->start = ipcdev.gcr_base;
  502. res->end = res->start + ipcdev.gcr_size - 1;
  503. ret = platform_device_add_resources(pdev, tco_res, ARRAY_SIZE(tco_res));
  504. if (ret) {
  505. dev_err(ipcdev.dev, "Failed to add tco platform resources\n");
  506. goto err;
  507. }
  508. ret = platform_device_add_data(pdev, &tco_info, sizeof(tco_info));
  509. if (ret) {
  510. dev_err(ipcdev.dev, "Failed to add tco platform data\n");
  511. goto err;
  512. }
  513. ret = platform_device_add(pdev);
  514. if (ret) {
  515. dev_err(ipcdev.dev, "Failed to add tco platform device\n");
  516. goto err;
  517. }
  518. ipcdev.tco_dev = pdev;
  519. return 0;
  520. err:
  521. platform_device_put(pdev);
  522. return ret;
  523. }
  524. static int ipc_create_telemetry_device(void)
  525. {
  526. struct platform_device *pdev;
  527. struct resource *res;
  528. int ret;
  529. pdev = platform_device_alloc(TELEMETRY_DEVICE_NAME, -1);
  530. if (!pdev) {
  531. dev_err(ipcdev.dev,
  532. "Failed to allocate telemetry platform device\n");
  533. return -ENOMEM;
  534. }
  535. pdev->dev.parent = ipcdev.dev;
  536. res = telemetry_res + TELEMETRY_RESOURCE_PUNIT_SSRAM;
  537. res->start = ipcdev.telem_punit_ssram_base;
  538. res->end = res->start + ipcdev.telem_punit_ssram_size - 1;
  539. res = telemetry_res + TELEMETRY_RESOURCE_PMC_SSRAM;
  540. res->start = ipcdev.telem_pmc_ssram_base;
  541. res->end = res->start + ipcdev.telem_pmc_ssram_size - 1;
  542. ret = platform_device_add_resources(pdev, telemetry_res,
  543. ARRAY_SIZE(telemetry_res));
  544. if (ret) {
  545. dev_err(ipcdev.dev,
  546. "Failed to add telemetry platform resources\n");
  547. goto err;
  548. }
  549. ret = platform_device_add(pdev);
  550. if (ret) {
  551. dev_err(ipcdev.dev,
  552. "Failed to add telemetry platform device\n");
  553. goto err;
  554. }
  555. ipcdev.telemetry_dev = pdev;
  556. return 0;
  557. err:
  558. platform_device_put(pdev);
  559. return ret;
  560. }
  561. static int ipc_create_pmc_devices(void)
  562. {
  563. int ret;
  564. ret = ipc_create_tco_device();
  565. if (ret) {
  566. dev_err(ipcdev.dev, "Failed to add tco platform device\n");
  567. return ret;
  568. }
  569. ret = ipc_create_punit_device();
  570. if (ret) {
  571. dev_err(ipcdev.dev, "Failed to add punit platform device\n");
  572. platform_device_unregister(ipcdev.tco_dev);
  573. }
  574. if (!ipcdev.telem_res_inval) {
  575. ret = ipc_create_telemetry_device();
  576. if (ret)
  577. dev_warn(ipcdev.dev,
  578. "Failed to add telemetry platform device\n");
  579. }
  580. return ret;
  581. }
  582. static int ipc_plat_get_res(struct platform_device *pdev)
  583. {
  584. struct resource *res, *punit_res;
  585. void __iomem *addr;
  586. int size;
  587. res = platform_get_resource(pdev, IORESOURCE_IO,
  588. PLAT_RESOURCE_ACPI_IO_INDEX);
  589. if (!res) {
  590. dev_err(&pdev->dev, "Failed to get io resource\n");
  591. return -ENXIO;
  592. }
  593. size = resource_size(res);
  594. ipcdev.acpi_io_base = res->start;
  595. ipcdev.acpi_io_size = size;
  596. dev_info(&pdev->dev, "io res: %pR\n", res);
  597. /* This is index 0 to cover BIOS data register */
  598. punit_res = punit_res_array;
  599. res = platform_get_resource(pdev, IORESOURCE_MEM,
  600. PLAT_RESOURCE_BIOS_DATA_INDEX);
  601. if (!res) {
  602. dev_err(&pdev->dev, "Failed to get res of punit BIOS data\n");
  603. return -ENXIO;
  604. }
  605. *punit_res = *res;
  606. dev_info(&pdev->dev, "punit BIOS data res: %pR\n", res);
  607. res = platform_get_resource(pdev, IORESOURCE_MEM,
  608. PLAT_RESOURCE_BIOS_IFACE_INDEX);
  609. if (!res) {
  610. dev_err(&pdev->dev, "Failed to get res of punit BIOS iface\n");
  611. return -ENXIO;
  612. }
  613. /* This is index 1 to cover BIOS interface register */
  614. *++punit_res = *res;
  615. dev_info(&pdev->dev, "punit BIOS interface res: %pR\n", res);
  616. res = platform_get_resource(pdev, IORESOURCE_MEM,
  617. PLAT_RESOURCE_ISP_DATA_INDEX);
  618. if (!res) {
  619. dev_err(&pdev->dev, "Failed to get res of punit ISP data\n");
  620. return -ENXIO;
  621. }
  622. /* This is index 2 to cover ISP data register */
  623. *++punit_res = *res;
  624. dev_info(&pdev->dev, "punit ISP data res: %pR\n", res);
  625. res = platform_get_resource(pdev, IORESOURCE_MEM,
  626. PLAT_RESOURCE_ISP_IFACE_INDEX);
  627. if (!res) {
  628. dev_err(&pdev->dev, "Failed to get res of punit ISP iface\n");
  629. return -ENXIO;
  630. }
  631. /* This is index 3 to cover ISP interface register */
  632. *++punit_res = *res;
  633. dev_info(&pdev->dev, "punit ISP interface res: %pR\n", res);
  634. res = platform_get_resource(pdev, IORESOURCE_MEM,
  635. PLAT_RESOURCE_GTD_DATA_INDEX);
  636. if (!res) {
  637. dev_err(&pdev->dev, "Failed to get res of punit GTD data\n");
  638. return -ENXIO;
  639. }
  640. /* This is index 4 to cover GTD data register */
  641. *++punit_res = *res;
  642. dev_info(&pdev->dev, "punit GTD data res: %pR\n", res);
  643. res = platform_get_resource(pdev, IORESOURCE_MEM,
  644. PLAT_RESOURCE_GTD_IFACE_INDEX);
  645. if (!res) {
  646. dev_err(&pdev->dev, "Failed to get res of punit GTD iface\n");
  647. return -ENXIO;
  648. }
  649. /* This is index 5 to cover GTD interface register */
  650. *++punit_res = *res;
  651. dev_info(&pdev->dev, "punit GTD interface res: %pR\n", res);
  652. res = platform_get_resource(pdev, IORESOURCE_MEM,
  653. PLAT_RESOURCE_IPC_INDEX);
  654. if (!res) {
  655. dev_err(&pdev->dev, "Failed to get ipc resource\n");
  656. return -ENXIO;
  657. }
  658. size = PLAT_RESOURCE_IPC_SIZE;
  659. if (!request_mem_region(res->start, size, pdev->name)) {
  660. dev_err(&pdev->dev, "Failed to request ipc resource\n");
  661. return -EBUSY;
  662. }
  663. addr = ioremap_nocache(res->start, size);
  664. if (!addr) {
  665. dev_err(&pdev->dev, "I/O memory remapping failed\n");
  666. release_mem_region(res->start, size);
  667. return -ENOMEM;
  668. }
  669. ipcdev.ipc_base = addr;
  670. ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET;
  671. ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
  672. dev_info(&pdev->dev, "ipc res: %pR\n", res);
  673. ipcdev.telem_res_inval = 0;
  674. res = platform_get_resource(pdev, IORESOURCE_MEM,
  675. PLAT_RESOURCE_TELEM_SSRAM_INDEX);
  676. if (!res) {
  677. dev_err(&pdev->dev, "Failed to get telemetry ssram resource\n");
  678. ipcdev.telem_res_inval = 1;
  679. } else {
  680. ipcdev.telem_punit_ssram_base = res->start +
  681. TELEM_PUNIT_SSRAM_OFFSET;
  682. ipcdev.telem_punit_ssram_size = TELEM_SSRAM_SIZE;
  683. ipcdev.telem_pmc_ssram_base = res->start +
  684. TELEM_PMC_SSRAM_OFFSET;
  685. ipcdev.telem_pmc_ssram_size = TELEM_SSRAM_SIZE;
  686. dev_info(&pdev->dev, "telemetry ssram res: %pR\n", res);
  687. }
  688. return 0;
  689. }
  690. #ifdef CONFIG_ACPI
  691. static const struct acpi_device_id ipc_acpi_ids[] = {
  692. { "INT34D2", 0},
  693. { }
  694. };
  695. MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids);
  696. #endif
  697. static int ipc_plat_probe(struct platform_device *pdev)
  698. {
  699. struct resource *res;
  700. int ret;
  701. ipcdev.dev = &pdev->dev;
  702. ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
  703. init_completion(&ipcdev.cmd_complete);
  704. ipcdev.irq = platform_get_irq(pdev, 0);
  705. if (ipcdev.irq < 0) {
  706. dev_err(&pdev->dev, "Failed to get irq\n");
  707. return -EINVAL;
  708. }
  709. ret = ipc_plat_get_res(pdev);
  710. if (ret) {
  711. dev_err(&pdev->dev, "Failed to request resource\n");
  712. return ret;
  713. }
  714. ret = ipc_create_pmc_devices();
  715. if (ret) {
  716. dev_err(&pdev->dev, "Failed to create pmc devices\n");
  717. goto err_device;
  718. }
  719. if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND,
  720. "intel_pmc_ipc", &ipcdev)) {
  721. dev_err(&pdev->dev, "Failed to request irq\n");
  722. ret = -EBUSY;
  723. goto err_irq;
  724. }
  725. ret = sysfs_create_group(&pdev->dev.kobj, &intel_ipc_group);
  726. if (ret) {
  727. dev_err(&pdev->dev, "Failed to create sysfs group %d\n",
  728. ret);
  729. goto err_sys;
  730. }
  731. return 0;
  732. err_sys:
  733. free_irq(ipcdev.irq, &ipcdev);
  734. err_irq:
  735. platform_device_unregister(ipcdev.tco_dev);
  736. platform_device_unregister(ipcdev.punit_dev);
  737. platform_device_unregister(ipcdev.telemetry_dev);
  738. err_device:
  739. iounmap(ipcdev.ipc_base);
  740. res = platform_get_resource(pdev, IORESOURCE_MEM,
  741. PLAT_RESOURCE_IPC_INDEX);
  742. if (res)
  743. release_mem_region(res->start, PLAT_RESOURCE_IPC_SIZE);
  744. return ret;
  745. }
  746. static int ipc_plat_remove(struct platform_device *pdev)
  747. {
  748. struct resource *res;
  749. sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group);
  750. free_irq(ipcdev.irq, &ipcdev);
  751. platform_device_unregister(ipcdev.tco_dev);
  752. platform_device_unregister(ipcdev.punit_dev);
  753. platform_device_unregister(ipcdev.telemetry_dev);
  754. iounmap(ipcdev.ipc_base);
  755. res = platform_get_resource(pdev, IORESOURCE_MEM,
  756. PLAT_RESOURCE_IPC_INDEX);
  757. if (res)
  758. release_mem_region(res->start, PLAT_RESOURCE_IPC_SIZE);
  759. ipcdev.dev = NULL;
  760. return 0;
  761. }
  762. static struct platform_driver ipc_plat_driver = {
  763. .remove = ipc_plat_remove,
  764. .probe = ipc_plat_probe,
  765. .driver = {
  766. .name = "pmc-ipc-plat",
  767. .acpi_match_table = ACPI_PTR(ipc_acpi_ids),
  768. },
  769. };
  770. static int __init intel_pmc_ipc_init(void)
  771. {
  772. int ret;
  773. ret = platform_driver_register(&ipc_plat_driver);
  774. if (ret) {
  775. pr_err("Failed to register PMC ipc platform driver\n");
  776. return ret;
  777. }
  778. ret = pci_register_driver(&ipc_pci_driver);
  779. if (ret) {
  780. pr_err("Failed to register PMC ipc pci driver\n");
  781. platform_driver_unregister(&ipc_plat_driver);
  782. return ret;
  783. }
  784. return ret;
  785. }
  786. static void __exit intel_pmc_ipc_exit(void)
  787. {
  788. pci_unregister_driver(&ipc_pci_driver);
  789. platform_driver_unregister(&ipc_plat_driver);
  790. }
  791. MODULE_AUTHOR("Zha Qipeng <qipeng.zha@intel.com>");
  792. MODULE_DESCRIPTION("Intel PMC IPC driver");
  793. MODULE_LICENSE("GPL");
  794. /* Some modules are dependent on this, so init earlier */
  795. fs_initcall(intel_pmc_ipc_init);
  796. module_exit(intel_pmc_ipc_exit);