Path: blob/master/drivers/i2c/busses/i2c-ixp2000.c
15111 views
/*1* drivers/i2c/busses/i2c-ixp2000.c2*3* I2C adapter for IXP2000 systems using GPIOs for I2C bus4*5* Author: Deepak Saxena <[email protected]>6* Based on IXDP2400 code by: Naeem M. Afzal <[email protected]>7* Made generic by: Jeff Daly <[email protected]>8*9* Copyright (c) 2003-2004 MontaVista Software Inc.10*11* This file is licensed under the terms of the GNU General Public12* License version 2. This program is licensed "as is" without any13* warranty of any kind, whether express or implied.14*15* From Jeff Daly:16*17* I2C adapter driver for Intel IXDP2xxx platforms. This should work for any18* IXP2000 platform if it uses the HW GPIO in the same manner. Basically,19* SDA and SCL GPIOs have external pullups. Setting the respective GPIO to20* an input will make the signal a '1' via the pullup. Setting them to21* outputs will pull them down.22*23* The GPIOs are open drain signals and are used as configuration strap inputs24* during power-up so there's generally a buffer on the board that needs to be25* 'enabled' to drive the GPIOs.26*/2728#include <linux/kernel.h>29#include <linux/init.h>30#include <linux/platform_device.h>31#include <linux/module.h>32#include <linux/i2c.h>33#include <linux/i2c-algo-bit.h>34#include <linux/slab.h>3536#include <mach/hardware.h> /* Pick up IXP2000-specific bits */37#include <mach/gpio.h>3839static inline int ixp2000_scl_pin(void *data)40{41return ((struct ixp2000_i2c_pins*)data)->scl_pin;42}4344static inline int ixp2000_sda_pin(void *data)45{46return ((struct ixp2000_i2c_pins*)data)->sda_pin;47}484950static void ixp2000_bit_setscl(void *data, int val)51{52int i = 5000;5354if (val) {55gpio_line_config(ixp2000_scl_pin(data), GPIO_IN);56while(!gpio_line_get(ixp2000_scl_pin(data)) && i--);57} else {58gpio_line_config(ixp2000_scl_pin(data), GPIO_OUT);59}60}6162static void ixp2000_bit_setsda(void *data, int val)63{64if (val) {65gpio_line_config(ixp2000_sda_pin(data), GPIO_IN);66} else {67gpio_line_config(ixp2000_sda_pin(data), GPIO_OUT);68}69}7071static int ixp2000_bit_getscl(void *data)72{73return gpio_line_get(ixp2000_scl_pin(data));74}7576static int ixp2000_bit_getsda(void *data)77{78return gpio_line_get(ixp2000_sda_pin(data));79}8081struct ixp2000_i2c_data {82struct ixp2000_i2c_pins *gpio_pins;83struct i2c_adapter adapter;84struct i2c_algo_bit_data algo_data;85};8687static int ixp2000_i2c_remove(struct platform_device *plat_dev)88{89struct ixp2000_i2c_data *drv_data = platform_get_drvdata(plat_dev);9091platform_set_drvdata(plat_dev, NULL);9293i2c_del_adapter(&drv_data->adapter);9495kfree(drv_data);9697return 0;98}99100static int ixp2000_i2c_probe(struct platform_device *plat_dev)101{102int err;103struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;104struct ixp2000_i2c_data *drv_data =105kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);106107if (!drv_data)108return -ENOMEM;109drv_data->gpio_pins = gpio;110111drv_data->algo_data.data = gpio;112drv_data->algo_data.setsda = ixp2000_bit_setsda;113drv_data->algo_data.setscl = ixp2000_bit_setscl;114drv_data->algo_data.getsda = ixp2000_bit_getsda;115drv_data->algo_data.getscl = ixp2000_bit_getscl;116drv_data->algo_data.udelay = 6;117drv_data->algo_data.timeout = HZ;118119strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,120sizeof(drv_data->adapter.name));121drv_data->adapter.algo_data = &drv_data->algo_data,122123drv_data->adapter.dev.parent = &plat_dev->dev;124125gpio_line_config(gpio->sda_pin, GPIO_IN);126gpio_line_config(gpio->scl_pin, GPIO_IN);127gpio_line_set(gpio->scl_pin, 0);128gpio_line_set(gpio->sda_pin, 0);129130if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) {131dev_err(&plat_dev->dev, "Could not install, error %d\n", err);132kfree(drv_data);133return err;134}135136platform_set_drvdata(plat_dev, drv_data);137138return 0;139}140141static struct platform_driver ixp2000_i2c_driver = {142.probe = ixp2000_i2c_probe,143.remove = ixp2000_i2c_remove,144.driver = {145.name = "IXP2000-I2C",146.owner = THIS_MODULE,147},148};149150static int __init ixp2000_i2c_init(void)151{152return platform_driver_register(&ixp2000_i2c_driver);153}154155static void __exit ixp2000_i2c_exit(void)156{157platform_driver_unregister(&ixp2000_i2c_driver);158}159160module_init(ixp2000_i2c_init);161module_exit(ixp2000_i2c_exit);162163MODULE_AUTHOR ("Deepak Saxena <[email protected]>");164MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");165MODULE_LICENSE("GPL");166MODULE_ALIAS("platform:IXP2000-I2C");167168169170