gpio-samsung.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  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