Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 14144
b: refs/heads/master
c: bd5d080
h: refs/heads/master
v: v3
  • Loading branch information
Richard Purdie authored and Russell King committed Nov 13, 2005
1 parent 734aec8 commit 212e82a
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e8b6f7f437a624fc2e2a2ec92fbeffdcf6f0e11e
refs/heads/master: bd5d080ab99642e3245ef7cfa54490384c01d878
1 change: 1 addition & 0 deletions trunk/arch/arm/mach-pxa/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o
obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o
obj-$(CONFIG_MACH_POODLE) += poodle.o
obj-$(CONFIG_MACH_TOSA) += tosa.o

Expand Down
223 changes: 223 additions & 0 deletions trunk/arch/arm/mach-pxa/akita-ioexp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
/*
* 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(void *private_);

static struct device *akita_ioexp_device;
static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT;
DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL);


/*
* 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 = {
.owner = THIS_MODULE,
.name = "akita-max7310",
.id = I2C_DRIVERID_AKITAIOEXP,
.flags = I2C_DF_NOTIFY,
.attach_adapter = max7310_attach_adapter,
.detach_client = max7310_detach_client,
};

static struct i2c_client max7310_template = {
name: "akita-max7310",
flags: I2C_CLIENT_ALLOW_USE,
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(void *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);

1 change: 1 addition & 0 deletions trunk/include/linux/i2c-id.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
#define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */
#define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */
#define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */
#define I2C_DRIVERID_AKITAIOEXP 74 /* IO Expander on Sharp SL-C1000 */

#define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
#define I2C_DRIVERID_EXP1 0xF1
Expand Down

0 comments on commit 212e82a

Please sign in to comment.