2 * Loongson-2F/3A/3B GPIO Support
4 * Copyright (c) 2008 Richard Liu, STMicroelectronics <richard.liu@st.com>
5 * Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
6 * Copyright (c) 2013 Hongbing Hu <huhb@lemote.com>
7 * Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/spinlock.h>
19 #include <linux/err.h>
20 #include <linux/gpio/driver.h>
21 #include <linux/platform_device.h>
22 #include <linux/bitops.h>
23 #include <asm/types.h>
26 #define STLS2F_N_GPIO 4
27 #define STLS3A_N_GPIO 16
29 #ifdef CONFIG_CPU_LOONGSON3
30 #define LOONGSON_N_GPIO STLS3A_N_GPIO
32 #define LOONGSON_N_GPIO STLS2F_N_GPIO
36 * Offset into the register where we read lines, we write them from offset 0.
37 * This offset is the only thing that stand between us and using
40 #define LOONGSON_GPIO_IN_OFFSET 16
42 static DEFINE_SPINLOCK(gpio_lock
);
44 static int loongson_gpio_get_value(struct gpio_chip
*chip
, unsigned gpio
)
48 spin_lock(&gpio_lock
);
49 val
= LOONGSON_GPIODATA
;
50 spin_unlock(&gpio_lock
);
52 return !!(val
& BIT(gpio
+ LOONGSON_GPIO_IN_OFFSET
));
55 static void loongson_gpio_set_value(struct gpio_chip
*chip
,
56 unsigned gpio
, int value
)
60 spin_lock(&gpio_lock
);
61 val
= LOONGSON_GPIODATA
;
66 LOONGSON_GPIODATA
= val
;
67 spin_unlock(&gpio_lock
);
70 static int loongson_gpio_direction_input(struct gpio_chip
*chip
, unsigned gpio
)
74 spin_lock(&gpio_lock
);
75 temp
= LOONGSON_GPIOIE
;
77 LOONGSON_GPIOIE
= temp
;
78 spin_unlock(&gpio_lock
);
83 static int loongson_gpio_direction_output(struct gpio_chip
*chip
,
84 unsigned gpio
, int level
)
88 loongson_gpio_set_value(chip
, gpio
, level
);
89 spin_lock(&gpio_lock
);
90 temp
= LOONGSON_GPIOIE
;
92 LOONGSON_GPIOIE
= temp
;
93 spin_unlock(&gpio_lock
);
98 static int loongson_gpio_probe(struct platform_device
*pdev
)
100 struct gpio_chip
*gc
;
101 struct device
*dev
= &pdev
->dev
;
103 gc
= devm_kzalloc(dev
, sizeof(*gc
), GFP_KERNEL
);
107 gc
->label
= "loongson-gpio-chip";
109 gc
->ngpio
= LOONGSON_N_GPIO
;
110 gc
->get
= loongson_gpio_get_value
;
111 gc
->set
= loongson_gpio_set_value
;
112 gc
->direction_input
= loongson_gpio_direction_input
;
113 gc
->direction_output
= loongson_gpio_direction_output
;
115 return gpiochip_add_data(gc
, NULL
);
118 static struct platform_driver loongson_gpio_driver
= {
120 .name
= "loongson-gpio",
122 .probe
= loongson_gpio_probe
,
125 static int __init
loongson_gpio_setup(void)
127 struct platform_device
*pdev
;
130 ret
= platform_driver_register(&loongson_gpio_driver
);
132 pr_err("error registering loongson GPIO driver\n");
136 pdev
= platform_device_register_simple("loongson-gpio", -1, NULL
, 0);
137 return PTR_ERR_OR_ZERO(pdev
);
139 postcore_initcall(loongson_gpio_setup
);