qcom-mpm.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2010-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/delay.h>
  7. #include <linux/err.h>
  8. #include <linux/kernel.h>
  9. #include <linux/init.h>
  10. #include <linux/irq.h>
  11. #include <linux/irqchip.h>
  12. #include <linux/irqdomain.h>
  13. #include <linux/io.h>
  14. #include <linux/module.h>
  15. #include <linux/of.h>
  16. #include <linux/of_address.h>
  17. #include <linux/of_irq.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/pm_domain.h>
  20. #include <linux/slab.h>
  21. #include <linux/soc/qcom/irq.h>
  22. #include <linux/spinlock.h>
  23. #include <soc/qcom/mpm.h>
  24. #define CREATE_TRACE_POINTS
  25. #include "trace/events/mpm.h"
  26. #define ARCH_TIMER_HZ (19200000)
  27. #define MAX_MPM_PIN_PER_IRQ 2
  28. #define CLEAR_INTR(reg, intr) (reg & ~(1 << intr))
  29. #define ENABLE_INTR(reg, intr) (reg | (1 << intr))
  30. #define CLEAR_TYPE(reg, type) (reg & ~(1 << type))
  31. #define ENABLE_TYPE(reg, type) (reg | (1 << type))
  32. #define MPM_REG_ENABLE 0
  33. #define MPM_REG_FALLING_EDGE 1
  34. #define MPM_REG_RISING_EDGE 2
  35. #define MPM_REG_POLARITY 3
  36. #define MPM_REG_STATUS 4
  37. #define MPM_GPIO 0
  38. #define MPM_GIC 1
  39. #define MAX_REG_WIDTH 3
  40. #define QCOM_MPM_REG_WIDTH DIV_ROUND_UP(num_mpm_irqs, 32)
  41. #define MPM_REGISTER(reg, index) ((reg * QCOM_MPM_REG_WIDTH + index + 2) * (4))
  42. #define GPIO_NO_WAKE_IRQ ~0U
  43. #define MPM_NO_PARENT_IRQ ~0U
  44. #define MPM_CNTCVAL_LO 0x30
  45. #define MPM_CNTCVAL_HI 0x34
  46. #define MPM_CNTV_CTL 0x3c
  47. #define MPM_ARCH_TIMER_CTRL_ENABLE (1 << 0)
  48. struct msm_mpm_device_data {
  49. struct device *dev;
  50. void __iomem *mpm_request_reg_base;
  51. void __iomem *mpm_ipc_reg;
  52. void __iomem *timer_frame_reg;
  53. irq_hw_number_t ipc_irq;
  54. struct irq_domain *gic_chip_domain;
  55. struct irq_domain *gpio_chip_domain;
  56. };
  57. struct mpm_pin {
  58. int pin;
  59. irq_hw_number_t hwirq;
  60. };
  61. static int num_mpm_irqs = 64;
  62. static struct msm_mpm_device_data msm_mpm_dev_data;
  63. static unsigned int *mpm_to_irq;
  64. static DEFINE_SPINLOCK(mpm_lock);
  65. static irq_hw_number_t get_parent_hwirq(struct irq_domain *d,
  66. irq_hw_number_t hwirq)
  67. {
  68. struct mpm_pin *mpm_data = NULL;
  69. int i = 0;
  70. if (!d)
  71. return GPIO_NO_WAKE_IRQ;
  72. if (d->host_data) {
  73. mpm_data = d->host_data;
  74. for (i = 0; (mpm_data[i].pin >= 0); i++) {
  75. if (mpm_data[i].pin == hwirq)
  76. return mpm_data[i].hwirq;
  77. }
  78. }
  79. return GPIO_NO_WAKE_IRQ;
  80. }
  81. static void msm_get_mpm_pin(struct irq_data *d, int *mpm_pin, bool is_mpmgic)
  82. {
  83. struct mpm_pin *mpm_data = NULL;
  84. int i = 0, j = 0;
  85. irq_hw_number_t hwirq;
  86. if (!d || !d->domain)
  87. return;
  88. if (is_mpmgic && d->domain->host_data) {
  89. mpm_data = d->domain->host_data;
  90. hwirq = get_parent_hwirq(d->domain, d->hwirq);
  91. if (hwirq == GPIO_NO_WAKE_IRQ)
  92. return;
  93. for (i = 0; (mpm_data[i].pin >= 0) &&
  94. (j < MAX_MPM_PIN_PER_IRQ); i++) {
  95. if (mpm_data[i].hwirq == hwirq) {
  96. mpm_pin[j] = mpm_data[i].pin;
  97. mpm_to_irq[mpm_data[i].pin] = d->irq;
  98. j++;
  99. }
  100. }
  101. } else if (!is_mpmgic) {
  102. mpm_pin[j] = d->hwirq;
  103. mpm_to_irq[d->hwirq] = d->irq;
  104. }
  105. }
  106. static inline uint32_t msm_mpm_read(unsigned int reg, unsigned int subreg_index)
  107. {
  108. unsigned int offset = MPM_REGISTER(reg, subreg_index);
  109. return readl_relaxed(msm_mpm_dev_data.mpm_request_reg_base + offset);
  110. }
  111. static inline void msm_mpm_write(unsigned int reg,
  112. unsigned int subreg_index,
  113. uint32_t value)
  114. {
  115. void __iomem *mpm_reg_base = msm_mpm_dev_data.mpm_request_reg_base;
  116. /*
  117. * Add 2 to offset to account for the 64 bit timer in the vMPM
  118. * mapping
  119. */
  120. unsigned int offset = MPM_REGISTER(reg, subreg_index);
  121. u32 r_value;
  122. writel_relaxed(value, mpm_reg_base + offset);
  123. do {
  124. r_value = readl_relaxed(mpm_reg_base + offset);
  125. udelay(5);
  126. } while (r_value != value);
  127. }
  128. static inline void msm_mpm_enable_irq(struct irq_data *d, bool on,
  129. bool is_mpmgic)
  130. {
  131. int mpm_pin[MAX_MPM_PIN_PER_IRQ] = {-1, -1};
  132. unsigned long flags;
  133. int i = 0;
  134. u32 enable;
  135. unsigned int index, mask;
  136. unsigned int reg;
  137. reg = MPM_REG_ENABLE;
  138. msm_get_mpm_pin(d, mpm_pin, is_mpmgic);
  139. for (i = 0; i < MAX_MPM_PIN_PER_IRQ; i++) {
  140. if (mpm_pin[i] < 0)
  141. return;
  142. index = mpm_pin[i]/32;
  143. mask = mpm_pin[i]%32;
  144. spin_lock_irqsave(&mpm_lock, flags);
  145. enable = msm_mpm_read(reg, index);
  146. if (on)
  147. enable = ENABLE_INTR(enable, mask);
  148. else
  149. enable = CLEAR_INTR(enable, mask);
  150. msm_mpm_write(reg, index, enable);
  151. spin_unlock_irqrestore(&mpm_lock, flags);
  152. }
  153. }
  154. static void msm_mpm_program_set_type(bool set, unsigned int reg,
  155. unsigned int index, unsigned int mask)
  156. {
  157. u32 type;
  158. type = msm_mpm_read(reg, index);
  159. if (set)
  160. type = ENABLE_TYPE(type, mask);
  161. else
  162. type = CLEAR_TYPE(type, mask);
  163. msm_mpm_write(reg, index, type);
  164. }
  165. static void msm_mpm_set_type(struct irq_data *d,
  166. unsigned int flowtype, bool is_mpmgic)
  167. {
  168. int mpm_pin[MAX_MPM_PIN_PER_IRQ] = {-1, -1};
  169. unsigned long flags;
  170. int i = 0;
  171. unsigned int index, mask;
  172. unsigned int reg = 0;
  173. msm_get_mpm_pin(d, mpm_pin, is_mpmgic);
  174. for (i = 0; i < MAX_MPM_PIN_PER_IRQ; i++) {
  175. if (mpm_pin[i] < 0)
  176. return;
  177. index = mpm_pin[i]/32;
  178. mask = mpm_pin[i]%32;
  179. spin_lock_irqsave(&mpm_lock, flags);
  180. reg = MPM_REG_RISING_EDGE;
  181. if (flowtype & IRQ_TYPE_EDGE_RISING)
  182. msm_mpm_program_set_type(1, reg, index, mask);
  183. else
  184. msm_mpm_program_set_type(0, reg, index, mask);
  185. reg = MPM_REG_FALLING_EDGE;
  186. if (flowtype & IRQ_TYPE_EDGE_FALLING)
  187. msm_mpm_program_set_type(1, reg, index, mask);
  188. else
  189. msm_mpm_program_set_type(0, reg, index, mask);
  190. reg = MPM_REG_POLARITY;
  191. if (flowtype & IRQ_TYPE_LEVEL_HIGH)
  192. msm_mpm_program_set_type(1, reg, index, mask);
  193. else
  194. msm_mpm_program_set_type(0, reg, index, mask);
  195. spin_unlock_irqrestore(&mpm_lock, flags);
  196. }
  197. }
  198. static void msm_mpm_gpio_chip_mask(struct irq_data *d)
  199. {
  200. if (d->hwirq == GPIO_NO_WAKE_IRQ)
  201. return;
  202. msm_mpm_enable_irq(d, false, MPM_GPIO);
  203. }
  204. static void msm_mpm_gpio_chip_unmask(struct irq_data *d)
  205. {
  206. if (d->hwirq == GPIO_NO_WAKE_IRQ)
  207. return;
  208. msm_mpm_enable_irq(d, true, MPM_GPIO);
  209. }
  210. static int msm_mpm_gpio_chip_set_type(struct irq_data *d, unsigned int type)
  211. {
  212. if (d->hwirq == GPIO_NO_WAKE_IRQ)
  213. return 0;
  214. msm_mpm_set_type(d, type, MPM_GPIO);
  215. return 0;
  216. }
  217. static void msm_mpm_gic_chip_mask(struct irq_data *d)
  218. {
  219. msm_mpm_enable_irq(d, false, MPM_GIC);
  220. irq_chip_mask_parent(d);
  221. }
  222. static void msm_mpm_gic_chip_unmask(struct irq_data *d)
  223. {
  224. msm_mpm_enable_irq(d, true, MPM_GIC);
  225. irq_chip_unmask_parent(d);
  226. }
  227. static int msm_mpm_gic_chip_set_type(struct irq_data *d, unsigned int type)
  228. {
  229. msm_mpm_set_type(d, type, MPM_GIC);
  230. return irq_chip_set_type_parent(d, type);
  231. }
  232. int msm_mpm_gic_chip_set_affinity(struct irq_data *data,
  233. const struct cpumask *dest, bool force)
  234. {
  235. data = data->parent_data;
  236. if (data->chip->irq_set_affinity)
  237. return data->chip->irq_set_affinity(data, dest, force);
  238. return -ENXIO;
  239. }
  240. void msm_mpm_gic_chip_eoi(struct irq_data *data)
  241. {
  242. data = data->parent_data;
  243. data->chip->irq_eoi(data);
  244. }
  245. static struct irq_chip msm_mpm_gic_chip = {
  246. .name = "mpm-gic",
  247. .irq_eoi = msm_mpm_gic_chip_eoi,
  248. .irq_mask = msm_mpm_gic_chip_mask,
  249. .irq_disable = msm_mpm_gic_chip_mask,
  250. .irq_unmask = msm_mpm_gic_chip_unmask,
  251. .irq_set_type = msm_mpm_gic_chip_set_type,
  252. .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
  253. .irq_set_affinity = msm_mpm_gic_chip_set_affinity,
  254. };
  255. static struct irq_chip msm_mpm_gpio_chip = {
  256. .name = "mpm-gpio",
  257. .irq_mask = msm_mpm_gpio_chip_mask,
  258. .irq_disable = msm_mpm_gpio_chip_mask,
  259. .irq_unmask = msm_mpm_gpio_chip_unmask,
  260. .irq_set_type = msm_mpm_gpio_chip_set_type,
  261. .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
  262. };
  263. static int msm_mpm_gpio_chip_translate(struct irq_domain *d,
  264. struct irq_fwspec *fwspec,
  265. unsigned long *hwirq,
  266. unsigned int *type)
  267. {
  268. if (is_of_node(fwspec->fwnode)) {
  269. if (fwspec->param_count != 2)
  270. return -EINVAL;
  271. *hwirq = fwspec->param[0];
  272. *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
  273. return 0;
  274. }
  275. return -EINVAL;
  276. }
  277. static int msm_mpm_gpio_chip_alloc(struct irq_domain *domain,
  278. unsigned int virq,
  279. unsigned int nr_irqs,
  280. void *data)
  281. {
  282. int ret = 0;
  283. struct irq_fwspec *fwspec = data;
  284. irq_hw_number_t hwirq;
  285. unsigned int type = IRQ_TYPE_NONE;
  286. ret = msm_mpm_gpio_chip_translate(domain, fwspec, &hwirq, &type);
  287. if (ret)
  288. return ret;
  289. if (hwirq == GPIO_NO_WAKE_IRQ)
  290. return irq_domain_disconnect_hierarchy(domain, virq);
  291. irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
  292. &msm_mpm_gpio_chip, NULL);
  293. return irq_domain_disconnect_hierarchy(domain->parent, virq);
  294. }
  295. static int msm_mpm_gpio_chip_select(struct irq_domain *d,
  296. struct irq_fwspec *node,
  297. enum irq_domain_bus_token bus_token)
  298. {
  299. return (bus_token == DOMAIN_BUS_WAKEUP);
  300. }
  301. static const struct irq_domain_ops msm_mpm_gpio_chip_domain_ops = {
  302. .alloc = msm_mpm_gpio_chip_alloc,
  303. .free = irq_domain_free_irqs_common,
  304. .select = msm_mpm_gpio_chip_select,
  305. };
  306. static int msm_mpm_gic_chip_translate(struct irq_domain *d,
  307. struct irq_fwspec *fwspec,
  308. unsigned long *hwirq,
  309. unsigned int *type)
  310. {
  311. if (is_of_node(fwspec->fwnode)) {
  312. if (fwspec->param_count != 2)
  313. return -EINVAL;
  314. *hwirq = fwspec->param[0];
  315. *type = fwspec->param[1];
  316. return 0;
  317. }
  318. return -EINVAL;
  319. }
  320. static int msm_mpm_gic_chip_alloc(struct irq_domain *domain,
  321. unsigned int virq,
  322. unsigned int nr_irqs,
  323. void *data)
  324. {
  325. struct irq_fwspec *fwspec = data;
  326. struct irq_fwspec parent_fwspec;
  327. irq_hw_number_t hwirq, parent_hwirq;
  328. unsigned int type;
  329. int ret;
  330. ret = msm_mpm_gic_chip_translate(domain, fwspec, &hwirq, &type);
  331. if (ret)
  332. return ret;
  333. irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
  334. &msm_mpm_gic_chip, NULL);
  335. parent_hwirq = get_parent_hwirq(domain, hwirq);
  336. if (parent_hwirq == MPM_NO_PARENT_IRQ)
  337. return 0;
  338. parent_fwspec.fwnode = domain->parent->fwnode;
  339. parent_fwspec.param_count = 3;
  340. parent_fwspec.param[0] = 0;
  341. parent_fwspec.param[1] = parent_hwirq;
  342. parent_fwspec.param[2] = type;
  343. return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
  344. &parent_fwspec);
  345. }
  346. static const struct irq_domain_ops msm_mpm_gic_chip_domain_ops = {
  347. .translate = msm_mpm_gic_chip_translate,
  348. .alloc = msm_mpm_gic_chip_alloc,
  349. .free = irq_domain_free_irqs_common,
  350. };
  351. static inline void msm_mpm_send_interrupt(void)
  352. {
  353. writel_relaxed(2, msm_mpm_dev_data.mpm_ipc_reg);
  354. /* Ensure the write is complete before returning. */
  355. wmb();
  356. }
  357. static inline void msm_mpm_timer_write(void)
  358. {
  359. u32 lo = ~0U, hi = ~0U, ctrl;
  360. ctrl = readl_relaxed(msm_mpm_dev_data.timer_frame_reg + MPM_CNTV_CTL);
  361. if (ctrl & MPM_ARCH_TIMER_CTRL_ENABLE) {
  362. lo = readl_relaxed(msm_mpm_dev_data.timer_frame_reg + MPM_CNTCVAL_LO);
  363. hi = readl_relaxed(msm_mpm_dev_data.timer_frame_reg + MPM_CNTCVAL_HI);
  364. }
  365. writel_relaxed(lo, msm_mpm_dev_data.mpm_request_reg_base);
  366. writel_relaxed(hi, msm_mpm_dev_data.mpm_request_reg_base + 0x4);
  367. }
  368. int msm_mpm_enter_sleep(struct cpumask *cpumask)
  369. {
  370. int i = 0;
  371. struct irq_chip *irq_chip;
  372. struct irq_data *irq_data;
  373. msm_mpm_timer_write();
  374. for (i = 0; i < QCOM_MPM_REG_WIDTH; i++)
  375. msm_mpm_write(MPM_REG_STATUS, i, 0);
  376. msm_mpm_send_interrupt();
  377. irq_data = irq_get_irq_data(msm_mpm_dev_data.ipc_irq);
  378. if (!irq_data)
  379. return -ENODEV;
  380. irq_chip = irq_data->chip;
  381. if (!irq_chip)
  382. return -ENODEV;
  383. if (cpumask && irq_chip->irq_set_affinity)
  384. irq_chip->irq_set_affinity(irq_data, cpumask, true);
  385. return 0;
  386. }
  387. EXPORT_SYMBOL(msm_mpm_enter_sleep);
  388. /*
  389. * Triggered by RPM when system resumes from deep sleep
  390. */
  391. static irqreturn_t msm_mpm_irq(int irq, void *dev_id)
  392. {
  393. unsigned long pending;
  394. uint32_t value[3];
  395. int i, k, apps_irq;
  396. unsigned int mpm_irq;
  397. struct irq_desc *desc = NULL;
  398. unsigned int reg = MPM_REG_ENABLE;
  399. bool pending_status;
  400. for (i = 0; i < QCOM_MPM_REG_WIDTH; i++) {
  401. value[i] = msm_mpm_read(reg, i);
  402. trace_mpm_wakeup_enable_irqs(i, value[i]);
  403. }
  404. for (i = 0; i < QCOM_MPM_REG_WIDTH; i++) {
  405. pending = msm_mpm_read(MPM_REG_STATUS, i);
  406. pending &= (unsigned long)value[i];
  407. trace_mpm_wakeup_pending_irqs(i, pending);
  408. for_each_set_bit(k, &pending, 32) {
  409. mpm_irq = 32 * i + k;
  410. apps_irq = mpm_to_irq[mpm_irq];
  411. desc = apps_irq ?
  412. irq_to_desc(apps_irq) : NULL;
  413. if (desc && !irqd_is_level_type(&desc->irq_data)) {
  414. irq_get_irqchip_state(apps_irq,
  415. IRQCHIP_STATE_PENDING, &pending_status);
  416. if (!pending_status)
  417. irq_set_irqchip_state(apps_irq,
  418. IRQCHIP_STATE_PENDING, true);
  419. }
  420. }
  421. }
  422. return IRQ_HANDLED;
  423. }
  424. static int msm_mpm_init(struct device_node *node)
  425. {
  426. struct msm_mpm_device_data *dev = &msm_mpm_dev_data;
  427. int ret = 0;
  428. int irq, index;
  429. index = of_property_match_string(node, "reg-names", "vmpm");
  430. if (index < 0) {
  431. ret = -EINVAL;
  432. goto reg_base_err;
  433. }
  434. dev->mpm_request_reg_base = of_iomap(node, index);
  435. if (!dev->mpm_request_reg_base) {
  436. pr_err("Unable to iomap\n");
  437. ret = -ENXIO;
  438. goto reg_base_err;
  439. }
  440. index = of_property_match_string(node, "reg-names", "ipc");
  441. if (index < 0) {
  442. ret = -EINVAL;
  443. goto reg_base_err;
  444. }
  445. dev->mpm_ipc_reg = of_iomap(node, index);
  446. if (!dev->mpm_ipc_reg) {
  447. pr_err("Unable to iomap IPC register\n");
  448. ret = -ENXIO;
  449. goto ipc_reg_err;
  450. }
  451. index = of_property_match_string(node, "reg-names", "timer");
  452. if (index < 0) {
  453. ret = -EINVAL;
  454. goto reg_base_err;
  455. }
  456. dev->timer_frame_reg = of_iomap(node, index);
  457. if (!dev->timer_frame_reg) {
  458. pr_err("Unable to iomap\n");
  459. ret = -ENXIO;
  460. goto reg_base_err;
  461. }
  462. irq = of_irq_get(node, 0);
  463. if (irq <= 0) {
  464. pr_err("no IRQ resource info\n");
  465. ret = irq;
  466. goto ipc_irq_err;
  467. }
  468. dev->ipc_irq = irq;
  469. ret = request_irq(dev->ipc_irq, msm_mpm_irq,
  470. IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, "mpm",
  471. msm_mpm_irq);
  472. if (ret) {
  473. pr_err("request_irq failed errno: %d\n", ret);
  474. goto ipc_irq_err;
  475. }
  476. ret = irq_set_irq_wake(dev->ipc_irq, 1);
  477. if (ret) {
  478. pr_err("failed to set wakeup irq %lu: %d\n",
  479. dev->ipc_irq, ret);
  480. goto set_wake_irq_err;
  481. }
  482. return 0;
  483. set_wake_irq_err:
  484. free_irq(dev->ipc_irq, msm_mpm_irq);
  485. ipc_irq_err:
  486. iounmap(dev->mpm_ipc_reg);
  487. ipc_reg_err:
  488. iounmap(dev->mpm_request_reg_base);
  489. reg_base_err:
  490. return ret;
  491. }
  492. const struct mpm_pin mpm_pitti_gic_chip_data[] = {
  493. {5, 296}, /* lpass_irq_out_sdc */
  494. {12, 422}, /* qmp_usb3_lfps_rxterm_irq_cx */
  495. {86, 183}, /* mpm_wake,spmi_m */
  496. {89, 314}, /* tsens0_tsens_0C_int */
  497. {90, 315}, /* tsens1_tsens_0C_int */
  498. {93, 188}, /* eud_p0_dpse_int_mx */
  499. {94, 188}, /* eud_p0_dmse_int_mx */
  500. {-1},
  501. };
  502. const struct mpm_pin mpm_blair_gic_chip_data[] = {
  503. {5, 296}, /* lpass_irq_out_sdc */
  504. {12, 422}, /* eud_p0_dpse_int_mx */
  505. {86, 183}, /* mpm_wake,spmi_m */
  506. {89, 314}, /* tsens0_tsens_0C_int */
  507. {90, 315}, /* eud_p0_dmse_int_mx */
  508. {93, 164}, /* eud_p0_dmse_int_mx */
  509. {94, 165}, /* eud_p0_dmse_int_mx */
  510. {-1},
  511. };
  512. const struct mpm_pin mpm_holi_gic_chip_data[] = {
  513. {5, 296}, /* lpass_irq_out_sdc */
  514. {12, 422}, /* qmp_usb3_lfps_rxterm_irq_cx */
  515. {86, 183}, /* mpm_wake,spmi_m */
  516. {89, 314}, /* tsens0_tsens_0C_int */
  517. {90, 315}, /* tsens1_tsens_0C_int */
  518. {93, 260}, /* eud_p0_dpse_int_mx */
  519. {94, 260}, /* eud_p0_dmse_int_mx */
  520. {-1},
  521. };
  522. static const struct of_device_id mpm_gic_chip_data_table[] = {
  523. {
  524. .compatible = "qcom,mpm-blair",
  525. .data = mpm_blair_gic_chip_data,
  526. },
  527. {
  528. .compatible = "qcom,mpm-holi",
  529. .data = mpm_holi_gic_chip_data,
  530. },
  531. {
  532. .compatible = "qcom,mpm-pitti",
  533. .data = mpm_pitti_gic_chip_data,
  534. },
  535. {}
  536. };
  537. MODULE_DEVICE_TABLE(of, mpm_gic_chip_data_table);
  538. static int msm_mpm_irqchip_init(struct device_node *node,
  539. struct device_node *parent)
  540. {
  541. struct irq_domain *parent_domain;
  542. const struct of_device_id *id;
  543. int ret;
  544. if (!parent) {
  545. pr_err("%s(): no parent for mpm-gic\n", node->full_name);
  546. return -ENXIO;
  547. }
  548. parent_domain = irq_find_host(parent);
  549. if (!parent_domain) {
  550. pr_err("unable to obtain gic parent domain\n");
  551. return -ENXIO;
  552. }
  553. of_property_read_u32(node, "qcom,num-mpm-irqs", &num_mpm_irqs);
  554. mpm_to_irq = kcalloc(num_mpm_irqs, sizeof(*mpm_to_irq), GFP_KERNEL);
  555. if (!mpm_to_irq)
  556. return -ENOMEM;
  557. id = of_match_node(mpm_gic_chip_data_table, node);
  558. if (!id) {
  559. pr_err("can not find mpm_gic_data_table of_node\n");
  560. ret = -ENODEV;
  561. goto mpm_map_err;
  562. }
  563. msm_mpm_dev_data.gic_chip_domain = irq_domain_create_hierarchy(
  564. parent_domain, 0, 256,
  565. of_fwnode_handle(node),
  566. &msm_mpm_gic_chip_domain_ops, (void *)id->data);
  567. if (!msm_mpm_dev_data.gic_chip_domain) {
  568. pr_err("gic domain add failed\n");
  569. ret = -ENOMEM;
  570. goto mpm_map_err;
  571. }
  572. msm_mpm_dev_data.gpio_chip_domain = irq_domain_create_hierarchy(
  573. parent_domain, IRQ_DOMAIN_FLAG_QCOM_MPM_WAKEUP,
  574. 256, of_node_to_fwnode(node),
  575. &msm_mpm_gpio_chip_domain_ops, NULL);
  576. if (!msm_mpm_dev_data.gpio_chip_domain)
  577. return -ENOMEM;
  578. irq_domain_update_bus_token(msm_mpm_dev_data.gpio_chip_domain, DOMAIN_BUS_WAKEUP);
  579. ret = msm_mpm_init(node);
  580. if (!ret)
  581. return ret;
  582. irq_domain_remove(msm_mpm_dev_data.gic_chip_domain);
  583. mpm_map_err:
  584. kfree(mpm_to_irq);
  585. return ret;
  586. }
  587. IRQCHIP_PLATFORM_DRIVER_BEGIN(msm_mpm)
  588. IRQCHIP_MATCH("qcom,mpm", msm_mpm_irqchip_init)
  589. IRQCHIP_PLATFORM_DRIVER_END(msm_mpm)
  590. MODULE_DESCRIPTION("Qualcomm Technologies, Inc. (QTI) MPM Driver");
  591. MODULE_LICENSE("GPL");