123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /*
- * Support for the Extra GPIOs on the Sharp SL-C1000 (Akita)
- * (uses a Maxim MAX7310 8 Port IO Expander)
- *
- * Copyright 2005 Openedhand Ltd.
- *
- * Author: Richard Purdie <richard@openedhand.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/platform_device.h>
- #include <linux/module.h>
- #include <linux/i2c.h>
- #include <linux/slab.h>
- #include <linux/workqueue.h>
- #include <asm/arch/akita.h>
- /* MAX7310 Regiser Map */
- #define MAX7310_INPUT 0x00
- #define MAX7310_OUTPUT 0x01
- #define MAX7310_POLINV 0x02
- #define MAX7310_IODIR 0x03 /* 1 = Input, 0 = Output */
- #define MAX7310_TIMEOUT 0x04
- /* Addresses to scan */
- static unsigned short normal_i2c[] = { 0x18, I2C_CLIENT_END };
- /* I2C Magic */
- I2C_CLIENT_INSMOD;
- static int max7310_write(struct i2c_client *client, int address, int data);
- static struct i2c_client max7310_template;
- static void akita_ioexp_work(struct work_struct *private_);
- static struct device *akita_ioexp_device;
- static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT;
- DECLARE_WORK(akita_ioexp, akita_ioexp_work);
- /*
- * MAX7310 Access
- */
- static int max7310_config(struct device *dev, int iomode, int polarity)
- {
- int ret;
- struct i2c_client *client = to_i2c_client(dev);
- ret = max7310_write(client, MAX7310_POLINV, polarity);
- if (ret < 0)
- return ret;
- ret = max7310_write(client, MAX7310_IODIR, iomode);
- return ret;
- }
- static int max7310_set_ouputs(struct device *dev, int outputs)
- {
- struct i2c_client *client = to_i2c_client(dev);
- return max7310_write(client, MAX7310_OUTPUT, outputs);
- }
- /*
- * I2C Functions
- */
- static int max7310_write(struct i2c_client *client, int address, int value)
- {
- u8 data[2];
- data[0] = address & 0xff;
- data[1] = value & 0xff;
- if (i2c_master_send(client, data, 2) == 2)
- return 0;
- return -1;
- }
- static int max7310_detect(struct i2c_adapter *adapter, int address, int kind)
- {
- struct i2c_client *new_client;
- int err;
- if (!(new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
- return -ENOMEM;
- max7310_template.adapter = adapter;
- max7310_template.addr = address;
- memcpy(new_client, &max7310_template, sizeof(struct i2c_client));
- if ((err = i2c_attach_client(new_client))) {
- kfree(new_client);
- return err;
- }
- max7310_config(&new_client->dev, AKITA_IOEXP_IO_DIR, 0);
- akita_ioexp_device = &new_client->dev;
- schedule_work(&akita_ioexp);
- return 0;
- }
- static int max7310_attach_adapter(struct i2c_adapter *adapter)
- {
- return i2c_probe(adapter, &addr_data, max7310_detect);
- }
- static int max7310_detach_client(struct i2c_client *client)
- {
- int err;
- akita_ioexp_device = NULL;
- if ((err = i2c_detach_client(client)))
- return err;
- kfree(client);
- return 0;
- }
- static struct i2c_driver max7310_i2c_driver = {
- .driver = {
- .name = "akita-max7310",
- },
- .id = I2C_DRIVERID_AKITAIOEXP,
- .attach_adapter = max7310_attach_adapter,
- .detach_client = max7310_detach_client,
- };
- static struct i2c_client max7310_template = {
- name: "akita-max7310",
- driver: &max7310_i2c_driver,
- };
- void akita_set_ioexp(struct device *dev, unsigned char bit)
- {
- ioexp_output_value |= bit;
- if (akita_ioexp_device)
- schedule_work(&akita_ioexp);
- return;
- }
- void akita_reset_ioexp(struct device *dev, unsigned char bit)
- {
- ioexp_output_value &= ~bit;
- if (akita_ioexp_device)
- schedule_work(&akita_ioexp);
- return;
- }
- EXPORT_SYMBOL(akita_set_ioexp);
- EXPORT_SYMBOL(akita_reset_ioexp);
- static void akita_ioexp_work(struct work_struct *private_)
- {
- if (akita_ioexp_device)
- max7310_set_ouputs(akita_ioexp_device, ioexp_output_value);
- }
- #ifdef CONFIG_PM
- static int akita_ioexp_suspend(struct platform_device *pdev, pm_message_t state)
- {
- flush_scheduled_work();
- return 0;
- }
- static int akita_ioexp_resume(struct platform_device *pdev)
- {
- schedule_work(&akita_ioexp);
- return 0;
- }
- #else
- #define akita_ioexp_suspend NULL
- #define akita_ioexp_resume NULL
- #endif
- static int __init akita_ioexp_probe(struct platform_device *pdev)
- {
- return i2c_add_driver(&max7310_i2c_driver);
- }
- static int akita_ioexp_remove(struct platform_device *pdev)
- {
- i2c_del_driver(&max7310_i2c_driver);
- return 0;
- }
- static struct platform_driver akita_ioexp_driver = {
- .probe = akita_ioexp_probe,
- .remove = akita_ioexp_remove,
- .suspend = akita_ioexp_suspend,
- .resume = akita_ioexp_resume,
- .driver = {
- .name = "akita-ioexp",
- },
- };
- static int __init akita_ioexp_init(void)
- {
- return platform_driver_register(&akita_ioexp_driver);
- }
- static void __exit akita_ioexp_exit(void)
- {
- platform_driver_unregister(&akita_ioexp_driver);
- }
- MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
- MODULE_DESCRIPTION("Akita IO-Expander driver");
- MODULE_LICENSE("GPL");
- fs_initcall(akita_ioexp_init);
- module_exit(akita_ioexp_exit);
|