⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menelaus.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
字号:
/* * drivers/i2c/chips/menelaus.c * * Copyright (C) 2004 Texas Instruments, Inc. * * Based on tlv320aic23.c: *   Copyright (c) by Kai Svahn <kai.svahn@nokia.com> * *   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, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/i2c.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/mach/irq.h>#include <asm/arch/mux.h>#include <asm/arch/menelaus.h>#include <asm/arch/sys_info.h>/* Local BCD/BIN conversion macros: */#ifdef BCD_TO_BIN#undef BCD_TO_BIN#endif#define BCD_TO_BIN(val)	((val)=((val)&15) + ((val)>>4)*10) #ifdef BIN_TO_BCD#undef BIN_TO_BCD#endif#define BIN_TO_BCD(val)	((val)=(((val)/10)<<4) + (val)%10)//#define MENELAUSID1		0xE4//#define MENELAUSID2		0xE5/* I2C Addresses to scan *///static unsigned short normal_i2c[] = { MENELAUSID1, MENELAUSID2, I2C_CLIENT_END };static unsigned short normal_i2c[] = { 0x72, I2C_CLIENT_END };static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };/* This makes all addr_data:s */I2C_CLIENT_INSMOD;static int menelaus_id = 0;static const int menelaus_irq = INT_SYS;static struct i2c_driver menelaus_driver; static struct i2c_client *client;s32 menelaus_write(u8 value, u8 reg){	return i2c_smbus_write_byte_data(client, reg, value);}s32 menelaus_read(u8 reg){	return i2c_smbus_read_byte_data(client, reg);}static void menelaus_mask_ack_irq(unsigned int irq){	unsigned int menelaus = irq - IH_MENELAUS_BASE;	if (menelaus > 7) {		/* INT_MASK2 */		menelaus_write(menelaus_read(MENELAUS_INT_MASK2) | (1<<(menelaus-8)), MENELAUS_INT_MASK2);		menelaus_write(1<<(menelaus-8), MENELAUS_INT_ACK2);	} else {		/* INT_MASK1 */		menelaus_write(menelaus_read(MENELAUS_INT_MASK1) | (1<<menelaus), MENELAUS_INT_MASK1);		menelaus_write(1<<menelaus, MENELAUS_INT_ACK1);	}}static void menelaus_mask_irq(unsigned int irq){	unsigned int menelaus = irq - IH_MENELAUS_BASE;	if (menelaus > 7) {		/* INT_MASK2 */		menelaus_write(menelaus_read(MENELAUS_INT_MASK2) | (1<<(menelaus-8)), MENELAUS_INT_MASK2);	} else {		/* INT_MASK1 */		menelaus_write(menelaus_read(MENELAUS_INT_MASK1) | (1<<menelaus), MENELAUS_INT_MASK1);	}}void menelaus_unmask_irq(unsigned int irq){	unsigned int menelaus = irq - IH_MENELAUS_BASE;	if (menelaus > 7) {		/* INT_MASK2 */		menelaus_write(menelaus_read(MENELAUS_INT_MASK2) & ~(1<<(menelaus-8)), MENELAUS_INT_MASK2);	} else {		/* INT_MASK1 */		menelaus_write(menelaus_read(MENELAUS_INT_MASK1) & ~(1<<menelaus), MENELAUS_INT_MASK1);	}}static struct irqchip menelaus_irq_chip = {	.ack = menelaus_mask_ack_irq,	.mask = menelaus_mask_irq,	.unmask = menelaus_unmask_irq,};struct menelaus_irq_info {	struct irqdesc *desc;	unsigned int irq;	struct work_struct *work;	struct pt_regs *regs;};static void menelaus_work(void *data){	struct menelaus_irq_info *i = (struct menelaus_irq_info *)data;	int menelaus;	s32 isr1 = menelaus_read(MENELAUS_INT_STATUS1);	s32 isr2 = menelaus_read(MENELAUS_INT_STATUS2);	for (menelaus = IH_MENELAUS_BASE; menelaus < IH_MENELAUS_BASE + 8; menelaus++) {		int m = menelaus - IH_MENELAUS_BASE;		if (isr1 & (1<<m)) {			struct irqdesc *d = irq_desc + menelaus;			d->handle(menelaus, d, i->regs);		}	}	for (menelaus = IH_MENELAUS_BASE + 8; menelaus < IH_MENELAUS_END; menelaus++) {		int m = menelaus - IH_MENELAUS_BASE - 8;		if (isr2 & (1<<m)) {			struct irqdesc *d = irq_desc + menelaus;			d->handle(menelaus, d, i->regs);		}	}		i->desc->chip->unmask(i->irq);	kfree(i->work);	kfree(i);	return;}static void do_menelaus_irq(unsigned int irq, struct irqdesc *desc,			   struct pt_regs *regs){	struct menelaus_irq_info *e;	struct work_struct *work;	desc->chip->ack(irq);	// ack mask parent pic	if (!(e = kmalloc(sizeof(struct menelaus_irq_info),				   GFP_KERNEL))) {		printk(KERN_CRIT "Couldn't allocate memory for irq (%d) to be run in keventd context\n", irq);		return;	}	if (!(work = kmalloc(sizeof(struct work_struct),				   GFP_KERNEL))) {		printk(KERN_CRIT "Couldn't allocate memory for irq (%d) to be run in keventd context\n", irq);		kfree(e);		return;	}	e->work = work;	e->irq = irq;	e->desc = desc;	e->regs = regs;	INIT_WORK(work, menelaus_work, e);	schedule_work(work);}static int menelaus_detect_client(struct i2c_adapter *adapter, int address, 				     int kind){	int err = 0, i;      	const char *client_name = "Menelaus";		if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA | 				     I2C_FUNC_SMBUS_WRITE_BYTE)) {		printk(KERN_WARNING "%s functinality check failed\n", client_name);		return err;	}		if (!(client = kmalloc(sizeof(struct i2c_client),				   GFP_KERNEL))) {		err = -ENOMEM;		printk(KERN_WARNING "Couldn't allocate memory for %s\n", client_name);		return err;	}		memset(client, 0x00, sizeof(struct i2c_client));	client->addr = address;	client->adapter = adapter;	client->driver = &menelaus_driver;	client->flags = 0;	strlcpy(client->name, client_name, I2C_NAME_SIZE);	client->id = menelaus_id++;	if (kind < 0)		if ((err = menelaus_read(MENELAUS_REV)) == -1)			goto fail1;       		if ((err = i2c_attach_client(client))) {	       	printk(KERN_WARNING "Couldn't attach %s\n", client_name);		goto fail1;	}	for (i = IH_MENELAUS_BASE; i < IH_MENELAUS_END; i++) {		set_irq_chip(i, &menelaus_irq_chip);		set_irq_handler(i, do_level_IRQ);		set_irq_flags(i, IRQF_VALID);	}	set_irq_chained_handler(menelaus_irq, do_menelaus_irq);	omap2_cfg_reg(W19_2420_SYS_NIRQ);	return 0;fail1:	kfree(client);	return err;}	static int menelaus_detach_client(struct i2c_client *client){	int err;	flush_scheduled_work();		if ((err = i2c_detach_client(client))) {		printk("menelaus.o: Client deregistration failed, client not detached.\n");		return err;	}		kfree(client);	return 0;}static int menelaus_attach_adapter(struct i2c_adapter *adapter){	if (!client)		return menelaus_detect_client(adapter, addr_data.normal_i2c[0], -1);	return -ENODEV;}/*-----------------------------------------------------------------------*/static struct i2c_driver menelaus_driver = {	.owner          = THIS_MODULE,         .name           = "Menelaus",        .id		= I2C_DRIVERID_EXP0,           /* Experimental ID */        .flags		= I2C_DF_NOTIFY,        .attach_adapter	= menelaus_attach_adapter,        .detach_client	= menelaus_detach_client,};static int __init menelaus_init(void){	int res;	struct i2c_client *client = client;	u32 board = get_board_type();		if(board == BOARD_H4_MENELAUS){		if ((res = i2c_add_driver(&menelaus_driver))) {			printk("menelaus i2c: Driver registration failed, module not inserted.\n");			return res;		}	}else		return -ENODEV;	return 0;}static void __exit menelaus_exit(void){	int res; 	u32 board = get_board_type();	if(board == BOARD_H4_MENELAUS){		if ((res = i2c_del_driver(&menelaus_driver))) 			printk("menelaus i2c: Driver remove failed, module not removed.\n");	}}MODULE_AUTHOR("Texas Instruments, Inc.");MODULE_DESCRIPTION("I2C interface for Menelaus.");MODULE_LICENSE("GPL");module_init(menelaus_init)module_exit(menelaus_exit)EXPORT_SYMBOL(menelaus_write);EXPORT_SYMBOL(menelaus_read);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -