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