Esempio n. 1
0
me8254_subdevice_t* me8254_constr(uint16_t device_id, void* reg_base, unsigned int me8254_idx, unsigned int ctr_idx,
										me_lock_t* ctrl_reg_lock, me_lock_t* clk_src_reg_lock)
{
	me8254_subdevice_t *subdevice;

	PDEBUG("executed.\n");

/** @todo Checkings should be removed. We can safetly assume that data passed from upper level are correct.
*/
	// Check if counter index is out of range
	if (ctr_idx > 2)
	{
		PERROR("Counter index is out of range.\n");
		return NULL;
	}

	// Check device specific values.
	switch (device_id)
	{
		case PCI_DEVICE_ID_MEILHAUS_ME140A:
		case PCI_DEVICE_ID_MEILHAUS_ME14EA:

		case PCI_DEVICE_ID_MEILHAUS_ME4610:
		case PCI_DEVICE_ID_MEILHAUS_ME4660:
		case PCI_DEVICE_ID_MEILHAUS_ME4660I:
		case PCI_DEVICE_ID_MEILHAUS_ME4660S:
		case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4670:
		case PCI_DEVICE_ID_MEILHAUS_ME4670I:
		case PCI_DEVICE_ID_MEILHAUS_ME4670S:
		case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4680:
		case PCI_DEVICE_ID_MEILHAUS_ME4680I:
		case PCI_DEVICE_ID_MEILHAUS_ME4680S:
		case PCI_DEVICE_ID_MEILHAUS_ME4680IS:

		case PCI_DEVICE_ID_MEILHAUS_ME4560:
		case PCI_DEVICE_ID_MEILHAUS_ME4560I:
		case PCI_DEVICE_ID_MEILHAUS_ME4560S:
		case PCI_DEVICE_ID_MEILHAUS_ME4560IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4570:
		case PCI_DEVICE_ID_MEILHAUS_ME4570I:
		case PCI_DEVICE_ID_MEILHAUS_ME4570S:
		case PCI_DEVICE_ID_MEILHAUS_ME4570IS:

		case PCI_DEVICE_ID_MEILHAUS_ME4760:
		case PCI_DEVICE_ID_MEILHAUS_ME4760I:
		case PCI_DEVICE_ID_MEILHAUS_ME4760S:
		case PCI_DEVICE_ID_MEILHAUS_ME4760IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4770:
		case PCI_DEVICE_ID_MEILHAUS_ME4770I:
		case PCI_DEVICE_ID_MEILHAUS_ME4770S:
		case PCI_DEVICE_ID_MEILHAUS_ME4770IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4780:
		case PCI_DEVICE_ID_MEILHAUS_ME4780I:
		case PCI_DEVICE_ID_MEILHAUS_ME4780S:
		case PCI_DEVICE_ID_MEILHAUS_ME4780IS:

		case PCI_DEVICE_ID_MEILHAUS_ME4860:
		case PCI_DEVICE_ID_MEILHAUS_ME4860I:
		case PCI_DEVICE_ID_MEILHAUS_ME4860S:
		case PCI_DEVICE_ID_MEILHAUS_ME4860IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4870:
		case PCI_DEVICE_ID_MEILHAUS_ME4870I:
		case PCI_DEVICE_ID_MEILHAUS_ME4870S:
		case PCI_DEVICE_ID_MEILHAUS_ME4870IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4880:
		case PCI_DEVICE_ID_MEILHAUS_ME4880I:
		case PCI_DEVICE_ID_MEILHAUS_ME4880S:
		case PCI_DEVICE_ID_MEILHAUS_ME4880IS:

		case PCI_DEVICE_ID_MEILHAUS_ME0752:
		case PCI_DEVICE_ID_MEILHAUS_ME0754:
		case PCI_DEVICE_ID_MEILHAUS_ME0762:
		case PCI_DEVICE_ID_MEILHAUS_ME0764:
		case PCI_DEVICE_ID_MEILHAUS_ME0772:
		case PCI_DEVICE_ID_MEILHAUS_ME0774:
		case PCI_DEVICE_ID_MEILHAUS_ME0782:
		case PCI_DEVICE_ID_MEILHAUS_ME0784:

		case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
		case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
			if (me8254_idx > 0)
			{
				PERROR("8254 index is out of range. Must be 0.\n");
				return NULL;
			}
			break;

		case PCI_DEVICE_ID_MEILHAUS_ME140B:
		case PCI_DEVICE_ID_MEILHAUS_ME14EB:
			if (me8254_idx > 1)
			{
				PERROR("8254 index is out of range. Must be 0 or 1.\n");
				return NULL;
			}
			break;

		case PCI_DEVICE_ID_MEILHAUS_ME140C:
			if (me8254_idx > 4)
			{
				PERROR("8254 index is out of range. Must be between 0 and 3.\n");
				return NULL;
			}

		case PCI_DEVICE_ID_MEILHAUS_ME140D:
			if (me8254_idx > 9)
			{
				PERROR("8254 index is out of range. Must be between 0 and 8.\n");
				return NULL;
			}
			break;

		default:
			PERROR_CRITICAL("8254 registred for %x!\n", device_id);
			return NULL;
	}

	// Allocate memory for subdevice instance
	subdevice = kzalloc(sizeof(me8254_subdevice_t), GFP_KERNEL);
	if (!subdevice)
	{
		PERROR("Cannot get memory for 8254 instance.\n");
		return NULL;
	}

	// Initialize subdevice base class
	if (me_subdevice_init(&subdevice->base))
	{
		PERROR("Cannot initialize subdevice base class instance.\n");
		kfree(subdevice);
		return NULL;
	}

	// Initialize spin locks.
	subdevice->ctrl_reg_lock = ctrl_reg_lock;
	subdevice->clk_src_reg_lock = clk_src_reg_lock;

	// Save type of Meilhaus device
	subdevice->device_id = device_id;

	// Save the subdevice indexes.
	subdevice->me8254_idx = me8254_idx;
	subdevice->ctr_idx = ctr_idx;
	subdevice->base.idx = ctr_idx + (me8254_idx * 3);

/** @todo Setting flags for particular implementations create portibility problem.
	Flags should be passed from upper level.
	Also registers should be some how provided by upper level call.
*/
	// Do device specific initialization
	switch (device_id)
	{
		case PCI_DEVICE_ID_MEILHAUS_ME140A:
		case PCI_DEVICE_ID_MEILHAUS_ME14EA:
		case PCI_DEVICE_ID_MEILHAUS_ME140B:
		case PCI_DEVICE_ID_MEILHAUS_ME14EB:
			// Initialize the counters capabilities
			subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;
			if (ctr_idx == 0)
				subdevice->caps |= ME_CAPS_CTR_CLK_INTERNAL_1MHZ | ME_CAPS_CTR_CLK_INTERNAL_10MHZ;
			else
				subdevice->caps |= ME_CAPS_CTR_CLK_PREVIOUS;

			// Get the counters registers
			subdevice->val_reg = me1400AB_get_val_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->ctrl_reg = me1400AB_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->clk_src_reg = me1400AB_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
			break;

		case PCI_DEVICE_ID_MEILHAUS_ME140C:
		case PCI_DEVICE_ID_MEILHAUS_ME140D:
			// Initialize the counters capabilities
			subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL | ME_CAPS_CTR_CLK_PREVIOUS;
			if (ctr_idx == 0)
			{
				subdevice->caps |= ME_CAPS_CTR_CLK_INTERNAL_1MHZ | ME_CAPS_CTR_CLK_INTERNAL_10MHZ;
				if ((me8254_idx == 0) || (me8254_idx == 5))
				{// No cascading for first counter on first chips.
					subdevice->caps &= ~ME_CAPS_CTR_CLK_PREVIOUS;
				}
			}

			// Get the counters registers
			subdevice->val_reg = me1400CD_get_val_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->ctrl_reg = me1400CD_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->clk_src_reg = me1400CD_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
			break;

		case PCI_DEVICE_ID_MEILHAUS_ME4610:
		case PCI_DEVICE_ID_MEILHAUS_ME4660:
		case PCI_DEVICE_ID_MEILHAUS_ME4660I:
		case PCI_DEVICE_ID_MEILHAUS_ME4660S:
		case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4670:
		case PCI_DEVICE_ID_MEILHAUS_ME4670I:
		case PCI_DEVICE_ID_MEILHAUS_ME4670S:
		case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4680:
		case PCI_DEVICE_ID_MEILHAUS_ME4680I:
		case PCI_DEVICE_ID_MEILHAUS_ME4680S:
		case PCI_DEVICE_ID_MEILHAUS_ME4680IS:

		case PCI_DEVICE_ID_MEILHAUS_ME4560:
		case PCI_DEVICE_ID_MEILHAUS_ME4560I:
		case PCI_DEVICE_ID_MEILHAUS_ME4560S:
		case PCI_DEVICE_ID_MEILHAUS_ME4560IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4570:
		case PCI_DEVICE_ID_MEILHAUS_ME4570I:
		case PCI_DEVICE_ID_MEILHAUS_ME4570S:
		case PCI_DEVICE_ID_MEILHAUS_ME4570IS:

		case PCI_DEVICE_ID_MEILHAUS_ME4760:
		case PCI_DEVICE_ID_MEILHAUS_ME4760I:
		case PCI_DEVICE_ID_MEILHAUS_ME4760S:
		case PCI_DEVICE_ID_MEILHAUS_ME4760IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4770:
		case PCI_DEVICE_ID_MEILHAUS_ME4770I:
		case PCI_DEVICE_ID_MEILHAUS_ME4770S:
		case PCI_DEVICE_ID_MEILHAUS_ME4770IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4780:
		case PCI_DEVICE_ID_MEILHAUS_ME4780I:
		case PCI_DEVICE_ID_MEILHAUS_ME4780S:
		case PCI_DEVICE_ID_MEILHAUS_ME4780IS:

		case PCI_DEVICE_ID_MEILHAUS_ME4860:
		case PCI_DEVICE_ID_MEILHAUS_ME4860I:
		case PCI_DEVICE_ID_MEILHAUS_ME4860S:
		case PCI_DEVICE_ID_MEILHAUS_ME4860IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4870:
		case PCI_DEVICE_ID_MEILHAUS_ME4870I:
		case PCI_DEVICE_ID_MEILHAUS_ME4870S:
		case PCI_DEVICE_ID_MEILHAUS_ME4870IS:
		case PCI_DEVICE_ID_MEILHAUS_ME4880:
		case PCI_DEVICE_ID_MEILHAUS_ME4880I:
		case PCI_DEVICE_ID_MEILHAUS_ME4880S:
		case PCI_DEVICE_ID_MEILHAUS_ME4880IS:

		case PCI_DEVICE_ID_MEILHAUS_ME0752:
		case PCI_DEVICE_ID_MEILHAUS_ME0754:
		case PCI_DEVICE_ID_MEILHAUS_ME0762:
		case PCI_DEVICE_ID_MEILHAUS_ME0764:
		case PCI_DEVICE_ID_MEILHAUS_ME0772:
		case PCI_DEVICE_ID_MEILHAUS_ME0774:
		case PCI_DEVICE_ID_MEILHAUS_ME0782:
		case PCI_DEVICE_ID_MEILHAUS_ME0784:

			// Initialize the counters capabilities
			subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;

			// Get the counters registers
			subdevice->val_reg = me4600_get_val_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->ctrl_reg = me4600_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->clk_src_reg = 0; // Not used
			break;

		case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
		case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
			// Initialize the counters capabilities
			subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;

			// Get the counters registers
			subdevice->val_reg = me8100_get_val_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->ctrl_reg = me8100_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
			subdevice->clk_src_reg = 0; // Not used
			break;

		default:
			PERROR("Unknown device type.\n");
			me_subdevice_deinit(&subdevice->base);
			kfree(subdevice);
			return NULL;
	}


	// Overload subdevice base class methods.
	subdevice->base.me_subdevice_io_reset_subdevice = me8254_io_reset_subdevice;
	subdevice->base.me_subdevice_io_single_config = me8254_io_single_config;
	subdevice->base.me_subdevice_io_single_read = me8254_io_single_read;
	subdevice->base.me_subdevice_io_single_write = me8254_io_single_write;
	subdevice->base.me_subdevice_query_number_channels = me8254_query_number_channels;
	subdevice->base.me_subdevice_query_subdevice_type = me8254_query_subdevice_type;
	subdevice->base.me_subdevice_query_subdevice_caps = me8254_query_subdevice_caps;
	subdevice->base.me_subdevice_query_subdevice_caps_args = me8254_query_subdevice_caps_args;

	return subdevice;
}
Esempio n. 2
0
me8254_subdevice_t *me8254_constructor(uint32_t device_id,
				       uint32_t reg_base,
				       unsigned int me8254_idx,
				       unsigned int ctr_idx,
				       spinlock_t * ctrl_reg_lock,
				       spinlock_t * clk_src_reg_lock)
{
	me8254_subdevice_t *subdevice;
	int err;

	PDEBUG("executed.\n");

	// Allocate memory for subdevice instance
	subdevice = kmalloc(sizeof(me8254_subdevice_t), GFP_KERNEL);

	if (!subdevice) {
		PERROR("Cannot get memory for 8254 instance.\n");
		return NULL;
	}

	memset(subdevice, 0, sizeof(me8254_subdevice_t));

	// Check if counter index is out of range

	if (ctr_idx > 2) {
		PERROR("Counter index is out of range.\n");
		kfree(subdevice);
		return NULL;
	}
	// Initialize subdevice base class
	err = me_subdevice_init(&subdevice->base);

	if (err) {
		PERROR("Cannot initialize subdevice base class instance.\n");
		kfree(subdevice);
		return NULL;
	}
	// Initialize spin locks.
	spin_lock_init(&subdevice->subdevice_lock);
	subdevice->ctrl_reg_lock = ctrl_reg_lock;
	subdevice->clk_src_reg_lock = clk_src_reg_lock;

	// Save type of Meilhaus device
	subdevice->device_id = device_id;

	// Save the indices
	subdevice->me8254_idx = me8254_idx;
	subdevice->ctr_idx = ctr_idx;

	// Do device specific initialization
	switch (device_id) {

	case PCI_DEVICE_ID_MEILHAUS_ME140A:
	case PCI_DEVICE_ID_MEILHAUS_ME14EA:
		// Check if 8254 index is out of range
		if (me8254_idx > 0) {
			PERROR("8254 index is out of range.\n");
			me_subdevice_deinit(&subdevice->base);
			kfree(subdevice);
			return NULL;
		}

	case PCI_DEVICE_ID_MEILHAUS_ME140B:	// Fall through
	case PCI_DEVICE_ID_MEILHAUS_ME14EB:
		// Check if 8254 index is out of range
		if (me8254_idx > 1) {
			PERROR("8254 index is out of range.\n");
			me_subdevice_deinit(&subdevice->base);
			kfree(subdevice);
			return NULL;
		}
		// Initialize the counters capabilities
		if (ctr_idx == 0)
			subdevice->caps =
			    ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
			    ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
			    ME_CAPS_CTR_CLK_EXTERNAL;
		else
			subdevice->caps =
			    ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL;

		// Get the counters registers
		subdevice->val_reg =
		    me1400AB_get_val_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->ctrl_reg =
		    me1400AB_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->clk_src_reg =
		    me1400AB_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
		break;

	case PCI_DEVICE_ID_MEILHAUS_ME140C:
		// Check if 8254 index is out of range
		if (me8254_idx > 4) {
			PERROR("8254 index is out of range.\n");
			me_subdevice_deinit(&subdevice->base);
			kfree(subdevice);
			return NULL;
		}

	case PCI_DEVICE_ID_MEILHAUS_ME140D:
		// Check if 8254 index is out of range
		if (me8254_idx > 9) {
			PERROR("8254 index is out of range.\n");
			me_subdevice_deinit(&subdevice->base);
			kfree(subdevice);
			return NULL;
		}
		// Initialize the counters capabilities
		if (ctr_idx == 0) {
			if (me8254_idx == 0)
				subdevice->caps =
				    ME_CAPS_CTR_CLK_PREVIOUS |
				    ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
				    ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
				    ME_CAPS_CTR_CLK_EXTERNAL;
			else
				subdevice->caps =
				    ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
				    ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
				    ME_CAPS_CTR_CLK_EXTERNAL;
		} else
			subdevice->caps =
			    ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL;

		// Get the counters registers
		subdevice->val_reg =
		    me1400CD_get_val_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->ctrl_reg =
		    me1400CD_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->clk_src_reg =
		    me1400CD_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
		break;

	case PCI_DEVICE_ID_MEILHAUS_ME4610:
	case PCI_DEVICE_ID_MEILHAUS_ME4660:
	case PCI_DEVICE_ID_MEILHAUS_ME4660I:
	case PCI_DEVICE_ID_MEILHAUS_ME4660S:
	case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
	case PCI_DEVICE_ID_MEILHAUS_ME4670:
	case PCI_DEVICE_ID_MEILHAUS_ME4670I:
	case PCI_DEVICE_ID_MEILHAUS_ME4670S:
	case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
	case PCI_DEVICE_ID_MEILHAUS_ME4680:
	case PCI_DEVICE_ID_MEILHAUS_ME4680I:
	case PCI_DEVICE_ID_MEILHAUS_ME4680S:
	case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
		// Check if 8254 index is out of range
		if (me8254_idx > 0) {
			PERROR("8254 index is out of range.\n");
			me_subdevice_deinit(&subdevice->base);
			kfree(subdevice);
			return NULL;
		}
		// Initialize the counters capabilities
		subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;

		// Get the counters registers
		subdevice->val_reg =
		    me4600_get_val_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->ctrl_reg =
		    me4600_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->clk_src_reg = 0;	// Not used
		break;

	case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
	case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
		// Check if 8254 index is out of range
		if (me8254_idx > 0) {
			PERROR("8254 index is out of range.\n");
			me_subdevice_deinit(&subdevice->base);
			kfree(subdevice);
			return NULL;
		}
		// Initialize the counters capabilities
		subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;

		// Get the counters registers
		subdevice->val_reg =
		    me8100_get_val_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->ctrl_reg =
		    me8100_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
		subdevice->clk_src_reg = 0;	// Not used
		break;

	case PCI_DEVICE_ID_MEILHAUS_ME4650:
	case PCI_DEVICE_ID_MEILHAUS_ME1400:
	case PCI_DEVICE_ID_MEILHAUS_ME14E0:
		PERROR("No 8254 subdevices available for subdevice device.\n");
		me_subdevice_deinit(&subdevice->base);
		kfree(subdevice);
		return NULL;

	default:
		PERROR("Unknown device type.\n");
		me_subdevice_deinit(&subdevice->base);
		kfree(subdevice);
		return NULL;
	}

	// Overload subdevice base class methods.
	subdevice->base.me_subdevice_io_reset_subdevice =
	    me8254_io_reset_subdevice;
	subdevice->base.me_subdevice_io_single_config = me8254_io_single_config;
	subdevice->base.me_subdevice_io_single_read = me8254_io_single_read;
	subdevice->base.me_subdevice_io_single_write = me8254_io_single_write;
	subdevice->base.me_subdevice_query_number_channels =
	    me8254_query_number_channels;
	subdevice->base.me_subdevice_query_subdevice_type =
	    me8254_query_subdevice_type;
	subdevice->base.me_subdevice_query_subdevice_caps =
	    me8254_query_subdevice_caps;
	subdevice->base.me_subdevice_query_subdevice_caps_args =
	    me8254_query_subdevice_caps_args;

	return subdevice;
}