Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
a9aec7fe AN |
2 | /* |
3 | * A gpio chip driver for TXx9 SoCs | |
4 | * | |
5 | * Copyright (C) 2008 Atsushi Nemoto <anemo@mba.ocn.ne.jp> | |
a9aec7fe AN |
6 | */ |
7 | ||
8 | #include <linux/init.h> | |
9 | #include <linux/spinlock.h> | |
d98312f7 | 10 | #include <linux/gpio/driver.h> |
a9aec7fe AN |
11 | #include <linux/errno.h> |
12 | #include <linux/io.h> | |
13 | #include <asm/txx9pio.h> | |
14 | ||
15 | static DEFINE_SPINLOCK(txx9_gpio_lock); | |
16 | ||
17 | static struct txx9_pio_reg __iomem *txx9_pioptr; | |
18 | ||
19 | static int txx9_gpio_get(struct gpio_chip *chip, unsigned int offset) | |
20 | { | |
6ea6b7fa | 21 | return !!(__raw_readl(&txx9_pioptr->din) & (1 << offset)); |
a9aec7fe AN |
22 | } |
23 | ||
24 | static void txx9_gpio_set_raw(unsigned int offset, int value) | |
25 | { | |
26 | u32 val; | |
27 | val = __raw_readl(&txx9_pioptr->dout); | |
28 | if (value) | |
29 | val |= 1 << offset; | |
30 | else | |
31 | val &= ~(1 << offset); | |
32 | __raw_writel(val, &txx9_pioptr->dout); | |
33 | } | |
34 | ||
35 | static void txx9_gpio_set(struct gpio_chip *chip, unsigned int offset, | |
36 | int value) | |
37 | { | |
38 | unsigned long flags; | |
39 | spin_lock_irqsave(&txx9_gpio_lock, flags); | |
40 | txx9_gpio_set_raw(offset, value); | |
41 | mmiowb(); | |
42 | spin_unlock_irqrestore(&txx9_gpio_lock, flags); | |
43 | } | |
44 | ||
45 | static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset) | |
46 | { | |
14476007 AN |
47 | unsigned long flags; |
48 | spin_lock_irqsave(&txx9_gpio_lock, flags); | |
a9aec7fe AN |
49 | __raw_writel(__raw_readl(&txx9_pioptr->dir) & ~(1 << offset), |
50 | &txx9_pioptr->dir); | |
51 | mmiowb(); | |
14476007 | 52 | spin_unlock_irqrestore(&txx9_gpio_lock, flags); |
a9aec7fe AN |
53 | return 0; |
54 | } | |
55 | ||
56 | static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset, | |
57 | int value) | |
58 | { | |
14476007 AN |
59 | unsigned long flags; |
60 | spin_lock_irqsave(&txx9_gpio_lock, flags); | |
a9aec7fe AN |
61 | txx9_gpio_set_raw(offset, value); |
62 | __raw_writel(__raw_readl(&txx9_pioptr->dir) | (1 << offset), | |
63 | &txx9_pioptr->dir); | |
64 | mmiowb(); | |
14476007 | 65 | spin_unlock_irqrestore(&txx9_gpio_lock, flags); |
a9aec7fe AN |
66 | return 0; |
67 | } | |
68 | ||
69 | static struct gpio_chip txx9_gpio_chip = { | |
70 | .get = txx9_gpio_get, | |
71 | .set = txx9_gpio_set, | |
72 | .direction_input = txx9_gpio_dir_in, | |
73 | .direction_output = txx9_gpio_dir_out, | |
74 | .label = "TXx9", | |
75 | }; | |
76 | ||
77 | int __init txx9_gpio_init(unsigned long baseaddr, | |
78 | unsigned int base, unsigned int num) | |
79 | { | |
80 | txx9_pioptr = ioremap(baseaddr, sizeof(struct txx9_pio_reg)); | |
81 | if (!txx9_pioptr) | |
82 | return -ENODEV; | |
83 | txx9_gpio_chip.base = base; | |
84 | txx9_gpio_chip.ngpio = num; | |
d98312f7 | 85 | return gpiochip_add_data(&txx9_gpio_chip, NULL); |
a9aec7fe | 86 | } |