1 /*
2  * drivers/i2c/busses/i2c-ixp2000.c
3  *
4  * I2C adapter for IXP2000 systems using GPIOs for I2C bus
5  *
6  * Author: Deepak Saxena <dsaxena@plexity.net>
7  * Based on IXDP2400 code by: Naeem M. Afzal <naeem.m.afzal@intel.com>
8  * Made generic by: Jeff Daly <jeffrey.daly@intel.com>
9  *
10  * Copyright (c) 2003-2004 MontaVista Software Inc.
11  *
12  * This file is licensed under  the terms of the GNU General Public
13  * License version 2. This program is licensed "as is" without any
14  * warranty of any kind, whether express or implied.
15  *
16  * From Jeff Daly:
17  *
18  * I2C adapter driver for Intel IXDP2xxx platforms. This should work for any
19  * IXP2000 platform if it uses the HW GPIO in the same manner.  Basically,
20  * SDA and SCL GPIOs have external pullups.  Setting the respective GPIO to
21  * an input will make the signal a '1' via the pullup.  Setting them to
22  * outputs will pull them down.
23  *
24  * The GPIOs are open drain signals and are used as configuration strap inputs
25  * during power-up so there's generally a buffer on the board that needs to be
26  * 'enabled' to drive the GPIOs.
27  */
28 
29 #include <linux/kernel.h>
30 #include <linux/init.h>
31 #include <linux/platform_device.h>
32 #include <linux/module.h>
33 #include <linux/i2c.h>
34 #include <linux/i2c-algo-bit.h>
35 #include <linux/slab.h>
36 
37 #include <mach/hardware.h>	/* Pick up IXP2000-specific bits */
38 #include <mach/gpio-ixp2000.h>
39 
ixp2000_scl_pin(void * data)40 static inline int ixp2000_scl_pin(void *data)
41 {
42 	return ((struct ixp2000_i2c_pins*)data)->scl_pin;
43 }
44 
ixp2000_sda_pin(void * data)45 static inline int ixp2000_sda_pin(void *data)
46 {
47 	return ((struct ixp2000_i2c_pins*)data)->sda_pin;
48 }
49 
50 
ixp2000_bit_setscl(void * data,int val)51 static void ixp2000_bit_setscl(void *data, int val)
52 {
53 	int i = 5000;
54 
55 	if (val) {
56 		gpio_line_config(ixp2000_scl_pin(data), GPIO_IN);
57 		while(!gpio_line_get(ixp2000_scl_pin(data)) && i--);
58 	} else {
59 		gpio_line_config(ixp2000_scl_pin(data), GPIO_OUT);
60 	}
61 }
62 
ixp2000_bit_setsda(void * data,int val)63 static void ixp2000_bit_setsda(void *data, int val)
64 {
65 	if (val) {
66 		gpio_line_config(ixp2000_sda_pin(data), GPIO_IN);
67 	} else {
68 		gpio_line_config(ixp2000_sda_pin(data), GPIO_OUT);
69 	}
70 }
71 
ixp2000_bit_getscl(void * data)72 static int ixp2000_bit_getscl(void *data)
73 {
74 	return gpio_line_get(ixp2000_scl_pin(data));
75 }
76 
ixp2000_bit_getsda(void * data)77 static int ixp2000_bit_getsda(void *data)
78 {
79 	return gpio_line_get(ixp2000_sda_pin(data));
80 }
81 
82 struct ixp2000_i2c_data {
83 	struct ixp2000_i2c_pins *gpio_pins;
84 	struct i2c_adapter adapter;
85 	struct i2c_algo_bit_data algo_data;
86 };
87 
ixp2000_i2c_remove(struct platform_device * plat_dev)88 static int ixp2000_i2c_remove(struct platform_device *plat_dev)
89 {
90 	struct ixp2000_i2c_data *drv_data = platform_get_drvdata(plat_dev);
91 
92 	platform_set_drvdata(plat_dev, NULL);
93 
94 	i2c_del_adapter(&drv_data->adapter);
95 
96 	kfree(drv_data);
97 
98 	return 0;
99 }
100 
ixp2000_i2c_probe(struct platform_device * plat_dev)101 static int ixp2000_i2c_probe(struct platform_device *plat_dev)
102 {
103 	int err;
104 	struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
105 	struct ixp2000_i2c_data *drv_data =
106 		kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
107 
108 	if (!drv_data)
109 		return -ENOMEM;
110 	drv_data->gpio_pins = gpio;
111 
112 	drv_data->algo_data.data = gpio;
113 	drv_data->algo_data.setsda = ixp2000_bit_setsda;
114 	drv_data->algo_data.setscl = ixp2000_bit_setscl;
115 	drv_data->algo_data.getsda = ixp2000_bit_getsda;
116 	drv_data->algo_data.getscl = ixp2000_bit_getscl;
117 	drv_data->algo_data.udelay = 6;
118 	drv_data->algo_data.timeout = HZ;
119 
120 	strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
121 		sizeof(drv_data->adapter.name));
122 	drv_data->adapter.algo_data = &drv_data->algo_data,
123 
124 	drv_data->adapter.dev.parent = &plat_dev->dev;
125 
126 	gpio_line_config(gpio->sda_pin, GPIO_IN);
127 	gpio_line_config(gpio->scl_pin, GPIO_IN);
128 	gpio_line_set(gpio->scl_pin, 0);
129 	gpio_line_set(gpio->sda_pin, 0);
130 
131 	if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) {
132 		dev_err(&plat_dev->dev, "Could not install, error %d\n", err);
133 		kfree(drv_data);
134 		return err;
135 	}
136 
137 	platform_set_drvdata(plat_dev, drv_data);
138 
139 	return 0;
140 }
141 
142 static struct platform_driver ixp2000_i2c_driver = {
143 	.probe		= ixp2000_i2c_probe,
144 	.remove		= ixp2000_i2c_remove,
145 	.driver		= {
146 		.name	= "IXP2000-I2C",
147 		.owner	= THIS_MODULE,
148 	},
149 };
150 
151 module_platform_driver(ixp2000_i2c_driver);
152 
153 MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>");
154 MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
155 MODULE_LICENSE("GPL");
156 MODULE_ALIAS("platform:IXP2000-I2C");
157 
158