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

📄 io_interface_mux.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* IO interface mux allocator for ETRAX100LX. * Copyright 2004, Axis Communications AB * $Id: io_interface_mux.c,v 1.2 2004/12/21 12:08:38 starvik Exp $ *//* C.f. ETRAX100LX Designer's Reference 20.9 */#include <linux/kernel.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/init.h>#include <asm/arch/svinto.h>#include <asm/io.h>#include <asm/arch/io_interface_mux.h>#define DBG(s)/* Macro to access ETRAX 100 registers */#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \					  IO_STATE_(reg##_, field##_, _##val)enum io_if_group {	group_a = (1<<0),	group_b = (1<<1),	group_c = (1<<2),	group_d = (1<<3),	group_e = (1<<4),	group_f = (1<<5)};struct watcher{	void (*notify)(const unsigned int gpio_in_available,		       const unsigned int gpio_out_available,		       const unsigned char pa_available,		       const unsigned char pb_available);	struct watcher *next;};struct if_group{	enum io_if_group        group;	unsigned char           used;	enum cris_io_interface  owner;};struct interface{	enum cris_io_interface   ioif;	unsigned char            groups;	unsigned char            used;	char                    *owner;	unsigned int             gpio_g_in;	unsigned int             gpio_g_out;	unsigned char            gpio_b;};static struct if_group if_groups[6] = {	{		.group = group_a,		.used = 0,	},	{		.group = group_b,		.used = 0,	},	{		.group = group_c,		.used = 0,	},	{		.group = group_d,		.used = 0,	},	{		.group = group_e,		.used = 0,	},	{		.group = group_f,		.used = 0,	}};/* The order in the array must match the order of enum * cris_io_interface in io_interface_mux.h */static struct interface interfaces[] = {	/* Begin Non-multiplexed interfaces */	{		.ioif = if_eth,		.groups = 0,		.gpio_g_in = 0,		.gpio_g_out = 0,		.gpio_b = 0	},	{		.ioif = if_serial_0,		.groups = 0,		.gpio_g_in = 0,		.gpio_g_out = 0,		.gpio_b = 0	},	/* End Non-multiplexed interfaces */	{		.ioif = if_serial_1,		.groups = group_e,		.gpio_g_in =  0x00000000,		.gpio_g_out = 0x00000000,		.gpio_b = 0x00	},	{		.ioif = if_serial_2,		.groups = group_b,		.gpio_g_in =  0x000000c0,		.gpio_g_out = 0x000000c0,		.gpio_b = 0x00	},	{		.ioif = if_serial_3,		.groups = group_c,		.gpio_g_in =  0xc0000000,		.gpio_g_out = 0xc0000000,		.gpio_b = 0x00	},	{		.ioif = if_sync_serial_1,		.groups = group_e | group_f, /* if_sync_serial_1 and if_sync_serial_3					       can be used simultaneously */		.gpio_g_in =  0x00000000,		.gpio_g_out = 0x00000000,		.gpio_b = 0x10	},	{		.ioif = if_sync_serial_3,		.groups = group_c | group_f,		.gpio_g_in =  0xc0000000,		.gpio_g_out = 0xc0000000,		.gpio_b = 0x80	},	{		.ioif = if_shared_ram,		.groups = group_a,		.gpio_g_in =  0x0000ff3e,		.gpio_g_out = 0x0000ff38,		.gpio_b = 0x00	},	{		.ioif = if_shared_ram_w,		.groups = group_a | group_d,		.gpio_g_in =  0x00ffff3e,		.gpio_g_out = 0x00ffff38,		.gpio_b = 0x00	},	{		.ioif = if_par_0,		.groups = group_a,		.gpio_g_in =  0x0000ff3e,		.gpio_g_out = 0x0000ff3e,		.gpio_b = 0x00	},	{		.ioif = if_par_1,		.groups = group_d,		.gpio_g_in =  0x3eff0000,		.gpio_g_out = 0x3eff0000,		.gpio_b = 0x00	},	{		.ioif = if_par_w,		.groups = group_a | group_d,		.gpio_g_in =  0x00ffff3e,		.gpio_g_out = 0x00ffff3e,		.gpio_b = 0x00	},	{		.ioif = if_scsi8_0,		.groups = group_a | group_b | group_f, /* if_scsi8_0 and if_scsi8_1							  can be used simultaneously */		.gpio_g_in =  0x0000ffff,		.gpio_g_out = 0x0000ffff,		.gpio_b = 0x10	},	{		.ioif = if_scsi8_1,		.groups = group_c | group_d | group_f, /* if_scsi8_0 and if_scsi8_1							  can be used simultaneously */		.gpio_g_in =  0xffff0000,		.gpio_g_out = 0xffff0000,		.gpio_b = 0x80	},	{		.ioif = if_scsi_w,		.groups = group_a | group_b | group_d | group_f,		.gpio_g_in =  0x01ffffff,		.gpio_g_out = 0x07ffffff,		.gpio_b = 0x80	},	{		.ioif = if_ata,		.groups = group_a | group_b | group_c | group_d,		.gpio_g_in =  0xf9ffffff,		.gpio_g_out = 0xffffffff,		.gpio_b = 0x80	},	{		.ioif = if_csp,		.groups = group_f, /* if_csp and if_i2c can be used simultaneously */		.gpio_g_in =  0x00000000,		.gpio_g_out = 0x00000000,		.gpio_b = 0xfc	},	{		.ioif = if_i2c,		.groups = group_f, /* if_csp and if_i2c can be used simultaneously */		.gpio_g_in =  0x00000000,		.gpio_g_out = 0x00000000,		.gpio_b = 0x03	},	{		.ioif = if_usb_1,		.groups = group_e | group_f,		.gpio_g_in =  0x00000000,		.gpio_g_out = 0x00000000,		.gpio_b = 0x2c	},	{		.ioif = if_usb_2,		.groups = group_d,		.gpio_g_in =  0x0e000000,		.gpio_g_out = 0x3c000000,		.gpio_b = 0x00	},	/* GPIO pins */	{		.ioif = if_gpio_grp_a,		.groups = group_a,		.gpio_g_in =  0x0000ff3f,		.gpio_g_out = 0x0000ff3f,		.gpio_b = 0x00	},	{		.ioif = if_gpio_grp_b,		.groups = group_b,		.gpio_g_in =  0x000000c0,		.gpio_g_out = 0x000000c0,		.gpio_b = 0x00	},	{		.ioif = if_gpio_grp_c,		.groups = group_c,		.gpio_g_in =  0xc0000000,		.gpio_g_out = 0xc0000000,		.gpio_b = 0x00	},	{		.ioif = if_gpio_grp_d,		.groups = group_d,		.gpio_g_in =  0x3fff0000,		.gpio_g_out = 0x3fff0000,		.gpio_b = 0x00	},	{		.ioif = if_gpio_grp_e,		.groups = group_e,		.gpio_g_in =  0x00000000,		.gpio_g_out = 0x00000000,		.gpio_b = 0x00	},	{		.ioif = if_gpio_grp_f,		.groups = group_f,		.gpio_g_in =  0x00000000,		.gpio_g_out = 0x00000000,		.gpio_b = 0xff	}	/* Array end */};static struct watcher *watchers = NULL;static unsigned int gpio_in_pins =  0xffffffff;static unsigned int gpio_out_pins = 0xffffffff;static unsigned char gpio_pb_pins = 0xff;static unsigned char gpio_pa_pins = 0xff;static enum cris_io_interface gpio_pa_owners[8];static enum cris_io_interface gpio_pb_owners[8];static enum cris_io_interface gpio_pg_owners[32];static int cris_io_interface_init(void);static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group){	return (groups & ~group->group);}static struct if_group *get_group(const unsigned char groups){	int i;	for (i = 0; i < ARRAY_SIZE(if_groups); i++) {		if (groups & if_groups[i].group) {			return &if_groups[i];		}	}	return NULL;}static void notify_watchers(void){	struct watcher *w = watchers;	DBG(printk("io_interface_mux: notifying watchers\n"));	while (NULL != w) {		w->notify((const unsigned int)gpio_in_pins,			  (const unsigned int)gpio_out_pins,			  (const unsigned char)gpio_pa_pins,			  (const unsigned char)gpio_pb_pins);		w = w->next;	}}int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id){	int set_gen_config = 0;	int set_gen_config_ii = 0;	unsigned long int gens;	unsigned long int gens_ii;	struct if_group *grp;	unsigned char group_set;	unsigned long flags;	(void)cris_io_interface_init();	DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id));	if ((ioif >= if_max_interfaces) || (ioif < 0)) {		printk(KERN_CRIT "cris_request_io_interface: Bad interface %u submitted for %s\n",		       ioif,		       device_id);		return -EINVAL;	}	local_irq_save(flags);	if (interfaces[ioif].used) {		local_irq_restore(flags);		printk(KERN_CRIT "cris_io_interface: Cannot allocate interface for %s, in use by %s\n",		       device_id,		       interfaces[ioif].owner);		return -EBUSY;	}	/* Check that all required groups are free before allocating, */	group_set = interfaces[ioif].groups;	while (NULL != (grp = get_group(group_set))) {		if (grp->used) {			if (grp->group == group_f) {				if ((if_sync_serial_1 ==  ioif) ||				    (if_sync_serial_3 ==  ioif)) {					if ((grp->owner != if_sync_serial_1) &&					    (grp->owner != if_sync_serial_3)) {						local_irq_restore(flags);						return -EBUSY;					}				} else if ((if_scsi8_0 == ioif) ||					   (if_scsi8_1 == ioif)) {					if ((grp->owner != if_scsi8_0) &&					    (grp->owner != if_scsi8_1)) {						local_irq_restore(flags);						return -EBUSY;					}				}			} else {				local_irq_restore(flags);				return -EBUSY;			}		}		group_set = clear_group_from_set(group_set, grp);	}	/* Are the required GPIO pins available too? */	if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != interfaces[ioif].gpio_g_in) ||	    ((interfaces[ioif].gpio_g_out & gpio_out_pins) != interfaces[ioif].gpio_g_out) ||	    ((interfaces[ioif].gpio_b & gpio_pb_pins) != interfaces[ioif].gpio_b)) {		local_irq_restore(flags);		printk(KERN_CRIT "cris_request_io_interface: Could not get required pins for interface %u\n",		       ioif);		return -EBUSY;	}	/* All needed I/O pins and pin groups are free, allocate. */	group_set = interfaces[ioif].groups;	while (NULL != (grp = get_group(group_set))) {		grp->used = 1;		grp->owner = ioif;		group_set = clear_group_from_set(group_set, grp);	}	gens = genconfig_shadow;	gens_ii = gen_config_ii_shadow;	set_gen_config = 1;	switch (ioif)	{	/* Begin Non-multiplexed interfaces */	case if_eth:		/* fall through */	case if_serial_0:		set_gen_config = 0;		break;	/* End Non-multiplexed interfaces */	case if_serial_1:		set_gen_config_ii = 1;		SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async);		break;	case if_serial_2:		SETS(gens, R_GEN_CONFIG, ser2, select);		break;	case if_serial_3:		SETS(gens, R_GEN_CONFIG, ser3, select);		set_gen_config_ii = 1;		SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async);		break;	case if_sync_serial_1:		set_gen_config_ii = 1;		SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync);		break;	case if_sync_serial_3:		SETS(gens, R_GEN_CONFIG, ser3, select);		set_gen_config_ii = 1;		SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync);

⌨️ 快捷键说明

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