1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * A gpio chip driver for TXx9 SoCs |
4 | * |
5 | * Copyright (C) 2008 Atsushi Nemoto <anemo@mba.ocn.ne.jp> |
6 | */ |
7 | |
8 | #include <linux/init.h> |
9 | #include <linux/spinlock.h> |
10 | #include <linux/gpio/driver.h> |
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 | { |
21 | return !!(__raw_readl(addr: &txx9_pioptr->din) & (1 << offset)); |
22 | } |
23 | |
24 | static void txx9_gpio_set_raw(unsigned int offset, int value) |
25 | { |
26 | u32 val; |
27 | val = __raw_readl(addr: &txx9_pioptr->dout); |
28 | if (value) |
29 | val |= 1 << offset; |
30 | else |
31 | val &= ~(1 << offset); |
32 | __raw_writel(val, addr: &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(lock: &txx9_gpio_lock, flags); |
43 | } |
44 | |
45 | static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset) |
46 | { |
47 | unsigned long flags; |
48 | spin_lock_irqsave(&txx9_gpio_lock, flags); |
49 | __raw_writel(__raw_readl(addr: &txx9_pioptr->dir) & ~(1 << offset), |
50 | addr: &txx9_pioptr->dir); |
51 | mmiowb(); |
52 | spin_unlock_irqrestore(lock: &txx9_gpio_lock, flags); |
53 | return 0; |
54 | } |
55 | |
56 | static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset, |
57 | int value) |
58 | { |
59 | unsigned long flags; |
60 | spin_lock_irqsave(&txx9_gpio_lock, flags); |
61 | txx9_gpio_set_raw(offset, value); |
62 | __raw_writel(__raw_readl(addr: &txx9_pioptr->dir) | (1 << offset), |
63 | addr: &txx9_pioptr->dir); |
64 | mmiowb(); |
65 | spin_unlock_irqrestore(lock: &txx9_gpio_lock, flags); |
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; |
85 | return gpiochip_add_data(&txx9_gpio_chip, NULL); |
86 | } |
87 | |