Creation of Cybook 2416 (actually Gen4) repository

This commit is contained in:
mlt
2009-12-18 17:10:00 +00:00
committed by godzil
commit 76f20f4d40
13791 changed files with 6812321 additions and 0 deletions

28
drivers/l3/Kconfig Normal file
View File

@@ -0,0 +1,28 @@
#
# L3 bus configuration
#
menu "L3 support"
config L3
tristate "L3 support"
config L3_ALGOBIT
boolean "L3 bit-banging interfaces"
depends on L3
config L3_BIT_SA1100_GPIO
boolean "SA11x0 GPIO adapter"
depends on L3_ALGOBIT && ARCH_SA1100
# i2c must come before this
config BIT_SA1100_GPIO
boolean
depends on L3_BIT_SA1100_GPIO || I2C_BIT_SA1100_GPIO=y
default y
config L3_BIT_S3C_GPIO
boolean "S3C GPIO adapter"
depends on L3_ALGOBIT && ARCH_S3C2410
endmenu

9
drivers/l3/Makefile Normal file
View File

@@ -0,0 +1,9 @@
#
# Makefile for the L3 bus driver.
# Link order:
# (core, adapters, algorithms, drivers) then clients
l3-$(CONFIG_L3_ALGOBIT) += l3-algo-bit.o
l3-$(CONFIG_BIT_SA1100_GPIO) += l3-bit-sa1100.o
l3-$(CONFIG_L3_BIT_S3C_GPIO) += l3-bit-s3c.o
obj-$(CONFIG_L3) += l3-core.o $(l3-y) $(l3-drv-y)

175
drivers/l3/l3-algo-bit.c Normal file
View File

@@ -0,0 +1,175 @@
/*
* L3 bus algorithm module.
*
* Copyright (C) 2001 Russell King, All Rights Reserved.
*
* 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.
*
* Note that L3 buses can share the same pins as I2C buses, so we must
* _not_ generate an I2C start condition. An I2C start condition is
* defined as a high-to-low transition of the data line while the clock
* is high. Therefore, we must only change the data line while the
* clock is low.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/l3/l3.h>
#include <linux/l3/algo-bit.h>
#define setdat(adap,val) adap->setdat(adap->data, val)
#define setclk(adap,val) adap->setclk(adap->data, val)
#define setmode(adap,val) adap->setmode(adap->data, val)
#define setdatin(adap) adap->setdir(adap->data, 1)
#define setdatout(adap) adap->setdir(adap->data, 0)
#define getdat(adap) adap->getdat(adap->data)
/*
* Send one byte of data to the chip. Data is latched into the chip on
* the rising edge of the clock.
*/
static void sendbyte(struct l3_algo_bit_data *adap, unsigned int byte)
{
int i;
for (i = 0; i < 8; i++) {
setclk(adap, 0);
udelay(adap->data_hold);
setdat(adap, byte & 1);
udelay(adap->data_setup);
setclk(adap, 1);
udelay(adap->clock_high);
byte >>= 1;
}
}
/*
* Send a set of bytes to the chip. We need to pulse the MODE line
* between each byte, but never at the start nor at the end of the
* transfer.
*/
static void sendbytes(struct l3_algo_bit_data *adap, const char *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
if (i) {
udelay(adap->mode_hold);
setmode(adap, 0);
udelay(adap->mode);
}
setmode(adap, 1);
udelay(adap->mode_setup);
sendbyte(adap, buf[i]);
}
}
/*
* Read one byte of data from the chip. Data is latched into the chip on
* the rising edge of the clock.
*/
static unsigned int readbyte(struct l3_algo_bit_data *adap)
{
unsigned int byte = 0;
int i;
for (i = 0; i < 8; i++) {
setclk(adap, 0);
udelay(adap->data_hold + adap->data_setup);
setclk(adap, 1);
if (getdat(adap))
byte |= 1 << i;
udelay(adap->clock_high);
}
return byte;
}
/*
* Read a set of bytes from the chip. We need to pulse the MODE line
* between each byte, but never at the start nor at the end of the
* transfer.
*/
static void readbytes(struct l3_algo_bit_data *adap, char *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
if (i) {
udelay(adap->mode_hold);
setmode(adap, 0);
}
setmode(adap, 1);
udelay(adap->mode_setup);
buf[i] = readbyte(adap);
}
}
static int l3_xfer(struct l3_adapter *l3_adap, struct l3_msg msgs[], int num)
{
struct l3_algo_bit_data *adap = l3_adap->algo_data;
int i;
/*
* If we share an I2C bus, ensure that it is in STOP mode
*/
setclk(adap, 1);
setdat(adap, 1);
setmode(adap, 1);
setdatout(adap);
udelay(adap->mode);
for (i = 0; i < num; i++) {
struct l3_msg *pmsg = &msgs[i];
if (!(pmsg->flags & L3_M_NOADDR)) {
setmode(adap, 0);
udelay(adap->mode_setup);
sendbyte(adap, pmsg->addr);
udelay(adap->mode_hold);
}
if (pmsg->flags & L3_M_RD) {
setdatin(adap);
readbytes(adap, pmsg->buf, pmsg->len);
} else {
setdatout(adap);
sendbytes(adap, pmsg->buf, pmsg->len);
}
}
/*
* Ensure that we leave the bus in I2C stop mode.
*/
setclk(adap, 1);
setdat(adap, 1);
setmode(adap, 0);
setdatin(adap);
return num;
}
static struct l3_algorithm l3_bit_algo = {
name: "L3 bit-shift algorithm",
xfer: l3_xfer,
};
int l3_bit_add_bus(struct l3_adapter *adap)
{
adap->algo = &l3_bit_algo;
return l3_add_adapter(adap);
}
int l3_bit_del_bus(struct l3_adapter *adap)
{
return l3_del_adapter(adap);
}
EXPORT_SYMBOL(l3_bit_add_bus);
EXPORT_SYMBOL(l3_bit_del_bus);

213
drivers/l3/l3-bit-s3c.c Normal file
View File

@@ -0,0 +1,213 @@
/*
* linux/drivers/l3/l3-bit-sa1100.c
*
* Copyright (C) 2001 Russell King
*
* 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.
*
* This is a combined I2C and L3 bus driver.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/l3/algo-bit.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/regs-gpio.h>
#define NAME "l3-bit-s3c-gpio"
struct bit_data {
unsigned int sda;
unsigned int scl;
unsigned int l3_mode;
};
static int getsda(void *data)
{
struct bit_data *bits = data;
return s3c2410_gpio_getpin(bits->sda);
}
static DECLARE_MUTEX(l3_lock);
#define LOCK &l3_lock
/*
* iPAQs need the clock line driven hard high and low.
*/
static void l3_setscl(void *data, int state)
{
struct bit_data *bits = data;
unsigned long flags;
local_irq_save(flags);
if (state)
s3c2410_gpio_setpin(bits->scl, 1);
else
s3c2410_gpio_setpin(bits->scl, 0);
#if defined CONFIG_MACH_SMDK2443
s3c2410_gpio_cfgpin(bits->scl, S3C2410_GPG2_OUTP);
#elif defined CONFIG_MACH_SMDK2412
s3c2410_gpio_cfgpin(bits->scl, S3C_GPB4_OUTP);
#endif
local_irq_restore(flags);
}
static void l3_setsda(void *data, int state)
{
struct bit_data *bits = data;
if (state)
s3c2410_gpio_setpin(bits->sda, 1);
else
s3c2410_gpio_setpin(bits->sda, 0);
}
static void l3_setdir(void *data, int in)
{
struct bit_data *bits = data;
unsigned long flags;
local_irq_save(flags);
#if defined CONFIG_MACH_SMDK2443
#if 0 //ryu
if (in)
s3c2410_gpio_cfgpin(bits->sda, S3C_GPG1_INP);
else
#endif
s3c2410_gpio_cfgpin(bits->sda, S3C2410_GPG1_OUTP);
#elif defined CONFIG_MACH_SMDK2412
if (in)
s3c2410_gpio_cfgpin(bits->sda, S3C_GPB3_INP);
else
s3c2410_gpio_cfgpin(bits->sda, S3C_GPB3_OUTP);
#endif
local_irq_restore(flags);
}
static void l3_setmode(void *data, int state)
{
struct bit_data *bits = data;
if (state)
s3c2410_gpio_setpin(bits->l3_mode, 1);
else
s3c2410_gpio_setpin(bits->l3_mode, 0);
}
static struct l3_algo_bit_data l3_bit_data = {
.data = NULL,
.setdat = l3_setsda,
.setclk = l3_setscl,
.setmode = l3_setmode,
.setdir = l3_setdir,
.getdat = getsda,
.data_hold = 1,
.data_setup = 1,
.clock_high = 1,
.mode_hold = 1,
.mode_setup = 1,
};
static struct l3_adapter l3_adapter_s3c= {
.owner = THIS_MODULE,
.name = NAME,
.algo_data = &l3_bit_data,
.lock = LOCK,
};
static int __init l3_init(struct bit_data *bits)
{
l3_bit_data.data = bits;
return l3_bit_add_bus(&l3_adapter_s3c);
}
static void l3_exit(void)
{
l3_bit_del_bus(&l3_adapter_s3c);
}
static struct bit_data bit_data;
static int __init bus_init(void)
{
struct bit_data *bit = &bit_data;
unsigned long flags;
int ret;
#if defined CONFIG_MACH_SMDK2443
bit->sda = S3C2410_GPG1;
bit->scl = S3C2410_GPG2;
bit->l3_mode = S3C2410_GPG0;
#elif defined CONFIG_MACH_SMDK2412
bit->sda = S3C_GPB3;
bit->scl = S3C_GPB4;
bit->l3_mode = S3C_GPB2;
#endif
if (!bit->sda)
return -ENODEV;
/*
* Default level for L3 mode is low.
*/
local_irq_save(flags);
s3c2410_gpio_setpin(bit->l3_mode, 1);
s3c2410_gpio_setpin(bit->scl, 1);
s3c2410_gpio_setpin(bit->sda, 0);
#if defined CONFIG_MACH_SMDK2443
s3c2410_gpio_cfgpin(bit->l3_mode, S3C2410_GPG0_OUTP);
s3c2410_gpio_cfgpin(bit->sda, S3C2410_GPG1_OUTP);
s3c2410_gpio_cfgpin(bit->scl, S3C2410_GPG2_OUTP);
#elif defined CONFIG_MACH_SMDK2412
s3c2410_gpio_cfgpin(bit->l3_mode, S3C_GPB2_OUTP);
s3c2410_gpio_cfgpin(bit->sda, S3C_GPB3_OUTP);
s3c2410_gpio_cfgpin(bit->scl, S3C_GPB4_OUTP);
#endif
/* L3 gpio interface set */
local_irq_restore(flags);
ret = l3_init(bit);
if (ret)
{
printk("l3 init failed \n");
l3_exit();
}
printk("GPIO L3 bus interface for s3c, installed\n");
return ret;
}
static void __exit bus_exit(void)
{
l3_exit();
}
module_init(bus_init);
module_exit(bus_exit);

203
drivers/l3/l3-core.c Normal file
View File

@@ -0,0 +1,203 @@
/*
* linux/drivers/l3/l3-core.c
*
* Copyright (C) 2001 Russell King
*
* General structure taken from i2c-core.c by Simon G. Vogl
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* See linux/Documentation/l3 for further documentation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/l3/l3.h>
static DECLARE_MUTEX(adapter_lock);
static LIST_HEAD(adapter_list);
static DECLARE_MUTEX(driver_lock);
static LIST_HEAD(driver_list);
/**
* l3_add_adapter - register a new L3 bus adapter
* @adap: l3_adapter structure for the registering adapter
*
* Make the adapter available for use by clients using name adap->name.
* The adap->adapters list is initialised by this function.
*
* Returns 0;
*/
int l3_add_adapter(struct l3_adapter *adap)
{
down(&adapter_lock);
list_add(&adap->adapters, &adapter_list);
up(&adapter_lock);
return 0;
}
/**
* l3_del_adapter - unregister a L3 bus adapter
* @adap: l3_adapter structure to unregister
*
* Remove an adapter from the list of available L3 Bus adapters.
*
* Returns 0;
*/
int l3_del_adapter(struct l3_adapter *adap)
{
down(&adapter_lock);
list_del(&adap->adapters);
up(&adapter_lock);
return 0;
}
static struct l3_adapter *__l3_get_adapter(const char *name)
{
struct list_head *l;
list_for_each(l, &adapter_list) {
struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters);
if (strcmp(adap->name, name) == 0)
return adap;
}
return NULL;
}
/**
* l3_get_adapter - get a reference to an adapter
* @name: driver name
*
* Obtain a l3_adapter structure for the specified adapter. If the adapter
* is not currently load, then load it. The adapter will be locked in core
* until all references are released via l3_put_adapter.
*/
struct l3_adapter *l3_get_adapter(const char *name)
{
struct l3_adapter *adap;
int try;
for (try = 0; try < 2; try ++) {
down(&adapter_lock);
adap = __l3_get_adapter(name);
if (adap && !try_module_get(adap->owner))
adap = NULL;
up(&adapter_lock);
if (adap)
break;
if (try == 0)
request_module(name);
}
return adap;
}
/**
* l3_put_adapter - release a reference to an adapter
* @adap: driver to release reference
*
* Indicate to the L3 core that you no longer require the adapter reference.
* The adapter module may be unloaded when there are no references to its
* data structure.
*
* You must not use the reference after calling this function.
*/
void l3_put_adapter(struct l3_adapter *adap)
{
if (adap && adap->owner)
module_put(adap->owner);
}
/**
* l3_transfer - transfer information on an L3 bus
* @adap: adapter structure to perform transfer on
* @msgs: array of l3_msg structures describing transfer
* @num: number of l3_msg structures
*
* Transfer the specified messages to/from a device on the L3 bus.
*
* Returns number of messages successfully transferred, otherwise negative
* error code.
*/
int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
{
int ret = -ENOSYS;
if (adap->algo->xfer) {
down(adap->lock);
ret = adap->algo->xfer(adap, msgs, num);
up(adap->lock);
}
return ret;
}
/**
* l3_write - send data to a device on an L3 bus
* @adap: L3 bus adapter
* @addr: L3 bus address
* @buf: buffer for bytes to send
* @len: number of bytes to send
*
* Send len bytes pointed to by buf to device address addr on the L3 bus
* described by client.
*
* Returns the number of bytes transferred, or negative error code.
*/
int l3_write(struct l3_adapter *adap, int addr, const char *buf, int len)
{
struct l3_msg msg;
int ret;
msg.addr = addr;
msg.flags = 0;
msg.buf = (char *)buf;
msg.len = len;
ret = l3_transfer(adap, &msg, 1);
return ret == 1 ? len : ret;
}
/**
* l3_read - receive data from a device on an L3 bus
* @adap: L3 bus adapter
* @addr: L3 bus address
* @buf: buffer for bytes to receive
* @len: number of bytes to receive
*
* Receive len bytes from device address addr on the L3 bus described by
* client to a buffer pointed to by buf.
*
* Returns the number of bytes transferred, or negative error code.
*/
int l3_read(struct l3_adapter *adap, int addr, char *buf, int len)
{
struct l3_msg msg;
int ret;
msg.addr = addr;
msg.flags = L3_M_RD;
msg.buf = buf;
msg.len = len;
ret = l3_transfer(adap, &msg, 1);
return ret == 1 ? len : ret;
}
EXPORT_SYMBOL(l3_add_adapter);
EXPORT_SYMBOL(l3_del_adapter);
EXPORT_SYMBOL(l3_get_adapter);
EXPORT_SYMBOL(l3_put_adapter);
EXPORT_SYMBOL(l3_transfer);
EXPORT_SYMBOL(l3_write);
EXPORT_SYMBOL(l3_read);