pinctrl-s3c24xx.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. /*
  2. * S3C24XX specific support for Samsung pinctrl/gpiolib driver.
  3. *
  4. * Copyright (c) 2013 Heiko Stuebner <[email protected]>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This file contains the SamsungS3C24XX specific information required by the
  12. * Samsung pinctrl/gpiolib driver. It also includes the implementation of
  13. * external gpio and wakeup interrupt support.
  14. */
  15. #include <linux/module.h>
  16. #include <linux/device.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/irqdomain.h>
  19. #include <linux/irq.h>
  20. #include <linux/of_irq.h>
  21. #include <linux/irqchip/chained_irq.h>
  22. #include <linux/io.h>
  23. #include <linux/slab.h>
  24. #include <linux/err.h>
  25. #include "pinctrl-samsung.h"
  26. #define NUM_EINT 24
  27. #define NUM_EINT_IRQ 6
  28. #define EINT_MAX_PER_GROUP 8
  29. #define EINTPEND_REG 0xa8
  30. #define EINTMASK_REG 0xa4
  31. #define EINT_GROUP(i) ((int)((i) / EINT_MAX_PER_GROUP))
  32. #define EINT_REG(i) ((EINT_GROUP(i) * 4) + 0x88)
  33. #define EINT_OFFS(i) ((i) % EINT_MAX_PER_GROUP * 4)
  34. #define EINT_LEVEL_LOW 0
  35. #define EINT_LEVEL_HIGH 1
  36. #define EINT_EDGE_FALLING 2
  37. #define EINT_EDGE_RISING 4
  38. #define EINT_EDGE_BOTH 6
  39. #define EINT_MASK 0xf
  40. static const struct samsung_pin_bank_type bank_type_1bit = {
  41. .fld_width = { 1, 1, },
  42. .reg_offset = { 0x00, 0x04, },
  43. };
  44. static const struct samsung_pin_bank_type bank_type_2bit = {
  45. .fld_width = { 2, 1, 2, },
  46. .reg_offset = { 0x00, 0x04, 0x08, },
  47. };
  48. #define PIN_BANK_A(pins, reg, id) \
  49. { \
  50. .type = &bank_type_1bit, \
  51. .pctl_offset = reg, \
  52. .nr_pins = pins, \
  53. .eint_type = EINT_TYPE_NONE, \
  54. .name = id \
  55. }
  56. #define PIN_BANK_2BIT(pins, reg, id) \
  57. { \
  58. .type = &bank_type_2bit, \
  59. .pctl_offset = reg, \
  60. .nr_pins = pins, \
  61. .eint_type = EINT_TYPE_NONE, \
  62. .name = id \
  63. }
  64. #define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs, emask)\
  65. { \
  66. .type = &bank_type_2bit, \
  67. .pctl_offset = reg, \
  68. .nr_pins = pins, \
  69. .eint_type = EINT_TYPE_WKUP, \
  70. .eint_func = 2, \
  71. .eint_mask = emask, \
  72. .eint_offset = eoffs, \
  73. .name = id \
  74. }
  75. /**
  76. * struct s3c24xx_eint_data: EINT common data
  77. * @drvdata: pin controller driver data
  78. * @domains: IRQ domains of particular EINT interrupts
  79. * @parents: mapped parent irqs in the main interrupt controller
  80. */
  81. struct s3c24xx_eint_data {
  82. struct samsung_pinctrl_drv_data *drvdata;
  83. struct irq_domain *domains[NUM_EINT];
  84. int parents[NUM_EINT_IRQ];
  85. };
  86. /**
  87. * struct s3c24xx_eint_domain_data: per irq-domain data
  88. * @bank: pin bank related to the domain
  89. * @eint_data: common data
  90. * eint0_3_parent_only: live eints 0-3 only in the main intc
  91. */
  92. struct s3c24xx_eint_domain_data {
  93. struct samsung_pin_bank *bank;
  94. struct s3c24xx_eint_data *eint_data;
  95. bool eint0_3_parent_only;
  96. };
  97. static int s3c24xx_eint_get_trigger(unsigned int type)
  98. {
  99. switch (type) {
  100. case IRQ_TYPE_EDGE_RISING:
  101. return EINT_EDGE_RISING;
  102. break;
  103. case IRQ_TYPE_EDGE_FALLING:
  104. return EINT_EDGE_FALLING;
  105. break;
  106. case IRQ_TYPE_EDGE_BOTH:
  107. return EINT_EDGE_BOTH;
  108. break;
  109. case IRQ_TYPE_LEVEL_HIGH:
  110. return EINT_LEVEL_HIGH;
  111. break;
  112. case IRQ_TYPE_LEVEL_LOW:
  113. return EINT_LEVEL_LOW;
  114. break;
  115. default:
  116. return -EINVAL;
  117. }
  118. }
  119. static void s3c24xx_eint_set_handler(struct irq_data *d, unsigned int type)
  120. {
  121. /* Edge- and level-triggered interrupts need different handlers */
  122. if (type & IRQ_TYPE_EDGE_BOTH)
  123. irq_set_handler_locked(d, handle_edge_irq);
  124. else
  125. irq_set_handler_locked(d, handle_level_irq);
  126. }
  127. static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
  128. struct samsung_pin_bank *bank, int pin)
  129. {
  130. const struct samsung_pin_bank_type *bank_type = bank->type;
  131. unsigned long flags;
  132. void __iomem *reg;
  133. u8 shift;
  134. u32 mask;
  135. u32 val;
  136. /* Make sure that pin is configured as interrupt */
  137. reg = d->virt_base + bank->pctl_offset;
  138. shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
  139. mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
  140. spin_lock_irqsave(&bank->slock, flags);
  141. val = readl(reg);
  142. val &= ~(mask << shift);
  143. val |= bank->eint_func << shift;
  144. writel(val, reg);
  145. spin_unlock_irqrestore(&bank->slock, flags);
  146. }
  147. static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
  148. {
  149. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  150. struct samsung_pinctrl_drv_data *d = bank->drvdata;
  151. int index = bank->eint_offset + data->hwirq;
  152. void __iomem *reg;
  153. int trigger;
  154. u8 shift;
  155. u32 val;
  156. trigger = s3c24xx_eint_get_trigger(type);
  157. if (trigger < 0) {
  158. dev_err(d->dev, "unsupported external interrupt type\n");
  159. return -EINVAL;
  160. }
  161. s3c24xx_eint_set_handler(data, type);
  162. /* Set up interrupt trigger */
  163. reg = d->virt_base + EINT_REG(index);
  164. shift = EINT_OFFS(index);
  165. val = readl(reg);
  166. val &= ~(EINT_MASK << shift);
  167. val |= trigger << shift;
  168. writel(val, reg);
  169. s3c24xx_eint_set_function(d, bank, data->hwirq);
  170. return 0;
  171. }
  172. /* Handling of EINTs 0-3 on all except S3C2412 and S3C2413 */
  173. static void s3c2410_eint0_3_ack(struct irq_data *data)
  174. {
  175. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  176. struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
  177. struct s3c24xx_eint_data *eint_data = ddata->eint_data;
  178. int parent_irq = eint_data->parents[data->hwirq];
  179. struct irq_chip *parent_chip = irq_get_chip(parent_irq);
  180. parent_chip->irq_ack(irq_get_irq_data(parent_irq));
  181. }
  182. static void s3c2410_eint0_3_mask(struct irq_data *data)
  183. {
  184. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  185. struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
  186. struct s3c24xx_eint_data *eint_data = ddata->eint_data;
  187. int parent_irq = eint_data->parents[data->hwirq];
  188. struct irq_chip *parent_chip = irq_get_chip(parent_irq);
  189. parent_chip->irq_mask(irq_get_irq_data(parent_irq));
  190. }
  191. static void s3c2410_eint0_3_unmask(struct irq_data *data)
  192. {
  193. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  194. struct s3c24xx_eint_domain_data *ddata = bank->irq_domain->host_data;
  195. struct s3c24xx_eint_data *eint_data = ddata->eint_data;
  196. int parent_irq = eint_data->parents[data->hwirq];
  197. struct irq_chip *parent_chip = irq_get_chip(parent_irq);
  198. parent_chip->irq_unmask(irq_get_irq_data(parent_irq));
  199. }
  200. static struct irq_chip s3c2410_eint0_3_chip = {
  201. .name = "s3c2410-eint0_3",
  202. .irq_ack = s3c2410_eint0_3_ack,
  203. .irq_mask = s3c2410_eint0_3_mask,
  204. .irq_unmask = s3c2410_eint0_3_unmask,
  205. .irq_set_type = s3c24xx_eint_type,
  206. };
  207. static void s3c2410_demux_eint0_3(struct irq_desc *desc)
  208. {
  209. struct irq_data *data = irq_desc_get_irq_data(desc);
  210. struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
  211. unsigned int virq;
  212. /* the first 4 eints have a simple 1 to 1 mapping */
  213. virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq);
  214. /* Something must be really wrong if an unmapped EINT is unmasked */
  215. BUG_ON(!virq);
  216. generic_handle_irq(virq);
  217. }
  218. /* Handling of EINTs 0-3 on S3C2412 and S3C2413 */
  219. static void s3c2412_eint0_3_ack(struct irq_data *data)
  220. {
  221. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  222. struct samsung_pinctrl_drv_data *d = bank->drvdata;
  223. unsigned long bitval = 1UL << data->hwirq;
  224. writel(bitval, d->virt_base + EINTPEND_REG);
  225. }
  226. static void s3c2412_eint0_3_mask(struct irq_data *data)
  227. {
  228. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  229. struct samsung_pinctrl_drv_data *d = bank->drvdata;
  230. unsigned long mask;
  231. mask = readl(d->virt_base + EINTMASK_REG);
  232. mask |= (1UL << data->hwirq);
  233. writel(mask, d->virt_base + EINTMASK_REG);
  234. }
  235. static void s3c2412_eint0_3_unmask(struct irq_data *data)
  236. {
  237. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  238. struct samsung_pinctrl_drv_data *d = bank->drvdata;
  239. unsigned long mask;
  240. mask = readl(d->virt_base + EINTMASK_REG);
  241. mask &= ~(1UL << data->hwirq);
  242. writel(mask, d->virt_base + EINTMASK_REG);
  243. }
  244. static struct irq_chip s3c2412_eint0_3_chip = {
  245. .name = "s3c2412-eint0_3",
  246. .irq_ack = s3c2412_eint0_3_ack,
  247. .irq_mask = s3c2412_eint0_3_mask,
  248. .irq_unmask = s3c2412_eint0_3_unmask,
  249. .irq_set_type = s3c24xx_eint_type,
  250. };
  251. static void s3c2412_demux_eint0_3(struct irq_desc *desc)
  252. {
  253. struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
  254. struct irq_data *data = irq_desc_get_irq_data(desc);
  255. struct irq_chip *chip = irq_data_get_irq_chip(data);
  256. unsigned int virq;
  257. chained_irq_enter(chip, desc);
  258. /* the first 4 eints have a simple 1 to 1 mapping */
  259. virq = irq_linear_revmap(eint_data->domains[data->hwirq], data->hwirq);
  260. /* Something must be really wrong if an unmapped EINT is unmasked */
  261. BUG_ON(!virq);
  262. generic_handle_irq(virq);
  263. chained_irq_exit(chip, desc);
  264. }
  265. /* Handling of all other eints */
  266. static void s3c24xx_eint_ack(struct irq_data *data)
  267. {
  268. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  269. struct samsung_pinctrl_drv_data *d = bank->drvdata;
  270. unsigned char index = bank->eint_offset + data->hwirq;
  271. writel(1UL << index, d->virt_base + EINTPEND_REG);
  272. }
  273. static void s3c24xx_eint_mask(struct irq_data *data)
  274. {
  275. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  276. struct samsung_pinctrl_drv_data *d = bank->drvdata;
  277. unsigned char index = bank->eint_offset + data->hwirq;
  278. unsigned long mask;
  279. mask = readl(d->virt_base + EINTMASK_REG);
  280. mask |= (1UL << index);
  281. writel(mask, d->virt_base + EINTMASK_REG);
  282. }
  283. static void s3c24xx_eint_unmask(struct irq_data *data)
  284. {
  285. struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
  286. struct samsung_pinctrl_drv_data *d = bank->drvdata;
  287. unsigned char index = bank->eint_offset + data->hwirq;
  288. unsigned long mask;
  289. mask = readl(d->virt_base + EINTMASK_REG);
  290. mask &= ~(1UL << index);
  291. writel(mask, d->virt_base + EINTMASK_REG);
  292. }
  293. static struct irq_chip s3c24xx_eint_chip = {
  294. .name = "s3c-eint",
  295. .irq_ack = s3c24xx_eint_ack,
  296. .irq_mask = s3c24xx_eint_mask,
  297. .irq_unmask = s3c24xx_eint_unmask,
  298. .irq_set_type = s3c24xx_eint_type,
  299. };
  300. static inline void s3c24xx_demux_eint(struct irq_desc *desc,
  301. u32 offset, u32 range)
  302. {
  303. struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
  304. struct irq_chip *chip = irq_desc_get_chip(desc);
  305. struct samsung_pinctrl_drv_data *d = data->drvdata;
  306. unsigned int pend, mask;
  307. chained_irq_enter(chip, desc);
  308. pend = readl(d->virt_base + EINTPEND_REG);
  309. mask = readl(d->virt_base + EINTMASK_REG);
  310. pend &= ~mask;
  311. pend &= range;
  312. while (pend) {
  313. unsigned int virq, irq;
  314. irq = __ffs(pend);
  315. pend &= ~(1 << irq);
  316. virq = irq_linear_revmap(data->domains[irq], irq - offset);
  317. /* Something is really wrong if an unmapped EINT is unmasked */
  318. BUG_ON(!virq);
  319. generic_handle_irq(virq);
  320. }
  321. chained_irq_exit(chip, desc);
  322. }
  323. static void s3c24xx_demux_eint4_7(struct irq_desc *desc)
  324. {
  325. s3c24xx_demux_eint(desc, 0, 0xf0);
  326. }
  327. static void s3c24xx_demux_eint8_23(struct irq_desc *desc)
  328. {
  329. s3c24xx_demux_eint(desc, 8, 0xffff00);
  330. }
  331. static irq_flow_handler_t s3c2410_eint_handlers[NUM_EINT_IRQ] = {
  332. s3c2410_demux_eint0_3,
  333. s3c2410_demux_eint0_3,
  334. s3c2410_demux_eint0_3,
  335. s3c2410_demux_eint0_3,
  336. s3c24xx_demux_eint4_7,
  337. s3c24xx_demux_eint8_23,
  338. };
  339. static irq_flow_handler_t s3c2412_eint_handlers[NUM_EINT_IRQ] = {
  340. s3c2412_demux_eint0_3,
  341. s3c2412_demux_eint0_3,
  342. s3c2412_demux_eint0_3,
  343. s3c2412_demux_eint0_3,
  344. s3c24xx_demux_eint4_7,
  345. s3c24xx_demux_eint8_23,
  346. };
  347. static int s3c24xx_gpf_irq_map(struct irq_domain *h, unsigned int virq,
  348. irq_hw_number_t hw)
  349. {
  350. struct s3c24xx_eint_domain_data *ddata = h->host_data;
  351. struct samsung_pin_bank *bank = ddata->bank;
  352. if (!(bank->eint_mask & (1 << (bank->eint_offset + hw))))
  353. return -EINVAL;
  354. if (hw <= 3) {
  355. if (ddata->eint0_3_parent_only)
  356. irq_set_chip_and_handler(virq, &s3c2410_eint0_3_chip,
  357. handle_edge_irq);
  358. else
  359. irq_set_chip_and_handler(virq, &s3c2412_eint0_3_chip,
  360. handle_edge_irq);
  361. } else {
  362. irq_set_chip_and_handler(virq, &s3c24xx_eint_chip,
  363. handle_edge_irq);
  364. }
  365. irq_set_chip_data(virq, bank);
  366. return 0;
  367. }
  368. static const struct irq_domain_ops s3c24xx_gpf_irq_ops = {
  369. .map = s3c24xx_gpf_irq_map,
  370. .xlate = irq_domain_xlate_twocell,
  371. };
  372. static int s3c24xx_gpg_irq_map(struct irq_domain *h, unsigned int virq,
  373. irq_hw_number_t hw)
  374. {
  375. struct s3c24xx_eint_domain_data *ddata = h->host_data;
  376. struct samsung_pin_bank *bank = ddata->bank;
  377. if (!(bank->eint_mask & (1 << (bank->eint_offset + hw))))
  378. return -EINVAL;
  379. irq_set_chip_and_handler(virq, &s3c24xx_eint_chip, handle_edge_irq);
  380. irq_set_chip_data(virq, bank);
  381. return 0;
  382. }
  383. static const struct irq_domain_ops s3c24xx_gpg_irq_ops = {
  384. .map = s3c24xx_gpg_irq_map,
  385. .xlate = irq_domain_xlate_twocell,
  386. };
  387. static const struct of_device_id s3c24xx_eint_irq_ids[] = {
  388. { .compatible = "samsung,s3c2410-wakeup-eint", .data = (void *)1 },
  389. { .compatible = "samsung,s3c2412-wakeup-eint", .data = (void *)0 },
  390. { }
  391. };
  392. static int s3c24xx_eint_init(struct samsung_pinctrl_drv_data *d)
  393. {
  394. struct device *dev = d->dev;
  395. const struct of_device_id *match;
  396. struct device_node *eint_np = NULL;
  397. struct device_node *np;
  398. struct samsung_pin_bank *bank;
  399. struct s3c24xx_eint_data *eint_data;
  400. const struct irq_domain_ops *ops;
  401. unsigned int i;
  402. bool eint0_3_parent_only;
  403. irq_flow_handler_t *handlers;
  404. for_each_child_of_node(dev->of_node, np) {
  405. match = of_match_node(s3c24xx_eint_irq_ids, np);
  406. if (match) {
  407. eint_np = np;
  408. eint0_3_parent_only = (bool)match->data;
  409. break;
  410. }
  411. }
  412. if (!eint_np)
  413. return -ENODEV;
  414. eint_data = devm_kzalloc(dev, sizeof(*eint_data), GFP_KERNEL);
  415. if (!eint_data)
  416. return -ENOMEM;
  417. eint_data->drvdata = d;
  418. handlers = eint0_3_parent_only ? s3c2410_eint_handlers
  419. : s3c2412_eint_handlers;
  420. for (i = 0; i < NUM_EINT_IRQ; ++i) {
  421. unsigned int irq;
  422. irq = irq_of_parse_and_map(eint_np, i);
  423. if (!irq) {
  424. dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
  425. return -ENXIO;
  426. }
  427. eint_data->parents[i] = irq;
  428. irq_set_chained_handler_and_data(irq, handlers[i], eint_data);
  429. }
  430. bank = d->pin_banks;
  431. for (i = 0; i < d->nr_banks; ++i, ++bank) {
  432. struct s3c24xx_eint_domain_data *ddata;
  433. unsigned int mask;
  434. unsigned int irq;
  435. unsigned int pin;
  436. if (bank->eint_type != EINT_TYPE_WKUP)
  437. continue;
  438. ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
  439. if (!ddata)
  440. return -ENOMEM;
  441. ddata->bank = bank;
  442. ddata->eint_data = eint_data;
  443. ddata->eint0_3_parent_only = eint0_3_parent_only;
  444. ops = (bank->eint_offset == 0) ? &s3c24xx_gpf_irq_ops
  445. : &s3c24xx_gpg_irq_ops;
  446. bank->irq_domain = irq_domain_add_linear(bank->of_node,
  447. bank->nr_pins, ops, ddata);
  448. if (!bank->irq_domain) {
  449. dev_err(dev, "wkup irq domain add failed\n");
  450. return -ENXIO;
  451. }
  452. irq = bank->eint_offset;
  453. mask = bank->eint_mask;
  454. for (pin = 0; mask; ++pin, mask >>= 1) {
  455. if (irq >= NUM_EINT)
  456. break;
  457. if (!(mask & 1))
  458. continue;
  459. eint_data->domains[irq] = bank->irq_domain;
  460. ++irq;
  461. }
  462. }
  463. return 0;
  464. }
  465. static const struct samsung_pin_bank_data s3c2412_pin_banks[] __initconst = {
  466. PIN_BANK_A(23, 0x000, "gpa"),
  467. PIN_BANK_2BIT(11, 0x010, "gpb"),
  468. PIN_BANK_2BIT(16, 0x020, "gpc"),
  469. PIN_BANK_2BIT(16, 0x030, "gpd"),
  470. PIN_BANK_2BIT(16, 0x040, "gpe"),
  471. PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
  472. PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
  473. PIN_BANK_2BIT(11, 0x070, "gph"),
  474. PIN_BANK_2BIT(13, 0x080, "gpj"),
  475. };
  476. const struct samsung_pin_ctrl s3c2412_pin_ctrl[] __initconst = {
  477. {
  478. .pin_banks = s3c2412_pin_banks,
  479. .nr_banks = ARRAY_SIZE(s3c2412_pin_banks),
  480. .eint_wkup_init = s3c24xx_eint_init,
  481. },
  482. };
  483. static const struct samsung_pin_bank_data s3c2416_pin_banks[] __initconst = {
  484. PIN_BANK_A(27, 0x000, "gpa"),
  485. PIN_BANK_2BIT(11, 0x010, "gpb"),
  486. PIN_BANK_2BIT(16, 0x020, "gpc"),
  487. PIN_BANK_2BIT(16, 0x030, "gpd"),
  488. PIN_BANK_2BIT(16, 0x040, "gpe"),
  489. PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
  490. PIN_BANK_2BIT_EINTW(8, 0x060, "gpg", 8, 0xff00),
  491. PIN_BANK_2BIT(15, 0x070, "gph"),
  492. PIN_BANK_2BIT(16, 0x0e0, "gpk"),
  493. PIN_BANK_2BIT(14, 0x0f0, "gpl"),
  494. PIN_BANK_2BIT(2, 0x100, "gpm"),
  495. };
  496. const struct samsung_pin_ctrl s3c2416_pin_ctrl[] __initconst = {
  497. {
  498. .pin_banks = s3c2416_pin_banks,
  499. .nr_banks = ARRAY_SIZE(s3c2416_pin_banks),
  500. .eint_wkup_init = s3c24xx_eint_init,
  501. },
  502. };
  503. static const struct samsung_pin_bank_data s3c2440_pin_banks[] __initconst = {
  504. PIN_BANK_A(25, 0x000, "gpa"),
  505. PIN_BANK_2BIT(11, 0x010, "gpb"),
  506. PIN_BANK_2BIT(16, 0x020, "gpc"),
  507. PIN_BANK_2BIT(16, 0x030, "gpd"),
  508. PIN_BANK_2BIT(16, 0x040, "gpe"),
  509. PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
  510. PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
  511. PIN_BANK_2BIT(11, 0x070, "gph"),
  512. PIN_BANK_2BIT(13, 0x0d0, "gpj"),
  513. };
  514. const struct samsung_pin_ctrl s3c2440_pin_ctrl[] __initconst = {
  515. {
  516. .pin_banks = s3c2440_pin_banks,
  517. .nr_banks = ARRAY_SIZE(s3c2440_pin_banks),
  518. .eint_wkup_init = s3c24xx_eint_init,
  519. },
  520. };
  521. static const struct samsung_pin_bank_data s3c2450_pin_banks[] __initconst = {
  522. PIN_BANK_A(28, 0x000, "gpa"),
  523. PIN_BANK_2BIT(11, 0x010, "gpb"),
  524. PIN_BANK_2BIT(16, 0x020, "gpc"),
  525. PIN_BANK_2BIT(16, 0x030, "gpd"),
  526. PIN_BANK_2BIT(16, 0x040, "gpe"),
  527. PIN_BANK_2BIT_EINTW(8, 0x050, "gpf", 0, 0xff),
  528. PIN_BANK_2BIT_EINTW(16, 0x060, "gpg", 8, 0xffff00),
  529. PIN_BANK_2BIT(15, 0x070, "gph"),
  530. PIN_BANK_2BIT(16, 0x0d0, "gpj"),
  531. PIN_BANK_2BIT(16, 0x0e0, "gpk"),
  532. PIN_BANK_2BIT(15, 0x0f0, "gpl"),
  533. PIN_BANK_2BIT(2, 0x100, "gpm"),
  534. };
  535. const struct samsung_pin_ctrl s3c2450_pin_ctrl[] __initconst = {
  536. {
  537. .pin_banks = s3c2450_pin_banks,
  538. .nr_banks = ARRAY_SIZE(s3c2450_pin_banks),
  539. .eint_wkup_init = s3c24xx_eint_init,
  540. },
  541. };