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