コード例 #1
0
ファイル: i2c.c プロジェクト: 3sOx/asuswrt-merlin
static int i2c_pnx_resume(struct platform_device *pdev)
{
	int retval = 0;
#ifdef CONFIG_PM
	retval = set_clock_run(pdev);
#endif
	return retval;
}
コード例 #2
0
ファイル: i2c.c プロジェクト: 3sOx/asuswrt-merlin
static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
{
	int retval = 0;
#ifdef CONFIG_PM
	retval = set_clock_run(pdev);
#endif
	return retval;
}
コード例 #3
0
ファイル: i2c-pnx.c プロジェクト: GodFox/magx_kernel_xpixl
static int i2c_pnx_probe(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	unsigned long tmp;
	int ret;
	i2c_pnx_algo_data_t * alg_data;
	int freq_mhz;
#ifdef CONFIG_I2C_PNX_SLAVE_SUPPORT
	int *m_params_mode[] = {&slave_mode0, &slave_mode1};
	int *m_params_address[] = {&slave_addr0, &slave_addr1};
#endif
	
	freq_mhz = calculate_input_freq(dev);
	
	if (pdev->id > ARRAY_SIZE(pnx_i2c_adapters)) {
		printk(KERN_ERR "I2C device %d is not defined.\n", pdev->id);
		return -ENODEV;
	}

	dev_set_drvdata(dev, pnx_i2c_adapters[pdev->id]);

	alg_data = (i2c_pnx_algo_data_t *) pnx_i2c_adapters[pdev->id]->algo_data;

#ifdef CONFIG_I2C_PNX_SLAVE_SUPPORT
	if (*m_params_mode[pdev->id]) 
		alg_data->mode = slave;
	else 
		alg_data->mode = master;
	alg_data->slave_addr = *m_params_address[pdev->id];
#endif

	/* Internal Data structures for Master */
	if (alg_data->mode == master) {
		memset(&alg_data->mif, 0, sizeof(alg_data->mif));
		init_MUTEX(&alg_data->mif.sem);
		init_timer(&alg_data->mif.timer);
		alg_data->mif.timer.function = i2c_pnx_timeout;
		alg_data->mif.timer.data = (unsigned long) alg_data;
	} else {
		/* Init I2C buffer */
		memset (&alg_data->buffer, 0, I2C_BUFFER_SIZE);
		alg_data->buf_index = 0;
	}

	/* Register I/O resource */
	if (!request_region(alg_data->base, I2C_BLOCK_SIZE, "i2c-pnx")) {
		printk(KERN_ERR
		       "I/O region 0x%08x for I2C already in use.\n",
		       alg_data->base);
		return -ENODEV;
	} 

	set_clock_run(dev);

	/* Clock Divisor High This value is the number of system clocks
	 * the serial clock (SCL) will be high. n is defined at compile
	 * time based on the system clock (PCLK) and minimum serial frequency.
	 * For example, if the system clock period is 50 ns and the maximum
	 * desired serial period is 10000 ns (100 kHz), then CLKHI would be
	 * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
	 * programmed into CLKHI will vary from this slightly due to
	 * variations in the output pad s rise and fall times as well as
	 * the deglitching filter length. In this example, n = 7, since
	 * eight bits are needed to hold the clock divider count.
	 */

	if (alg_data->mode == master) {
		tmp = ((freq_mhz * 1000) / I2C_PNX010X_SPEED_KHZ)/2 - 2;
		alg_data->master->ckh = tmp;
		alg_data->master->ckl = tmp;
	}
	else if (alg_data->slave_addr != 0xff) {
		alg_data->slave->adr = alg_data->slave_addr & 0x7f;
		if (alg_data->slave->adr != (alg_data->slave_addr & 0x7f))
			printk(KERN_ERR "%s: "
			       "Failed to program the slave to address %u.\n",
			       pnx_i2c_adapters[pdev->id]->name, (alg_data->slave_addr & 0x7f));
	}
	/* Master/Slave interrupts init */
	if (alg_data->mode == slave)
		alg_data->slave->ctl = scntrl_drsie | scntrl_daie;
	else
		alg_data->master->ctl = 0;

	/* Reset the I2C Master/Slave. The reset bit is self clearing. */
	if (alg_data->mode == slave) {
		alg_data->slave->ctl |= scntrl_reset;
		while ((alg_data->slave->ctl & scntrl_reset));
	} else {
		alg_data->master->ctl |= mcntrl_reset;
		while ((alg_data->master->ctl & mcntrl_reset));
	}

	if (alg_data->mode != slave) {
		/* initialize the completion var */	
		init_completion(&alg_data->mif.complete);
	}

	ret = request_irq(alg_data->irq, i2c_pnx_interrupt, 0,
			  alg_data->mode == slave? CHIP_NAME" Slave":CHIP_NAME" Master",
			  alg_data);
	if (ret) {
		set_clock_stop(dev);
		release_region(alg_data->base, I2C_BLOCK_SIZE);
		return ret;
	}

	/* Register this adapter with the I2C subsystem */
	if (alg_data->mode == master) {
		pnx_i2c_adapters[pdev->id]->dev.parent = dev;
		ret = i2c_add_adapter(pnx_i2c_adapters[pdev->id]);
		if (ret < 0) {
			printk(KERN_INFO "I2C: Failed to add bus\n");
			free_irq(alg_data->irq, alg_data);
			set_clock_stop(dev);
			release_region(alg_data->base, I2C_BLOCK_SIZE);
			return ret;
		}
	}

	printk(KERN_INFO "%s: %s at %#8x, irq %d.\n",
	       pnx_i2c_adapters[pdev->id]->name, alg_data->mode == slave?"Slave":"Master",
	       alg_data->base, alg_data->irq);

	return 0;
}