aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorwu guoxing <b39297@freescale.com>2012-01-30 01:31:20 -0500
committerGrant Likely <grant.likely@secretlab.ca>2012-01-30 09:49:08 -0500
commit608589b15f02e59e8c40df7ef861064f1b6fa504 (patch)
tree55c7119187542ee660cc7aaafa8662caf2cc894e /drivers/gpio
parentdcd6c92267155e70a94b3927bce681ce74b80d1f (diff)
ARM/mx35/3ds: gpio: add mc9s08dz60 gpio function
we only use the gpio function of mc9s08dz60 mcu chip, so just add the gpio driver, as this mcu will never be used in other board. Signed-off-by: Wu Guoxing <b39297@freescale.com> Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-mc9s08dz60.c161
3 files changed, 168 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d0c41188d4e5..eaa7d3828e70 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -225,6 +225,12 @@ config GPIO_MAX732X_IRQ
225 Say yes here to enable the max732x to be used as an interrupt 225 Say yes here to enable the max732x to be used as an interrupt
226 controller. It requires the driver to be built in the kernel. 226 controller. It requires the driver to be built in the kernel.
227 227
228config GPIO_MC9S08DZ60
229 bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
230 depends on I2C && MACH_MX35_3DS
231 help
232 Select this to enable the MC9S08DZ60 GPIO driver
233
228config GPIO_PCA953X 234config GPIO_PCA953X
229 tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" 235 tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
230 depends on I2C 236 depends on I2C
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index fa10df604c01..8863a7f2dece 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_MAX7300) += gpio-max7300.o
26obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o 26obj-$(CONFIG_GPIO_MAX7301) += gpio-max7301.o
27obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o 27obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o
28obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o 28obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
29obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
29obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o 30obj-$(CONFIG_GPIO_MCP23S08) += gpio-mcp23s08.o
30obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o 31obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o
31obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o 32obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c
new file mode 100644
index 000000000000..2738cc44d636
--- /dev/null
+++ b/drivers/gpio/gpio-mc9s08dz60.c
@@ -0,0 +1,161 @@
1/*
2 * Copyright 2009-2012 Freescale Semiconductor, Inc. All Rights Reserved.
3 *
4 * Author: Wu Guoxing <b39297@freescale.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/i2c.h>
21#include <linux/gpio.h>
22
23#define GPIO_GROUP_NUM 2
24#define GPIO_NUM_PER_GROUP 8
25#define GPIO_NUM (GPIO_GROUP_NUM*GPIO_NUM_PER_GROUP)
26
27struct mc9s08dz60 {
28 struct i2c_client *client;
29 struct gpio_chip chip;
30};
31
32static inline struct mc9s08dz60 *to_mc9s08dz60(struct gpio_chip *gc)
33{
34 return container_of(gc, struct mc9s08dz60, chip);
35}
36
37
38static void mc9s_gpio_to_reg_and_bit(int offset, u8 *reg, u8 *bit)
39{
40 *reg = 0x20 + offset / GPIO_NUM_PER_GROUP;
41 *bit = offset % GPIO_NUM_PER_GROUP;
42}
43
44static int mc9s08dz60_get_value(struct gpio_chip *gc, unsigned offset)
45{
46 u8 reg, bit;
47 s32 value;
48 struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
49
50 mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
51 value = i2c_smbus_read_byte_data(mc9s->client, reg);
52
53 return (value >= 0) ? (value >> bit) & 0x1 : 0;
54}
55
56static int mc9s08dz60_set(struct mc9s08dz60 *mc9s, unsigned offset, int val)
57{
58 u8 reg, bit;
59 s32 value;
60
61 mc9s_gpio_to_reg_and_bit(offset, &reg, &bit);
62 value = i2c_smbus_read_byte_data(mc9s->client, reg);
63 if (value >= 0) {
64 if (val)
65 value |= 1 << bit;
66 else
67 value &= ~(1 << bit);
68
69 return i2c_smbus_write_byte_data(mc9s->client, reg, value);
70 } else
71 return value;
72
73}
74
75
76static void mc9s08dz60_set_value(struct gpio_chip *gc, unsigned offset, int val)
77{
78 struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
79
80 mc9s08dz60_set(mc9s, offset, val);
81}
82
83static int mc9s08dz60_direction_output(struct gpio_chip *gc,
84 unsigned offset, int val)
85{
86 struct mc9s08dz60 *mc9s = to_mc9s08dz60(gc);
87
88 return mc9s08dz60_set(mc9s, offset, val);
89}
90
91static int mc9s08dz60_probe(struct i2c_client *client,
92 const struct i2c_device_id *id)
93{
94 int ret = 0;
95 struct mc9s08dz60 *mc9s;
96
97 mc9s = kzalloc(sizeof(*mc9s), GFP_KERNEL);
98 if (!mc9s)
99 return -ENOMEM;
100
101 mc9s->chip.label = client->name;
102 mc9s->chip.base = -1;
103 mc9s->chip.dev = &client->dev;
104 mc9s->chip.owner = THIS_MODULE;
105 mc9s->chip.ngpio = GPIO_NUM;
106 mc9s->chip.can_sleep = 1;
107 mc9s->chip.get = mc9s08dz60_get_value;
108 mc9s->chip.set = mc9s08dz60_set_value;
109 mc9s->chip.direction_output = mc9s08dz60_direction_output;
110 mc9s->client = client;
111 i2c_set_clientdata(client, mc9s);
112
113 ret = gpiochip_add(&mc9s->chip);
114 if (ret)
115 goto error;
116
117 return 0;
118
119 error:
120 kfree(mc9s);
121 return ret;
122}
123
124static int mc9s08dz60_remove(struct i2c_client *client)
125{
126 struct mc9s08dz60 *mc9s;
127 int ret;
128
129 mc9s = i2c_get_clientdata(client);
130
131 ret = gpiochip_remove(&mc9s->chip);
132 if (!ret)
133 kfree(mc9s);
134
135 return ret;
136
137}
138
139static const struct i2c_device_id mc9s08dz60_id[] = {
140 {"mc9s08dz60", 0},
141 {},
142};
143
144MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id);
145
146static struct i2c_driver mc9s08dz60_i2c_driver = {
147 .driver = {
148 .owner = THIS_MODULE,
149 .name = "mc9s08dz60",
150 },
151 .probe = mc9s08dz60_probe,
152 .remove = mc9s08dz60_remove,
153 .id_table = mc9s08dz60_id,
154};
155
156module_i2c_driver(mc9s08dz60_i2c_driver);
157
158MODULE_AUTHOR("Freescale Semiconductor, Inc. "
159 "Wu Guoxing <b39297@freescale.com>");
160MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board");
161MODULE_LICENSE("GPL v2");