gpio-samsung.c 30 KB

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