i2c: rcar_i2c: Add DM and DT capable I2C driver
Add derivative of the rcar_i2c driver which is capable of probing itself from DM and uses DT. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Heiko Schocher <hs@denx.de> Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
This commit is contained in:
		
							parent
							
								
									a4d9aafadb
								
							
						
					
					
						commit
						a06a0ac36d
					
				|  | @ -339,6 +339,12 @@ config SYS_OMAP24_I2C_SPEED | ||||||
| 	  OMAP24xx Slave speed channel 0 | 	  OMAP24xx Slave speed channel 0 | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | config SYS_I2C_RCAR_I2C | ||||||
|  | 	bool "Renesas RCar I2C driver" | ||||||
|  | 	depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C | ||||||
|  | 	help | ||||||
|  | 	  Support for Renesas RCar I2C controller. | ||||||
|  | 
 | ||||||
| config SYS_I2C_RCAR_IIC | config SYS_I2C_RCAR_IIC | ||||||
| 	bool "Renesas RCar Gen3 IIC driver" | 	bool "Renesas RCar Gen3 IIC driver" | ||||||
| 	depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C | 	depends on (RCAR_GEN3 || RCAR_GEN2) && DM_I2C | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o | ||||||
| obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o | obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o | ||||||
| obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o | obj-$(CONFIG_SYS_I2C_MXS) += mxs_i2c.o | ||||||
| obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o | obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o | ||||||
|  | obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o | ||||||
| obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o | obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o | ||||||
| obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o | obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o | ||||||
| obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o | obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o exynos_hs_i2c.o | ||||||
|  |  | ||||||
|  | @ -0,0 +1,353 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+
 | ||||||
|  | /*
 | ||||||
|  |  * drivers/i2c/rcar_i2c.c | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com> | ||||||
|  |  * | ||||||
|  |  * Clock configuration based on Linux i2c-rcar.c: | ||||||
|  |  * Copyright (C) 2014-15 Wolfram Sang <wsa@sang-engineering.com> | ||||||
|  |  * Copyright (C) 2011-2015 Renesas Electronics Corporation | ||||||
|  |  * Copyright (C) 2012-14 Renesas Solutions Corp. | ||||||
|  |  *   Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <common.h> | ||||||
|  | #include <clk.h> | ||||||
|  | #include <dm.h> | ||||||
|  | #include <i2c.h> | ||||||
|  | #include <asm/io.h> | ||||||
|  | #include <wait_bit.h> | ||||||
|  | 
 | ||||||
|  | #define RCAR_I2C_ICSCR			0x00 | ||||||
|  | #define RCAR_I2C_ICMCR			0x04 | ||||||
|  | #define RCAR_I2C_ICMCR_MDBS		BIT(7) | ||||||
|  | #define RCAR_I2C_ICMCR_FSCL		BIT(6) | ||||||
|  | #define RCAR_I2C_ICMCR_FSDA		BIT(5) | ||||||
|  | #define RCAR_I2C_ICMCR_OBPC		BIT(4) | ||||||
|  | #define RCAR_I2C_ICMCR_MIE		BIT(3) | ||||||
|  | #define RCAR_I2C_ICMCR_TSBE		BIT(2) | ||||||
|  | #define RCAR_I2C_ICMCR_FSB		BIT(1) | ||||||
|  | #define RCAR_I2C_ICMCR_ESG		BIT(0) | ||||||
|  | #define RCAR_I2C_ICSSR			0x08 | ||||||
|  | #define RCAR_I2C_ICMSR			0x0c | ||||||
|  | #define RCAR_I2C_ICMSR_MASK		0x7f | ||||||
|  | #define RCAR_I2C_ICMSR_MNR		BIT(6) | ||||||
|  | #define RCAR_I2C_ICMSR_MAL		BIT(5) | ||||||
|  | #define RCAR_I2C_ICMSR_MST		BIT(4) | ||||||
|  | #define RCAR_I2C_ICMSR_MDE		BIT(3) | ||||||
|  | #define RCAR_I2C_ICMSR_MDT		BIT(2) | ||||||
|  | #define RCAR_I2C_ICMSR_MDR		BIT(1) | ||||||
|  | #define RCAR_I2C_ICMSR_MAT		BIT(0) | ||||||
|  | #define RCAR_I2C_ICSIER			0x10 | ||||||
|  | #define RCAR_I2C_ICMIER			0x14 | ||||||
|  | #define RCAR_I2C_ICCCR			0x18 | ||||||
|  | #define RCAR_I2C_ICCCR_SCGD_OFF		3 | ||||||
|  | #define RCAR_I2C_ICSAR			0x1c | ||||||
|  | #define RCAR_I2C_ICMAR			0x20 | ||||||
|  | #define RCAR_I2C_ICRXD_ICTXD		0x24 | ||||||
|  | 
 | ||||||
|  | struct rcar_i2c_priv { | ||||||
|  | 	void __iomem		*base; | ||||||
|  | 	struct clk		clk; | ||||||
|  | 	u32			intdelay; | ||||||
|  | 	u32			icccr; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_finish(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, RCAR_I2C_ICMSR_MST, | ||||||
|  | 				true, 10, true); | ||||||
|  | 
 | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICSSR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void rcar_i2c_recover(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	u32 mcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_OBPC; | ||||||
|  | 	u32 mcra = mcr | RCAR_I2C_ICMCR_FSDA; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	/* Send 9 SCL pulses */ | ||||||
|  | 	for (i = 0; i < 9; i++) { | ||||||
|  | 		writel(mcra | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 		udelay(5); | ||||||
|  | 		writel(mcra, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 		udelay(5); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Send stop condition */ | ||||||
|  | 	udelay(5); | ||||||
|  | 	writel(mcra, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 	udelay(5); | ||||||
|  | 	writel(mcr, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 	udelay(5); | ||||||
|  | 	writel(mcr | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 	udelay(5); | ||||||
|  | 	writel(mcra | RCAR_I2C_ICMCR_FSCL, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 	udelay(5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_set_addr(struct udevice *dev, u8 chip, u8 read) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	u32 mask = RCAR_I2C_ICMSR_MAT | | ||||||
|  | 		   (read ? RCAR_I2C_ICMSR_MDR : RCAR_I2C_ICMSR_MDE); | ||||||
|  | 	u32 val; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMIER); | ||||||
|  | 	writel(RCAR_I2C_ICMCR_MDBS, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 	writel(priv->icccr, priv->base + RCAR_I2C_ICCCR); | ||||||
|  | 
 | ||||||
|  | 	ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMCR, | ||||||
|  | 				RCAR_I2C_ICMCR_FSDA, false, 2, true); | ||||||
|  | 	if (ret) { | ||||||
|  | 		rcar_i2c_recover(dev); | ||||||
|  | 		val = readl(priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 		if (val & RCAR_I2C_ICMCR_FSDA) { | ||||||
|  | 			dev_err(dev, "Bus busy, aborting\n"); | ||||||
|  | 			return ret; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	writel((chip << 1) | read, priv->base + RCAR_I2C_ICMAR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 	writel(RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE | RCAR_I2C_ICMCR_ESG, | ||||||
|  | 	       priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 
 | ||||||
|  | 	ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, mask, | ||||||
|  | 				true, 100, true); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	/* Check NAK */ | ||||||
|  | 	if (readl(priv->base + RCAR_I2C_ICMSR) & RCAR_I2C_ICMSR_MNR) | ||||||
|  | 		return -EREMOTEIO; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_read_common(struct udevice *dev, struct i2c_msg *msg) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	u32 icmcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE; | ||||||
|  | 	int i, ret = -EREMOTEIO; | ||||||
|  | 
 | ||||||
|  | 	ret = rcar_i2c_set_addr(dev, msg->addr, 1); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < msg->len; i++) { | ||||||
|  | 		if (msg->len - 1 == i) | ||||||
|  | 			icmcr |= RCAR_I2C_ICMCR_FSB; | ||||||
|  | 
 | ||||||
|  | 		writel(icmcr, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 		writel(~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 
 | ||||||
|  | 		ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, | ||||||
|  | 					RCAR_I2C_ICMSR_MDR, true, 100, true); | ||||||
|  | 		if (ret) | ||||||
|  | 			return ret; | ||||||
|  | 
 | ||||||
|  | 		msg->buf[i] = readl(priv->base + RCAR_I2C_ICRXD_ICTXD) & 0xff; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	writel(~RCAR_I2C_ICMSR_MDR, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 
 | ||||||
|  | 	return rcar_i2c_finish(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_write_common(struct udevice *dev, struct i2c_msg *msg) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	u32 icmcr = RCAR_I2C_ICMCR_MDBS | RCAR_I2C_ICMCR_MIE; | ||||||
|  | 	int i, ret = -EREMOTEIO; | ||||||
|  | 
 | ||||||
|  | 	ret = rcar_i2c_set_addr(dev, msg->addr, 0); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < msg->len; i++) { | ||||||
|  | 		writel(msg->buf[i], priv->base + RCAR_I2C_ICRXD_ICTXD); | ||||||
|  | 		writel(icmcr, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 		writel(~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 
 | ||||||
|  | 		ret = wait_for_bit_le32(priv->base + RCAR_I2C_ICMSR, | ||||||
|  | 					RCAR_I2C_ICMSR_MDE, true, 100, true); | ||||||
|  | 		if (ret) | ||||||
|  | 			return ret; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	writel(~RCAR_I2C_ICMSR_MDE, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 	icmcr |= RCAR_I2C_ICMCR_FSB; | ||||||
|  | 	writel(icmcr, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 
 | ||||||
|  | 	return rcar_i2c_finish(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	for (; nmsgs > 0; nmsgs--, msg++) { | ||||||
|  | 		if (msg->flags & I2C_M_RD) | ||||||
|  | 			ret = rcar_i2c_read_common(dev, msg); | ||||||
|  | 		else | ||||||
|  | 			ret = rcar_i2c_write_common(dev, msg); | ||||||
|  | 
 | ||||||
|  | 		if (ret) | ||||||
|  | 			return -EREMOTEIO; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_probe_chip(struct udevice *dev, uint addr, uint flags) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	/* Ignore address 0, slave address */ | ||||||
|  | 	if (addr == 0) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	ret = rcar_i2c_set_addr(dev, addr, 1); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_set_speed(struct udevice *dev, uint bus_freq_hz) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	u32 scgd, cdf, round, ick, sum, scl; | ||||||
|  | 	unsigned long rate; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * calculate SCL clock | ||||||
|  | 	 * see | ||||||
|  | 	 *	ICCCR | ||||||
|  | 	 * | ||||||
|  | 	 * ick	= clkp / (1 + CDF) | ||||||
|  | 	 * SCL	= ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick]) | ||||||
|  | 	 * | ||||||
|  | 	 * ick  : I2C internal clock < 20 MHz | ||||||
|  | 	 * ticf : I2C SCL falling time | ||||||
|  | 	 * tr   : I2C SCL rising  time | ||||||
|  | 	 * intd : LSI internal delay | ||||||
|  | 	 * clkp : peripheral_clk | ||||||
|  | 	 * F[]  : integer up-valuation | ||||||
|  | 	 */ | ||||||
|  | 	rate = clk_get_rate(&priv->clk); | ||||||
|  | 	cdf = rate / 20000000; | ||||||
|  | 	if (cdf >= 8) { | ||||||
|  | 		dev_err(dev, "Input clock %lu too high\n", rate); | ||||||
|  | 		return -EIO; | ||||||
|  | 	} | ||||||
|  | 	ick = rate / (cdf + 1); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * it is impossible to calculate large scale | ||||||
|  | 	 * number on u32. separate it | ||||||
|  | 	 * | ||||||
|  | 	 * F[(ticf + tr + intd) * ick] with sum = (ticf + tr + intd) | ||||||
|  | 	 *  = F[sum * ick / 1000000000] | ||||||
|  | 	 *  = F[(ick / 1000000) * sum / 1000] | ||||||
|  | 	 */ | ||||||
|  | 	sum = 35 + 200 + priv->intdelay; | ||||||
|  | 	round = (ick + 500000) / 1000000 * sum; | ||||||
|  | 	round = (round + 500) / 1000; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * SCL	= ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick]) | ||||||
|  | 	 * | ||||||
|  | 	 * Calculation result (= SCL) should be less than | ||||||
|  | 	 * bus_speed for hardware safety | ||||||
|  | 	 * | ||||||
|  | 	 * We could use something along the lines of | ||||||
|  | 	 *	div = ick / (bus_speed + 1) + 1; | ||||||
|  | 	 *	scgd = (div - 20 - round + 7) / 8; | ||||||
|  | 	 *	scl = ick / (20 + (scgd * 8) + round); | ||||||
|  | 	 * (not fully verified) but that would get pretty involved | ||||||
|  | 	 */ | ||||||
|  | 	for (scgd = 0; scgd < 0x40; scgd++) { | ||||||
|  | 		scl = ick / (20 + (scgd * 8) + round); | ||||||
|  | 		if (scl <= bus_freq_hz) | ||||||
|  | 			goto scgd_find; | ||||||
|  | 	} | ||||||
|  | 	dev_err(dev, "it is impossible to calculate best SCL\n"); | ||||||
|  | 	return -EIO; | ||||||
|  | 
 | ||||||
|  | scgd_find: | ||||||
|  | 	dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n", | ||||||
|  | 		scl, bus_freq_hz, clk_get_rate(&priv->clk), round, cdf, scgd); | ||||||
|  | 
 | ||||||
|  | 	priv->icccr = (scgd << RCAR_I2C_ICCCR_SCGD_OFF) | cdf; | ||||||
|  | 	writel(priv->icccr, priv->base + RCAR_I2C_ICCCR); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int rcar_i2c_probe(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct rcar_i2c_priv *priv = dev_get_priv(dev); | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	priv->base = dev_read_addr_ptr(dev); | ||||||
|  | 	priv->intdelay = dev_read_u32_default(dev, | ||||||
|  | 					      "i2c-scl-internal-delay-ns", 5); | ||||||
|  | 
 | ||||||
|  | 	ret = clk_get_by_index(dev, 0, &priv->clk); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	ret = clk_enable(&priv->clk); | ||||||
|  | 	if (ret) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  | 	/* reset slave mode */ | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICSIER); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICSAR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICSCR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICSSR); | ||||||
|  | 
 | ||||||
|  | 	/* reset master mode */ | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMIER); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMCR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMSR); | ||||||
|  | 	writel(0, priv->base + RCAR_I2C_ICMAR); | ||||||
|  | 
 | ||||||
|  | 	ret = rcar_i2c_set_speed(dev, 100000); | ||||||
|  | 	if (ret) | ||||||
|  | 		clk_disable(&priv->clk); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct dm_i2c_ops rcar_i2c_ops = { | ||||||
|  | 	.xfer		= rcar_i2c_xfer, | ||||||
|  | 	.probe_chip	= rcar_i2c_probe_chip, | ||||||
|  | 	.set_bus_speed	= rcar_i2c_set_speed, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct udevice_id rcar_i2c_ids[] = { | ||||||
|  | 	{ .compatible = "renesas,rcar-gen2-i2c" }, | ||||||
|  | 	{ } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | U_BOOT_DRIVER(i2c_rcar) = { | ||||||
|  | 	.name		= "i2c_rcar", | ||||||
|  | 	.id		= UCLASS_I2C, | ||||||
|  | 	.of_match	= rcar_i2c_ids, | ||||||
|  | 	.probe		= rcar_i2c_probe, | ||||||
|  | 	.priv_auto_alloc_size = sizeof(struct rcar_i2c_priv), | ||||||
|  | 	.ops		= &rcar_i2c_ops, | ||||||
|  | }; | ||||||
		Loading…
	
		Reference in New Issue