Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d32f60ed authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'next-i2c' of git://aeryn.fluff.org.uk/bjdooks/linux

* 'next-i2c' of git://aeryn.fluff.org.uk/bjdooks/linux:
  i2c-ocores: Can add I2C devices to the bus
  i2c-s3c2410: move to using platform idtable to match devices
  i2c: OMAP3: Better noise suppression for fast/standard modes
  i2c: OMAP2/3: Fix scll/sclh calculations
  i2c: Blackfin TWI: implement I2C_FUNC_SMBUS_I2C_BLOCK functionality
  i2c: Blackfin TWI: fix transfer errors with repeat start
  i2c: Blackfin TWI: fix REPEAT START mode doesn't repeat
  i2c: Blackfin TWI: make sure we don't end up with a CLKDIV=0
parents a2ee2981 dd14be4c
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ platform_device with the base address and interrupt number. The
dev.platform_data of the device should also point to a struct
ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the
distance between registers and the input clock speed.
There is also a possibility to attach a list of i2c_board_info which
the i2c-ocores driver will add to the bus upon creation.

E.G. something like:

@@ -36,9 +38,24 @@ static struct resource ocores_resources[] = {
	},
};

/* optional board info */
struct i2c_board_info ocores_i2c_board_info[] = {
	{
		I2C_BOARD_INFO("tsc2003", 0x48),
		.platform_data = &tsc2003_platform_data,
		.irq = TSC_IRQ
	},
	{
		I2C_BOARD_INFO("adv7180", 0x42 >> 1),
		.irq = ADV_IRQ
	}
};

static struct ocores_i2c_platform_data myi2c_data = {
	.regstep	= 2,		/* two bytes between registers */
	.clock_khz	= 50000,	/* input clock of 50MHz */
	.devices	= ocores_i2c_board_info, /* optional table of devices */
	.num_devices	= ARRAY_SIZE(ocores_i2c_board_info), /* table size */
};

static struct platform_device myi2c = {
+1 −1
Original line number Diff line number Diff line
@@ -298,7 +298,7 @@ config I2C_BLACKFIN_TWI
config I2C_BLACKFIN_TWI_CLK_KHZ
	int "Blackfin TWI I2C clock (kHz)"
	depends on I2C_BLACKFIN_TWI
	range 10 400
	range 21 400
	default 50
	help
	  The unit of the TWI clock is kHz.
+41 −18
Original line number Diff line number Diff line
@@ -104,9 +104,14 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
			write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) | STOP);
		else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
				iface->cur_msg+1 < iface->msg_num)
		         iface->cur_msg + 1 < iface->msg_num) {
			if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
				write_MASTER_CTL(iface,
					read_MASTER_CTL(iface) | RSTART | MDIR);
			else
				write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) | RSTART);
					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
		}
		SSYNC();
		/* Clear status */
		write_INT_STAT(iface, XMTSERV);
@@ -135,8 +140,12 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
			SSYNC();
		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
		           iface->cur_msg + 1 < iface->msg_num) {
			if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
				write_MASTER_CTL(iface,
					read_MASTER_CTL(iface) | RSTART | MDIR);
			else
				write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) | RSTART);
					(read_MASTER_CTL(iface) | RSTART) & ~MDIR);
			SSYNC();
		}
		/* Clear interrupt source */
@@ -196,8 +205,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
			/* remove restart bit and enable master receive */
			write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) & ~RSTART);
			write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) | MEN | MDIR);
			SSYNC();
		} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
				iface->cur_msg+1 < iface->msg_num) {
@@ -223,17 +230,18 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)

			if (iface->pmsg[iface->cur_msg].len <= 255)
					write_MASTER_CTL(iface,
				iface->pmsg[iface->cur_msg].len << 6);
					(read_MASTER_CTL(iface) &
					(~(0xff << 6))) |
				(iface->pmsg[iface->cur_msg].len << 6));
			else {
				write_MASTER_CTL(iface, 0xff << 6);
				write_MASTER_CTL(iface,
					(read_MASTER_CTL(iface) |
					(0xff << 6)));
				iface->manual_stop = 1;
			}
			/* remove restart bit and enable master receive */
			write_MASTER_CTL(iface,
				read_MASTER_CTL(iface) & ~RSTART);
			write_MASTER_CTL(iface, read_MASTER_CTL(iface) |
				MEN | ((iface->read_write == I2C_SMBUS_READ) ?
				MDIR : 0));
			SSYNC();
		} else {
			iface->result = 1;
@@ -441,6 +449,16 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
		}
		iface->transPtr = data->block;
		break;
	case I2C_SMBUS_I2C_BLOCK_DATA:
		if (read_write == I2C_SMBUS_READ) {
			iface->readNum = data->block[0];
			iface->cur_mode = TWI_I2C_MODE_COMBINED;
		} else {
			iface->writeNum = data->block[0];
			iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
		}
		iface->transPtr = (u8 *)&data->block[1];
		break;
	default:
		return -1;
	}
@@ -564,7 +582,7 @@ static u32 bfin_twi_functionality(struct i2c_adapter *adap)
	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
	       I2C_FUNC_I2C;
	       I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK;
}

static struct i2c_algorithm bfin_twi_algorithm = {
@@ -614,6 +632,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
	struct i2c_adapter *p_adap;
	struct resource *res;
	int rc;
	unsigned int clkhilow;

	iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
	if (!iface) {
@@ -675,10 +694,14 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
	/* Set TWI internal clock as 10MHz */
	write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);

	/*
	 * We will not end up with a CLKDIV=0 because no one will specify
	 * 20kHz SCL or less in Kconfig now. (5 * 1024 / 20 = 0x100)
	 */
	clkhilow = 5 * 1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ;

	/* Set Twi interface clock as specified */
	write_CLKDIV(iface, ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
			<< 8) | ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
			& 0xFF));
	write_CLKDIV(iface, (clkhilow << 8) | clkhilow);

	/* Enable TWI */
	write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
+5 −0
Original line number Diff line number Diff line
@@ -216,6 +216,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
	struct ocores_i2c_platform_data *pdata;
	struct resource *res, *res2;
	int ret;
	int i;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
@@ -271,6 +272,10 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
		goto add_adapter_failed;
	}

	/* add in known devices to the bus */
	for (i = 0; i < pdata->num_devices; i++)
		i2c_new_device(&i2c->adap, pdata->devices + i);

	return 0;

add_adapter_failed:
+30 −9
Original line number Diff line number Diff line
@@ -333,8 +333,18 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)

	if (cpu_is_omap2430() || cpu_is_omap34xx()) {

		/* HSI2C controller internal clk rate should be 19.2 Mhz */
		/*
		 * HSI2C controller internal clk rate should be 19.2 Mhz for
		 * HS and for all modes on 2430. On 34xx we can use lower rate
		 * to get longer filter period for better noise suppression.
		 * The filter is iclk (fclk for HS) period.
		 */
		if (dev->speed > 400 || cpu_is_omap_2430())
			internal_clk = 19200;
		else if (dev->speed > 100)
			internal_clk = 9600;
		else
			internal_clk = 4000;
		fclk_rate = clk_get_rate(dev->fclk) / 1000;

		/* Compute prescaler divisor */
@@ -343,17 +353,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)

		/* If configured for High Speed */
		if (dev->speed > 400) {
			unsigned long scl;

			/* For first phase of HS mode */
			fsscll = internal_clk / (400 * 2) - 6;
			fssclh = internal_clk / (400 * 2) - 6;
			scl = internal_clk / 400;
			fsscll = scl - (scl / 3) - 7;
			fssclh = (scl / 3) - 5;

			/* For second phase of HS mode */
			hsscll = fclk_rate / (dev->speed * 2) - 6;
			hssclh = fclk_rate / (dev->speed * 2) - 6;
			scl = fclk_rate / dev->speed;
			hsscll = scl - (scl / 3) - 7;
			hssclh = (scl / 3) - 5;
		} else if (dev->speed > 100) {
			unsigned long scl;

			/* Fast mode */
			scl = internal_clk / dev->speed;
			fsscll = scl - (scl / 3) - 7;
			fssclh = (scl / 3) - 5;
		} else {
			/* To handle F/S modes */
			fsscll = internal_clk / (dev->speed * 2) - 6;
			fssclh = internal_clk / (dev->speed * 2) - 6;
			/* Standard mode */
			fsscll = internal_clk / (dev->speed * 2) - 7;
			fssclh = internal_clk / (dev->speed * 2) - 5;
		}
		scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
		sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
Loading