gpio-samsung.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. /*
  2. * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
  3. * http://www.samsung.com/
  4. *
  5. * Copyright 2008 Openmoko, Inc.
  6. * Copyright 2008 Simtec Electronics
  7. * Ben Dooks <ben@simtec.co.uk>
  8. * http://armlinux.simtec.co.uk/
  9. *
  10. * SAMSUNG - GPIOlib support
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License version 2 as
  14. * published by the Free Software Foundation.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/irq.h>
  18. #include <linux/io.h>
  19. #include <linux/gpio.h>
  20. #include <linux/init.h>
  21. #include <linux/spinlock.h>
  22. #include <linux/module.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/device.h>
  25. #include <linux/ioport.h>
  26. #include <linux/of.h>
  27. #include <linux/slab.h>
  28. #include <linux/of_address.h>
  29. #include <asm/irq.h>
  30. #include <mach/irqs.h>
  31. #include <mach/map.h>
  32. #include <mach/regs-gpio.h>
  33. #include <mach/gpio-samsung.h>
  34. #include <plat/cpu.h>
  35. #include <plat/gpio-core.h>
  36. #include <plat/gpio-cfg.h>
  37. #include <plat/gpio-cfg-helpers.h>
  38. #include <plat/pm.h>
  39. int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
  40. unsigned int off, samsung_gpio_pull_t pull)
  41. {
  42. void __iomem *reg = chip->base + 0x08;
  43. int shift = off * 2;
  44. u32 pup;
  45. pup = __raw_readl(reg);
  46. pup &= ~(3 << shift);
  47. pup |= pull << shift;
  48. __raw_writel(pup, reg);
  49. return 0;
  50. }
  51. samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
  52. unsigned int off)
  53. {
  54. void __iomem *reg = chip->base + 0x08;
  55. int shift = off * 2;
  56. u32 pup = __raw_readl(reg);
  57. pup >>= shift;
  58. pup &= 0x3;
  59. return (__force samsung_gpio_pull_t)pup;
  60. }
  61. int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
  62. unsigned int off, samsung_gpio_pull_t pull)
  63. {
  64. switch (pull) {
  65. case S3C_GPIO_PULL_NONE:
  66. pull = 0x01;
  67. break;
  68. case S3C_GPIO_PULL_UP:
  69. pull = 0x00;
  70. break;
  71. case S3C_GPIO_PULL_DOWN:
  72. pull = 0x02;
  73. break;
  74. }
  75. return samsung_gpio_setpull_updown(chip, off, pull);
  76. }
  77. samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
  78. unsigned int off)
  79. {
  80. samsung_gpio_pull_t pull;
  81. pull = samsung_gpio_getpull_updown(chip, off);
  82. switch (pull) {
  83. case 0x00:
  84. pull = S3C_GPIO_PULL_UP;
  85. break;
  86. case 0x01:
  87. case 0x03:
  88. pull = S3C_GPIO_PULL_NONE;
  89. break;
  90. case 0x02:
  91. pull = S3C_GPIO_PULL_DOWN;
  92. break;
  93. }
  94. return pull;
  95. }
  96. static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
  97. unsigned int off, samsung_gpio_pull_t pull,
  98. samsung_gpio_pull_t updown)
  99. {
  100. void __iomem *reg = chip->base + 0x08;
  101. u32 pup = __raw_readl(reg);
  102. if (pull == updown)
  103. pup &= ~(1 << off);
  104. else if (pull == S3C_GPIO_PULL_NONE)
  105. pup |= (1 << off);
  106. else
  107. return -EINVAL;
  108. __raw_writel(pup, reg);
  109. return 0;
  110. }
  111. static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
  112. unsigned int off,
  113. samsung_gpio_pull_t updown)
  114. {
  115. void __iomem *reg = chip->base + 0x08;
  116. u32 pup = __raw_readl(reg);
  117. pup &= (1 << off);
  118. return pup ? S3C_GPIO_PULL_NONE : updown;
  119. }
  120. samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
  121. unsigned int off)
  122. {
  123. return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
  124. }
  125. int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
  126. unsigned int off, samsung_gpio_pull_t pull)
  127. {
  128. return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
  129. }
  130. samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
  131. unsigned int off)
  132. {
  133. return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
  134. }
  135. int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
  136. unsigned int off, samsung_gpio_pull_t pull)
  137. {
  138. return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
  139. }
  140. /*
  141. * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
  142. * @chip: The gpio chip that is being configured.
  143. * @off: The offset for the GPIO being configured.
  144. * @cfg: The configuration value to set.
  145. *
  146. * This helper deal with the GPIO cases where the control register
  147. * has two bits of configuration per gpio, which have the following
  148. * functions:
  149. * 00 = input
  150. * 01 = output
  151. * 1x = special function
  152. */
  153. static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
  154. unsigned int off, unsigned int cfg)
  155. {
  156. void __iomem *reg = chip->base;
  157. unsigned int shift = off * 2;
  158. u32 con;
  159. if (samsung_gpio_is_cfg_special(cfg)) {
  160. cfg &= 0xf;
  161. if (cfg > 3)
  162. return -EINVAL;
  163. cfg <<= shift;
  164. }
  165. con = __raw_readl(reg);
  166. con &= ~(0x3 << shift);
  167. con |= cfg;
  168. __raw_writel(con, reg);
  169. return 0;
  170. }
  171. /*
  172. * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
  173. * @chip: The gpio chip that is being configured.
  174. * @off: The offset for the GPIO being configured.
  175. *
  176. * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
  177. * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
  178. * S3C_GPIO_SPECIAL() macro.
  179. */
  180. static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
  181. unsigned int off)
  182. {
  183. u32 con;
  184. con = __raw_readl(chip->base);
  185. con >>= off * 2;
  186. con &= 3;
  187. /* this conversion works for IN and OUT as well as special mode */
  188. return S3C_GPIO_SPECIAL(con);
  189. }
  190. /*
  191. * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
  192. * @chip: The gpio chip that is being configured.
  193. * @off: The offset for the GPIO being configured.
  194. * @cfg: The configuration value to set.
  195. *
  196. * This helper deal with the GPIO cases where the control register has 4 bits
  197. * of control per GPIO, generally in the form of:
  198. * 0000 = Input
  199. * 0001 = Output
  200. * others = Special functions (dependent on bank)
  201. *
  202. * Note, since the code to deal with the case where there are two control
  203. * registers instead of one, we do not have a separate set of functions for
  204. * each case.
  205. */
  206. static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
  207. unsigned int off, unsigned int cfg)
  208. {
  209. void __iomem *reg = chip->base;
  210. unsigned int shift = (off & 7) * 4;
  211. u32 con;
  212. if (off < 8 && chip->chip.ngpio > 8)
  213. reg -= 4;
  214. if (samsung_gpio_is_cfg_special(cfg)) {
  215. cfg &= 0xf;
  216. cfg <<= shift;
  217. }
  218. con = __raw_readl(reg);
  219. con &= ~(0xf << shift);
  220. con |= cfg;
  221. __raw_writel(con, reg);
  222. return 0;
  223. }
  224. /*
  225. * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
  226. * @chip: The gpio chip that is being configured.
  227. * @off: The offset for the GPIO being configured.
  228. *
  229. * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
  230. * register setting into a value the software can use, such as could be passed
  231. * to samsung_gpio_setcfg_4bit().
  232. *
  233. * @sa samsung_gpio_getcfg_2bit
  234. */
  235. static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
  236. unsigned int off)
  237. {
  238. void __iomem *reg = chip->base;
  239. unsigned int shift = (off & 7) * 4;
  240. u32 con;
  241. if (off < 8 && chip->chip.ngpio > 8)
  242. reg -= 4;
  243. con = __raw_readl(reg);
  244. con >>= shift;
  245. con &= 0xf;
  246. /* this conversion works for IN and OUT as well as special mode */
  247. return S3C_GPIO_SPECIAL(con);
  248. }
  249. #ifdef CONFIG_PLAT_S3C24XX
  250. /*
  251. * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
  252. * @chip: The gpio chip that is being configured.
  253. * @off: The offset for the GPIO being configured.
  254. * @cfg: The configuration value to set.
  255. *
  256. * This helper deal with the GPIO cases where the control register
  257. * has one bit of configuration for the gpio, where setting the bit
  258. * means the pin is in special function mode and unset means output.
  259. */
  260. static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
  261. unsigned int off, unsigned int cfg)
  262. {
  263. void __iomem *reg = chip->base;
  264. unsigned int shift = off;
  265. u32 con;
  266. if (samsung_gpio_is_cfg_special(cfg)) {
  267. cfg &= 0xf;
  268. /* Map output to 0, and SFN2 to 1 */
  269. cfg -= 1;
  270. if (cfg > 1)
  271. return -EINVAL;
  272. cfg <<= shift;
  273. }
  274. con = __raw_readl(reg);
  275. con &= ~(0x1 << shift);
  276. con |= cfg;
  277. __raw_writel(con, reg);
  278. return 0;
  279. }
  280. /*
  281. * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
  282. * @chip: The gpio chip that is being configured.
  283. * @off: The offset for the GPIO being configured.
  284. *
  285. * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
  286. * GPIO configuration value.
  287. *
  288. * @sa samsung_gpio_getcfg_2bit
  289. * @sa samsung_gpio_getcfg_4bit
  290. */
  291. static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
  292. unsigned int off)
  293. {
  294. u32 con;
  295. con = __raw_readl(chip->base);
  296. con >>= off;
  297. con &= 1;
  298. con++;
  299. return S3C_GPIO_SFN(con);
  300. }
  301. #endif
  302. static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
  303. int nr_chips)
  304. {
  305. for (; nr_chips > 0; nr_chips--, chipcfg++) {
  306. if (!chipcfg->set_config)
  307. chipcfg->set_config = samsung_gpio_setcfg_4bit;
  308. if (!chipcfg->get_config)
  309. chipcfg->get_config = samsung_gpio_getcfg_4bit;
  310. if (!chipcfg->set_pull)
  311. chipcfg->set_pull = samsung_gpio_setpull_updown;
  312. if (!chipcfg->get_pull)
  313. chipcfg->get_pull = samsung_gpio_getpull_updown;
  314. }
  315. }
  316. struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
  317. .set_config = samsung_gpio_setcfg_2bit,
  318. .get_config = samsung_gpio_getcfg_2bit,
  319. };
  320. #ifdef CONFIG_PLAT_S3C24XX
  321. static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
  322. .set_config = s3c24xx_gpio_setcfg_abank,
  323. .get_config = s3c24xx_gpio_getcfg_abank,
  324. };
  325. #endif
  326. static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
  327. [0] = {
  328. .cfg_eint = 0x0,
  329. },
  330. [1] = {
  331. .cfg_eint = 0x3,
  332. },
  333. [2] = {
  334. .cfg_eint = 0x7,
  335. },
  336. [3] = {
  337. .cfg_eint = 0xF,
  338. },
  339. [4] = {
  340. .cfg_eint = 0x0,
  341. .set_config = samsung_gpio_setcfg_2bit,
  342. .get_config = samsung_gpio_getcfg_2bit,
  343. },
  344. [5] = {
  345. .cfg_eint = 0x2,
  346. .set_config = samsung_gpio_setcfg_2bit,
  347. .get_config = samsung_gpio_getcfg_2bit,
  348. },
  349. [6] = {
  350. .cfg_eint = 0x3,
  351. .set_config = samsung_gpio_setcfg_2bit,
  352. .get_config = samsung_gpio_getcfg_2bit,
  353. },
  354. [7] = {
  355. .set_config = samsung_gpio_setcfg_2bit,
  356. .get_config = samsung_gpio_getcfg_2bit,
  357. },
  358. };
  359. /*
  360. * Default routines for controlling GPIO, based on the original S3C24XX
  361. * GPIO functions which deal with the case where each gpio bank of the
  362. * chip is as following:
  363. *
  364. * base + 0x00: Control register, 2 bits per gpio
  365. * gpio n: 2 bits starting at (2*n)
  366. * 00 = input, 01 = output, others mean special-function
  367. * base + 0x04: Data register, 1 bit per gpio
  368. * bit n: data bit n
  369. */
  370. static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
  371. {
  372. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  373. void __iomem *base = ourchip->base;
  374. unsigned long flags;
  375. unsigned long con;
  376. samsung_gpio_lock(ourchip, flags);
  377. con = __raw_readl(base + 0x00);
  378. con &= ~(3 << (offset * 2));
  379. __raw_writel(con, base + 0x00);
  380. samsung_gpio_unlock(ourchip, flags);
  381. return 0;
  382. }
  383. static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
  384. unsigned offset, int value)
  385. {
  386. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  387. void __iomem *base = ourchip->base;
  388. unsigned long flags;
  389. unsigned long dat;
  390. unsigned long con;
  391. samsung_gpio_lock(ourchip, flags);
  392. dat = __raw_readl(base + 0x04);
  393. dat &= ~(1 << offset);
  394. if (value)
  395. dat |= 1 << offset;
  396. __raw_writel(dat, base + 0x04);
  397. con = __raw_readl(base + 0x00);
  398. con &= ~(3 << (offset * 2));
  399. con |= 1 << (offset * 2);
  400. __raw_writel(con, base + 0x00);
  401. __raw_writel(dat, base + 0x04);
  402. samsung_gpio_unlock(ourchip, flags);
  403. return 0;
  404. }
  405. /*
  406. * The samsung_gpiolib_4bit routines are to control the gpio banks where
  407. * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
  408. * following example:
  409. *
  410. * base + 0x00: Control register, 4 bits per gpio
  411. * gpio n: 4 bits starting at (4*n)
  412. * 0000 = input, 0001 = output, others mean special-function
  413. * base + 0x04: Data register, 1 bit per gpio
  414. * bit n: data bit n
  415. *
  416. * Note, since the data register is one bit per gpio and is at base + 0x4
  417. * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
  418. * state of the output.
  419. */
  420. static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
  421. unsigned int offset)
  422. {
  423. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  424. void __iomem *base = ourchip->base;
  425. unsigned long con;
  426. con = __raw_readl(base + GPIOCON_OFF);
  427. if (ourchip->bitmap_gpio_int & BIT(offset))
  428. con |= 0xf << con_4bit_shift(offset);
  429. else
  430. con &= ~(0xf << con_4bit_shift(offset));
  431. __raw_writel(con, base + GPIOCON_OFF);
  432. pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
  433. return 0;
  434. }
  435. static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
  436. unsigned int offset, int value)
  437. {
  438. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  439. void __iomem *base = ourchip->base;
  440. unsigned long con;
  441. unsigned long dat;
  442. con = __raw_readl(base + GPIOCON_OFF);
  443. con &= ~(0xf << con_4bit_shift(offset));
  444. con |= 0x1 << con_4bit_shift(offset);
  445. dat = __raw_readl(base + GPIODAT_OFF);
  446. if (value)
  447. dat |= 1 << offset;
  448. else
  449. dat &= ~(1 << offset);
  450. __raw_writel(dat, base + GPIODAT_OFF);
  451. __raw_writel(con, base + GPIOCON_OFF);
  452. __raw_writel(dat, base + GPIODAT_OFF);
  453. pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
  454. return 0;
  455. }
  456. /*
  457. * The next set of routines are for the case where the GPIO configuration
  458. * registers are 4 bits per GPIO but there is more than one register (the
  459. * bank has more than 8 GPIOs.
  460. *
  461. * This case is the similar to the 4 bit case, but the registers are as
  462. * follows:
  463. *
  464. * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
  465. * gpio n: 4 bits starting at (4*n)
  466. * 0000 = input, 0001 = output, others mean special-function
  467. * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
  468. * gpio n: 4 bits starting at (4*n)
  469. * 0000 = input, 0001 = output, others mean special-function
  470. * base + 0x08: Data register, 1 bit per gpio
  471. * bit n: data bit n
  472. *
  473. * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
  474. * routines we store the 'base + 0x4' address so that these routines see
  475. * the data register at ourchip->base + 0x04.
  476. */
  477. static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
  478. unsigned int offset)
  479. {
  480. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  481. void __iomem *base = ourchip->base;
  482. void __iomem *regcon = base;
  483. unsigned long con;
  484. if (offset > 7)
  485. offset -= 8;
  486. else
  487. regcon -= 4;
  488. con = __raw_readl(regcon);
  489. con &= ~(0xf << con_4bit_shift(offset));
  490. __raw_writel(con, regcon);
  491. pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
  492. return 0;
  493. }
  494. static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
  495. unsigned int offset, int value)
  496. {
  497. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  498. void __iomem *base = ourchip->base;
  499. void __iomem *regcon = base;
  500. unsigned long con;
  501. unsigned long dat;
  502. unsigned con_offset = offset;
  503. if (con_offset > 7)
  504. con_offset -= 8;
  505. else
  506. regcon -= 4;
  507. con = __raw_readl(regcon);
  508. con &= ~(0xf << con_4bit_shift(con_offset));
  509. con |= 0x1 << con_4bit_shift(con_offset);
  510. dat = __raw_readl(base + GPIODAT_OFF);
  511. if (value)
  512. dat |= 1 << offset;
  513. else
  514. dat &= ~(1 << offset);
  515. __raw_writel(dat, base + GPIODAT_OFF);
  516. __raw_writel(con, regcon);
  517. __raw_writel(dat, base + GPIODAT_OFF);
  518. pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
  519. return 0;
  520. }
  521. #ifdef CONFIG_PLAT_S3C24XX
  522. /* The next set of routines are for the case of s3c24xx bank a */
  523. static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
  524. {
  525. return -EINVAL;
  526. }
  527. static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
  528. unsigned offset, int value)
  529. {
  530. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  531. void __iomem *base = ourchip->base;
  532. unsigned long flags;
  533. unsigned long dat;
  534. unsigned long con;
  535. local_irq_save(flags);
  536. con = __raw_readl(base + 0x00);
  537. dat = __raw_readl(base + 0x04);
  538. dat &= ~(1 << offset);
  539. if (value)
  540. dat |= 1 << offset;
  541. __raw_writel(dat, base + 0x04);
  542. con &= ~(1 << offset);
  543. __raw_writel(con, base + 0x00);
  544. __raw_writel(dat, base + 0x04);
  545. local_irq_restore(flags);
  546. return 0;
  547. }
  548. #endif
  549. static void samsung_gpiolib_set(struct gpio_chip *chip,
  550. unsigned offset, int value)
  551. {
  552. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  553. void __iomem *base = ourchip->base;
  554. unsigned long flags;
  555. unsigned long dat;
  556. samsung_gpio_lock(ourchip, flags);
  557. dat = __raw_readl(base + 0x04);
  558. dat &= ~(1 << offset);
  559. if (value)
  560. dat |= 1 << offset;
  561. __raw_writel(dat, base + 0x04);
  562. samsung_gpio_unlock(ourchip, flags);
  563. }
  564. static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
  565. {
  566. struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
  567. unsigned long val;
  568. val = __raw_readl(ourchip->base + 0x04);
  569. val >>= offset;
  570. val &= 1;
  571. return val;
  572. }
  573. /*
  574. * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
  575. * for use with the configuration calls, and other parts of the s3c gpiolib
  576. * support code.
  577. *
  578. * Not all s3c support code will need this, as some configurations of cpu
  579. * may only support one or two different configuration options and have an
  580. * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
  581. * the machine support file should provide its own samsung_gpiolib_getchip()
  582. * and any other necessary functions.
  583. */
  584. #ifdef CONFIG_S3C_GPIO_TRACK
  585. struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
  586. static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
  587. {
  588. unsigned int gpn;
  589. int i;
  590. gpn = chip->chip.base;
  591. for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
  592. BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
  593. s3c_gpios[gpn] = chip;
  594. }
  595. }
  596. #endif /* CONFIG_S3C_GPIO_TRACK */
  597. /*
  598. * samsung_gpiolib_add() - add the Samsung gpio_chip.
  599. * @chip: The chip to register
  600. *
  601. * This is a wrapper to gpiochip_add() that takes our specific gpio chip
  602. * information and makes the necessary alterations for the platform and
  603. * notes the information for use with the configuration systems and any
  604. * other parts of the system.
  605. */
  606. static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
  607. {
  608. struct gpio_chip *gc = &chip->chip;
  609. int ret;
  610. BUG_ON(!chip->base);
  611. BUG_ON(!gc->label);
  612. BUG_ON(!gc->ngpio);
  613. spin_lock_init(&chip->lock);
  614. if (!gc->direction_input)
  615. gc->direction_input = samsung_gpiolib_2bit_input;
  616. if (!gc->direction_output)
  617. gc->direction_output = samsung_gpiolib_2bit_output;
  618. if (!gc->set)
  619. gc->set = samsung_gpiolib_set;
  620. if (!gc->get)
  621. gc->get = samsung_gpiolib_get;
  622. #ifdef CONFIG_PM
  623. if (chip->pm != NULL) {
  624. if (!chip->pm->save || !chip->pm->resume)
  625. pr_err("gpio: %s has missing PM functions\n",
  626. gc->label);
  627. } else
  628. pr_err("gpio: %s has no PM function\n", gc->label);
  629. #endif
  630. /* gpiochip_add() prints own failure message on error. */
  631. ret = gpiochip_add_data(gc, chip);
  632. if (ret >= 0)
  633. s3c_gpiolib_track(chip);
  634. }
  635. static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
  636. int nr_chips, void __iomem *base)
  637. {
  638. int i;
  639. struct gpio_chip *gc = &chip->chip;
  640. for (i = 0 ; i < nr_chips; i++, chip++) {
  641. /* skip banks not present on SoC */
  642. if (chip->chip.base >= S3C_GPIO_END)
  643. continue;
  644. if (!chip->config)
  645. chip->config = &s3c24xx_gpiocfg_default;
  646. if (!chip->pm)
  647. chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
  648. if ((base != NULL) && (chip->base == NULL))
  649. chip->base = base + ((i) * 0x10);
  650. if (!gc->direction_input)
  651. gc->direction_input = samsung_gpiolib_2bit_input;
  652. if (!gc->direction_output)
  653. gc->direction_output = samsung_gpiolib_2bit_output;
  654. samsung_gpiolib_add(chip);
  655. }
  656. }
  657. static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
  658. int nr_chips, void __iomem *base,
  659. unsigned int offset)
  660. {
  661. int i;
  662. for (i = 0 ; i < nr_chips; i++, chip++) {
  663. chip->chip.direction_input = samsung_gpiolib_2bit_input;
  664. chip->chip.direction_output = samsung_gpiolib_2bit_output;
  665. if (!chip->config)
  666. chip->config = &samsung_gpio_cfgs[7];
  667. if (!chip->pm)
  668. chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
  669. if ((base != NULL) && (chip->base == NULL))
  670. chip->base = base + ((i) * offset);
  671. samsung_gpiolib_add(chip);
  672. }
  673. }
  674. /*
  675. * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
  676. * @chip: The gpio chip that is being configured.
  677. * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
  678. *
  679. * This helper deal with the GPIO cases where the control register has 4 bits
  680. * of control per GPIO, generally in the form of:
  681. * 0000 = Input
  682. * 0001 = Output
  683. * others = Special functions (dependent on bank)
  684. *
  685. * Note, since the code to deal with the case where there are two control
  686. * registers instead of one, we do not have a separate set of function
  687. * (samsung_gpiolib_add_4bit2_chips)for each case.
  688. */
  689. static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
  690. int nr_chips, void __iomem *base)
  691. {
  692. int i;
  693. for (i = 0 ; i < nr_chips; i++, chip++) {
  694. chip->chip.direction_input = samsung_gpiolib_4bit_input;
  695. chip->chip.direction_output = samsung_gpiolib_4bit_output;
  696. if (!chip->config)
  697. chip->config = &samsung_gpio_cfgs[2];
  698. if (!chip->pm)
  699. chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
  700. if ((base != NULL) && (chip->base == NULL))
  701. chip->base = base + ((i) * 0x20);
  702. chip->bitmap_gpio_int = 0;
  703. samsung_gpiolib_add(chip);
  704. }
  705. }
  706. static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
  707. int nr_chips)
  708. {
  709. for (; nr_chips > 0; nr_chips--, chip++) {
  710. chip->chip.direction_input = samsung_gpiolib_4bit2_input;
  711. chip->chip.direction_output = samsung_gpiolib_4bit2_output;
  712. if (!chip->config)
  713. chip->config = &samsung_gpio_cfgs[2];
  714. if (!chip->pm)
  715. chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
  716. samsung_gpiolib_add(chip);
  717. }
  718. }
  719. int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
  720. {
  721. struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
  722. return samsung_chip->irq_base + offset;
  723. }
  724. #ifdef CONFIG_PLAT_S3C24XX
  725. static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
  726. {
  727. if (offset < 4) {
  728. if (soc_is_s3c2412())
  729. return IRQ_EINT0_2412 + offset;
  730. else
  731. return IRQ_EINT0 + offset;
  732. }
  733. if (offset < 8)
  734. return IRQ_EINT4 + offset - 4;
  735. return -EINVAL;
  736. }
  737. #endif
  738. #ifdef CONFIG_ARCH_S3C64XX
  739. static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
  740. {
  741. return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
  742. }
  743. static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
  744. {
  745. return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
  746. }
  747. #endif
  748. struct samsung_gpio_chip s3c24xx_gpios[] = {
  749. #ifdef CONFIG_PLAT_S3C24XX
  750. {
  751. .config = &s3c24xx_gpiocfg_banka,
  752. .chip = {
  753. .base = S3C2410_GPA(0),
  754. .owner = THIS_MODULE,
  755. .label = "GPIOA",
  756. .ngpio = 27,
  757. .direction_input = s3c24xx_gpiolib_banka_input,
  758. .direction_output = s3c24xx_gpiolib_banka_output,
  759. },
  760. }, {
  761. .chip = {
  762. .base = S3C2410_GPB(0),
  763. .owner = THIS_MODULE,
  764. .label = "GPIOB",
  765. .ngpio = 11,
  766. },
  767. }, {
  768. .chip = {
  769. .base = S3C2410_GPC(0),
  770. .owner = THIS_MODULE,
  771. .label = "GPIOC",
  772. .ngpio = 16,
  773. },
  774. }, {
  775. .chip = {
  776. .base = S3C2410_GPD(0),
  777. .owner = THIS_MODULE,
  778. .label = "GPIOD",
  779. .ngpio = 16,
  780. },
  781. }, {
  782. .chip = {
  783. .base = S3C2410_GPE(0),
  784. .label = "GPIOE",
  785. .owner = THIS_MODULE,
  786. .ngpio = 16,
  787. },
  788. }, {
  789. .chip = {
  790. .base = S3C2410_GPF(0),
  791. .owner = THIS_MODULE,
  792. .label = "GPIOF",
  793. .ngpio = 8,
  794. .to_irq = s3c24xx_gpiolib_fbank_to_irq,
  795. },
  796. }, {
  797. .irq_base = IRQ_EINT8,
  798. .chip = {
  799. .base = S3C2410_GPG(0),
  800. .owner = THIS_MODULE,
  801. .label = "GPIOG",
  802. .ngpio = 16,
  803. .to_irq = samsung_gpiolib_to_irq,
  804. },
  805. }, {
  806. .chip = {
  807. .base = S3C2410_GPH(0),
  808. .owner = THIS_MODULE,
  809. .label = "GPIOH",
  810. .ngpio = 15,
  811. },
  812. },
  813. /* GPIOS for the S3C2443 and later devices. */
  814. {
  815. .base = S3C2440_GPJCON,
  816. .chip = {
  817. .base = S3C2410_GPJ(0),
  818. .owner = THIS_MODULE,
  819. .label = "GPIOJ",
  820. .ngpio = 16,
  821. },
  822. }, {
  823. .base = S3C2443_GPKCON,
  824. .chip = {
  825. .base = S3C2410_GPK(0),
  826. .owner = THIS_MODULE,
  827. .label = "GPIOK",
  828. .ngpio = 16,
  829. },
  830. }, {
  831. .base = S3C2443_GPLCON,
  832. .chip = {
  833. .base = S3C2410_GPL(0),
  834. .owner = THIS_MODULE,
  835. .label = "GPIOL",
  836. .ngpio = 15,
  837. },
  838. }, {
  839. .base = S3C2443_GPMCON,
  840. .chip = {
  841. .base = S3C2410_GPM(0),
  842. .owner = THIS_MODULE,
  843. .label = "GPIOM",
  844. .ngpio = 2,
  845. },
  846. },
  847. #endif
  848. };
  849. /*
  850. * GPIO bank summary:
  851. *
  852. * Bank GPIOs Style SlpCon ExtInt Group
  853. * A 8 4Bit Yes 1
  854. * B 7 4Bit Yes 1
  855. * C 8 4Bit Yes 2
  856. * D 5 4Bit Yes 3
  857. * E 5 4Bit Yes None
  858. * F 16 2Bit Yes 4 [1]
  859. * G 7 4Bit Yes 5
  860. * H 10 4Bit[2] Yes 6
  861. * I 16 2Bit Yes None
  862. * J 12 2Bit Yes None
  863. * K 16 4Bit[2] No None
  864. * L 15 4Bit[2] No None
  865. * M 6 4Bit No IRQ_EINT
  866. * N 16 2Bit No IRQ_EINT
  867. * O 16 2Bit Yes 7
  868. * P 15 2Bit Yes 8
  869. * Q 9 2Bit Yes 9
  870. *
  871. * [1] BANKF pins 14,15 do not form part of the external interrupt sources
  872. * [2] BANK has two control registers, GPxCON0 and GPxCON1
  873. */
  874. static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
  875. #ifdef CONFIG_ARCH_S3C64XX
  876. {
  877. .chip = {
  878. .base = S3C64XX_GPA(0),
  879. .ngpio = S3C64XX_GPIO_A_NR,
  880. .label = "GPA",
  881. },
  882. }, {
  883. .chip = {
  884. .base = S3C64XX_GPB(0),
  885. .ngpio = S3C64XX_GPIO_B_NR,
  886. .label = "GPB",
  887. },
  888. }, {
  889. .chip = {
  890. .base = S3C64XX_GPC(0),
  891. .ngpio = S3C64XX_GPIO_C_NR,
  892. .label = "GPC",
  893. },
  894. }, {
  895. .chip = {
  896. .base = S3C64XX_GPD(0),
  897. .ngpio = S3C64XX_GPIO_D_NR,
  898. .label = "GPD",
  899. },
  900. }, {
  901. .config = &samsung_gpio_cfgs[0],
  902. .chip = {
  903. .base = S3C64XX_GPE(0),
  904. .ngpio = S3C64XX_GPIO_E_NR,
  905. .label = "GPE",
  906. },
  907. }, {
  908. .base = S3C64XX_GPG_BASE,
  909. .chip = {
  910. .base = S3C64XX_GPG(0),
  911. .ngpio = S3C64XX_GPIO_G_NR,
  912. .label = "GPG",
  913. },
  914. }, {
  915. .base = S3C64XX_GPM_BASE,
  916. .config = &samsung_gpio_cfgs[1],
  917. .chip = {
  918. .base = S3C64XX_GPM(0),
  919. .ngpio = S3C64XX_GPIO_M_NR,
  920. .label = "GPM",
  921. .to_irq = s3c64xx_gpiolib_mbank_to_irq,
  922. },
  923. },
  924. #endif
  925. };
  926. static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
  927. #ifdef CONFIG_ARCH_S3C64XX
  928. {
  929. .base = S3C64XX_GPH_BASE + 0x4,
  930. .chip = {
  931. .base = S3C64XX_GPH(0),
  932. .ngpio = S3C64XX_GPIO_H_NR,
  933. .label = "GPH",
  934. },
  935. }, {
  936. .base = S3C64XX_GPK_BASE + 0x4,
  937. .config = &samsung_gpio_cfgs[0],
  938. .chip = {
  939. .base = S3C64XX_GPK(0),
  940. .ngpio = S3C64XX_GPIO_K_NR,
  941. .label = "GPK",
  942. },
  943. }, {
  944. .base = S3C64XX_GPL_BASE + 0x4,
  945. .config = &samsung_gpio_cfgs[1],
  946. .chip = {
  947. .base = S3C64XX_GPL(0),
  948. .ngpio = S3C64XX_GPIO_L_NR,
  949. .label = "GPL",
  950. .to_irq = s3c64xx_gpiolib_lbank_to_irq,
  951. },
  952. },
  953. #endif
  954. };
  955. static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
  956. #ifdef CONFIG_ARCH_S3C64XX
  957. {
  958. .base = S3C64XX_GPF_BASE,
  959. .config = &samsung_gpio_cfgs[6],
  960. .chip = {
  961. .base = S3C64XX_GPF(0),
  962. .ngpio = S3C64XX_GPIO_F_NR,
  963. .label = "GPF",
  964. },
  965. }, {
  966. .config = &samsung_gpio_cfgs[7],
  967. .chip = {
  968. .base = S3C64XX_GPI(0),
  969. .ngpio = S3C64XX_GPIO_I_NR,
  970. .label = "GPI",
  971. },
  972. }, {
  973. .config = &samsung_gpio_cfgs[7],
  974. .chip = {
  975. .base = S3C64XX_GPJ(0),
  976. .ngpio = S3C64XX_GPIO_J_NR,
  977. .label = "GPJ",
  978. },
  979. }, {
  980. .config = &samsung_gpio_cfgs[6],
  981. .chip = {
  982. .base = S3C64XX_GPO(0),
  983. .ngpio = S3C64XX_GPIO_O_NR,
  984. .label = "GPO",
  985. },
  986. }, {
  987. .config = &samsung_gpio_cfgs[6],
  988. .chip = {
  989. .base = S3C64XX_GPP(0),
  990. .ngpio = S3C64XX_GPIO_P_NR,
  991. .label = "GPP",
  992. },
  993. }, {
  994. .config = &samsung_gpio_cfgs[6],
  995. .chip = {
  996. .base = S3C64XX_GPQ(0),
  997. .ngpio = S3C64XX_GPIO_Q_NR,
  998. .label = "GPQ",
  999. },
  1000. }, {
  1001. .base = S3C64XX_GPN_BASE,
  1002. .irq_base = IRQ_EINT(0),
  1003. .config = &samsung_gpio_cfgs[5],
  1004. .chip = {
  1005. .base = S3C64XX_GPN(0),
  1006. .ngpio = S3C64XX_GPIO_N_NR,
  1007. .label = "GPN",
  1008. .to_irq = samsung_gpiolib_to_irq,
  1009. },
  1010. },
  1011. #endif
  1012. };
  1013. /* TODO: cleanup soc_is_* */
  1014. static __init int samsung_gpiolib_init(void)
  1015. {
  1016. /*
  1017. * Currently there are two drivers that can provide GPIO support for
  1018. * Samsung SoCs. For device tree enabled platforms, the new
  1019. * pinctrl-samsung driver is used, providing both GPIO and pin control
  1020. * interfaces. For legacy (non-DT) platforms this driver is used.
  1021. */
  1022. if (of_have_populated_dt())
  1023. return 0;
  1024. if (soc_is_s3c24xx()) {
  1025. samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
  1026. ARRAY_SIZE(samsung_gpio_cfgs));
  1027. s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
  1028. ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
  1029. } else if (soc_is_s3c64xx()) {
  1030. samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
  1031. ARRAY_SIZE(samsung_gpio_cfgs));
  1032. samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
  1033. ARRAY_SIZE(s3c64xx_gpios_2bit),
  1034. S3C64XX_VA_GPIO + 0xE0, 0x20);
  1035. samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
  1036. ARRAY_SIZE(s3c64xx_gpios_4bit),
  1037. S3C64XX_VA_GPIO);
  1038. samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
  1039. ARRAY_SIZE(s3c64xx_gpios_4bit2));
  1040. }
  1041. return 0;
  1042. }
  1043. core_initcall(samsung_gpiolib_init);
  1044. int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
  1045. {
  1046. struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
  1047. unsigned long flags;
  1048. int offset;
  1049. int ret;
  1050. if (!chip)
  1051. return -EINVAL;
  1052. offset = pin - chip->chip.base;
  1053. samsung_gpio_lock(chip, flags);
  1054. ret = samsung_gpio_do_setcfg(chip, offset, config);
  1055. samsung_gpio_unlock(chip, flags);
  1056. return ret;
  1057. }
  1058. EXPORT_SYMBOL(s3c_gpio_cfgpin);
  1059. int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
  1060. unsigned int cfg)
  1061. {
  1062. int ret;
  1063. for (; nr > 0; nr--, start++) {
  1064. ret = s3c_gpio_cfgpin(start, cfg);
  1065. if (ret != 0)
  1066. return ret;
  1067. }
  1068. return 0;
  1069. }
  1070. EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
  1071. int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
  1072. unsigned int cfg, samsung_gpio_pull_t pull)
  1073. {
  1074. int ret;
  1075. for (; nr > 0; nr--, start++) {
  1076. s3c_gpio_setpull(start, pull);
  1077. ret = s3c_gpio_cfgpin(start, cfg);
  1078. if (ret != 0)
  1079. return ret;
  1080. }
  1081. return 0;
  1082. }
  1083. EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
  1084. unsigned s3c_gpio_getcfg(unsigned int pin)
  1085. {
  1086. struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
  1087. unsigned long flags;
  1088. unsigned ret = 0;
  1089. int offset;
  1090. if (chip) {
  1091. offset = pin - chip->chip.base;
  1092. samsung_gpio_lock(chip, flags);
  1093. ret = samsung_gpio_do_getcfg(chip, offset);
  1094. samsung_gpio_unlock(chip, flags);
  1095. }
  1096. return ret;
  1097. }
  1098. EXPORT_SYMBOL(s3c_gpio_getcfg);
  1099. int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
  1100. {
  1101. struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
  1102. unsigned long flags;
  1103. int offset, ret;
  1104. if (!chip)
  1105. return -EINVAL;
  1106. offset = pin - chip->chip.base;
  1107. samsung_gpio_lock(chip, flags);
  1108. ret = samsung_gpio_do_setpull(chip, offset, pull);
  1109. samsung_gpio_unlock(chip, flags);
  1110. return ret;
  1111. }
  1112. EXPORT_SYMBOL(s3c_gpio_setpull);
  1113. samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
  1114. {
  1115. struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
  1116. unsigned long flags;
  1117. int offset;
  1118. u32 pup = 0;
  1119. if (chip) {
  1120. offset = pin - chip->chip.base;
  1121. samsung_gpio_lock(chip, flags);
  1122. pup = samsung_gpio_do_getpull(chip, offset);
  1123. samsung_gpio_unlock(chip, flags);
  1124. }
  1125. return (__force samsung_gpio_pull_t)pup;
  1126. }
  1127. EXPORT_SYMBOL(s3c_gpio_getpull);
  1128. #ifdef CONFIG_PLAT_S3C24XX
  1129. unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
  1130. {
  1131. unsigned long flags;
  1132. unsigned long misccr;
  1133. local_irq_save(flags);
  1134. misccr = __raw_readl(S3C24XX_MISCCR);
  1135. misccr &= ~clear;
  1136. misccr ^= change;
  1137. __raw_writel(misccr, S3C24XX_MISCCR);
  1138. local_irq_restore(flags);
  1139. return misccr;
  1140. }
  1141. EXPORT_SYMBOL(s3c2410_modify_misccr);
  1142. #endif