diff options
Diffstat (limited to 'drivers/i2c')
38 files changed, 2042 insertions, 563 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index fc90293afcbf..eddf25b90ca8 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -184,8 +184,9 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)  	/* read ack: SDA should be pulled down by slave, or it may  	 * NAK (usually to report problems with the data we wrote). +	 * Always report ACK if SDA is write-only.  	 */ -	ack = !getsda(adap);    /* ack: sda is pulled low -> success */ +	ack = !adap->getsda || !getsda(adap);    /* ack: sda is pulled low -> success */  	bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,  		ack ? "A" : "NA"); @@ -238,71 +239,55 @@ static int test_bus(struct i2c_adapter *i2c_adap)  			return -ENODEV;  	} +	if (adap->getsda == NULL) +		pr_info("%s: SDA is write-only, testing not possible\n", name);  	if (adap->getscl == NULL) -		pr_info("%s: Testing SDA only, SCL is not readable\n", name); +		pr_info("%s: SCL is write-only, testing not possible\n", name); -	sda = getsda(adap); -	scl = (adap->getscl == NULL) ? 1 : getscl(adap); +	sda = adap->getsda ? getsda(adap) : 1; +	scl = adap->getscl ? getscl(adap) : 1;  	if (!scl || !sda) { -		printk(KERN_WARNING -		       "%s: bus seems to be busy (scl=%d, sda=%d)\n", -		       name, scl, sda); +		pr_warn("%s: bus seems to be busy (scl=%d, sda=%d)\n", name, scl, sda);  		goto bailout;  	}  	sdalo(adap); -	sda = getsda(adap); -	scl = (adap->getscl == NULL) ? 1 : getscl(adap); -	if (sda) { -		printk(KERN_WARNING "%s: SDA stuck high!\n", name); +	if (adap->getsda && getsda(adap)) { +		pr_warn("%s: SDA stuck high!\n", name);  		goto bailout;  	} -	if (!scl) { -		printk(KERN_WARNING -		       "%s: SCL unexpected low while pulling SDA low!\n", -		       name); +	if (adap->getscl && !getscl(adap)) { +		pr_warn("%s: SCL unexpected low while pulling SDA low!\n", name);  		goto bailout;  	}  	sdahi(adap); -	sda = getsda(adap); -	scl = (adap->getscl == NULL) ? 1 : getscl(adap); -	if (!sda) { -		printk(KERN_WARNING "%s: SDA stuck low!\n", name); +	if (adap->getsda && !getsda(adap)) { +		pr_warn("%s: SDA stuck low!\n", name);  		goto bailout;  	} -	if (!scl) { -		printk(KERN_WARNING -		       "%s: SCL unexpected low while pulling SDA high!\n", -		       name); +	if (adap->getscl && !getscl(adap)) { +		pr_warn("%s: SCL unexpected low while pulling SDA high!\n", name);  		goto bailout;  	}  	scllo(adap); -	sda = getsda(adap); -	scl = (adap->getscl == NULL) ? 0 : getscl(adap); -	if (scl) { -		printk(KERN_WARNING "%s: SCL stuck high!\n", name); +	if (adap->getscl && getscl(adap)) { +		pr_warn("%s: SCL stuck high!\n", name);  		goto bailout;  	} -	if (!sda) { -		printk(KERN_WARNING -		       "%s: SDA unexpected low while pulling SCL low!\n", -		       name); +	if (adap->getsda && !getsda(adap)) { +		pr_warn("%s: SDA unexpected low while pulling SCL low!\n", name);  		goto bailout;  	}  	sclhi(adap); -	sda = getsda(adap); -	scl = (adap->getscl == NULL) ? 1 : getscl(adap); -	if (!scl) { -		printk(KERN_WARNING "%s: SCL stuck low!\n", name); +	if (adap->getscl && !getscl(adap)) { +		pr_warn("%s: SCL stuck low!\n", name);  		goto bailout;  	} -	if (!sda) { -		printk(KERN_WARNING -		       "%s: SDA unexpected low while pulling SCL high!\n", -		       name); +	if (adap->getsda && !getsda(adap)) { +		pr_warn("%s: SDA unexpected low while pulling SCL high!\n", name);  		goto bailout;  	} @@ -420,6 +405,10 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)  	unsigned char *temp = msg->buf;  	int count = msg->len;  	const unsigned flags = msg->flags; +	struct i2c_algo_bit_data *adap = i2c_adap->algo_data; + +	if (!adap->getsda) +		return -EOPNOTSUPP;  	while (count > 0) {  		inval = i2c_inb(i2c_adap); @@ -670,11 +659,15 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,  	if (ret < 0)  		return ret; -	/* Complain if SCL can't be read */ -	if (bit_adap->getscl == NULL) { +	if (bit_adap->getsda == NULL) +		dev_warn(&adap->dev, "Not I2C compliant: can't read SDA\n"); + +	if (bit_adap->getscl == NULL)  		dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n"); + +	if (bit_adap->getsda == NULL || bit_adap->getscl == NULL)  		dev_warn(&adap->dev, "Bus may be unreliable\n"); -	} +  	return 0;  } diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index a7bfddf08fa7..25eb4e8fd22f 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -659,6 +659,13 @@ config I2C_GPIO_FAULT_INJECTOR  	  faults to an I2C bus, so another bus master can be stress-tested.  	  This is for debugging. If unsure, say 'no'. +config I2C_GXP +	tristate "GXP I2C Interface" +	depends on ARCH_HPE_GXP || COMPILE_TEST +	help +	  This enables support for GXP I2C interface. The I2C engines can be +	  either I2C master or I2C slaves. +  config I2C_HIGHLANDER  	tristate "Highlander FPGA SMBus interface"  	depends on SH_HIGHLANDER || COMPILE_TEST @@ -723,11 +730,11 @@ config I2C_IMX_LPI2C  	  will be called i2c-imx-lpi2c.  config I2C_IOP3XX -	tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" -	depends on ARCH_IOP32X || ARCH_IXP4XX || COMPILE_TEST +	tristate "Intel IXP4xx on-chip I2C interface" +	depends on ARCH_IXP4XX || COMPILE_TEST  	help  	  Say Y here if you want to use the IIC bus controller on -	  the Intel IOPx3xx I/O Processors or IXP4xx Network Processors. +	  the Intel IXP4xx Network Processors.  	  This driver can also be built as a module.  If so, the module  	  will be called i2c-iop3xx. @@ -761,6 +768,17 @@ config I2C_LPC2K  	  This driver can also be built as a module.  If so, the module  	  will be called i2c-lpc2k. +config I2C_LS2X +	tristate "Loongson LS2X I2C adapter" +	depends on MACH_LOONGSON64 || COMPILE_TEST +	help +	  If you say yes to this option, support will be included for the +	  I2C interface on the Loongson-2K SoCs and Loongson LS7A bridge +	  chip. + +	  This driver can also be built as a module. If so, the module +	  will be called i2c-ls2x. +  config I2C_MLXBF          tristate "Mellanox BlueField I2C controller"          depends on MELLANOX_PLATFORM && ARM64 @@ -874,7 +892,7 @@ config I2C_OCORES  config I2C_OMAP  	tristate "OMAP I2C adapter"  	depends on ARCH_OMAP || ARCH_K3 || COMPILE_TEST -	default y if MACH_OMAP_H3 || MACH_OMAP_OSK +	default MACH_OMAP_OSK  	help  	  If you say yes to this option, support will be included for the  	  I2C interface on the Texas Instruments OMAP1/2 family of processors. @@ -896,6 +914,7 @@ config I2C_PASEMI  config I2C_APPLE  	tristate "Apple SMBus platform driver" +	depends on !I2C_PASEMI  	depends on ARCH_APPLE || COMPILE_TEST  	default ARCH_APPLE  	help @@ -1010,8 +1029,7 @@ config I2C_RZV2M  config I2C_S3C2410  	tristate "S3C/Exynos I2C Driver" -	depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || \ -		   ARCH_S5PV210 || COMPILE_TEST +	depends on ARCH_EXYNOS || ARCH_S3C64XX || ARCH_S5PV210 || COMPILE_TEST  	help  	  Say Y here to include support for I2C controller in the  	  Samsung SoCs (S3C, S5Pv210, Exynos). diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index e73cdb1d2b5a..af56fe2c75c0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o  obj-$(CONFIG_I2C_JZ4780)	+= i2c-jz4780.o  obj-$(CONFIG_I2C_KEMPLD)	+= i2c-kempld.o  obj-$(CONFIG_I2C_LPC2K)		+= i2c-lpc2k.o +obj-$(CONFIG_I2C_LS2X)		+= i2c-ls2x.o  obj-$(CONFIG_I2C_MESON)		+= i2c-meson.o  obj-$(CONFIG_I2C_MICROCHIP_CORE)	+= i2c-microchip-corei2c.o  obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o @@ -127,6 +128,7 @@ obj-$(CONFIG_I2C_THUNDERX)	+= i2c-thunderx.o  obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o  obj-$(CONFIG_I2C_XLP9XX)	+= i2c-xlp9xx.o  obj-$(CONFIG_I2C_RCAR)		+= i2c-rcar.o +obj-$(CONFIG_I2C_GXP)		+= i2c-gxp.o  # External I2C/SMBus adapter drivers  obj-$(CONFIG_I2C_DIOLAN_U2C)	+= i2c-diolan-u2c.o diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index c64c381b69b7..d3c99c5b3247 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -979,15 +979,13 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)  	const struct of_device_id *match;  	struct aspeed_i2c_bus *bus;  	struct clk *parent_clk; -	struct resource *res;  	int irq, ret;  	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);  	if (!bus)  		return -ENOMEM; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	bus->base = devm_ioremap_resource(&pdev->dev, res); +	bus->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);  	if (IS_ERR(bus->base))  		return PTR_ERR(bus->base); diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index 99bd24d0e6a5..7b42d35b1294 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -302,7 +302,6 @@ static int  i2c_au1550_probe(struct platform_device *pdev)  {  	struct i2c_au1550_data *priv; -	struct resource *r;  	int ret;  	priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_au1550_data), @@ -310,8 +309,7 @@ i2c_au1550_probe(struct platform_device *pdev)  	if (!priv)  		return -ENOMEM; -	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	priv->psc_base = devm_ioremap_resource(&pdev->dev, r); +	priv->psc_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);  	if (IS_ERR(priv->psc_base))  		return PTR_ERR(priv->psc_base); diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index bdf3b50de8ad..c1c74ce08407 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -118,7 +118,7 @@  #define SDA_HOLD_TIME		0x90  /** - * axxia_i2c_dev - I2C device context + * struct axxia_i2c_dev - I2C device context   * @base: pointer to register struct   * @msg: pointer to current message   * @msg_r: pointer to current read message (sequence transfer) diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index f72c6576d8a3..09a077b31bfe 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -407,7 +407,6 @@ static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {  static int bcm2835_i2c_probe(struct platform_device *pdev)  {  	struct bcm2835_i2c_dev *i2c_dev; -	struct resource *mem;  	int ret;  	struct i2c_adapter *adap;  	struct clk *mclk; @@ -420,8 +419,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)  	i2c_dev->dev = &pdev->dev;  	init_completion(&i2c_dev->completion); -	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	i2c_dev->regs = devm_ioremap_resource(&pdev->dev, mem); +	i2c_dev->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);  	if (IS_ERR(i2c_dev->regs))  		return PTR_ERR(i2c_dev->regs); diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index f58943cb1341..b5d22e7282c2 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -115,8 +115,6 @@  #define CNDS_I2C_PM_TIMEOUT		1000	/* ms */  #define CDNS_I2C_FIFO_DEPTH		16 -/* FIFO depth at which the DATA interrupt occurs */ -#define CDNS_I2C_DATA_INTR_DEPTH	(CDNS_I2C_FIFO_DEPTH - 2)  #define CDNS_I2C_MAX_TRANSFER_SIZE	255  /* Transfer size in multiples of data interrupt depth */  #define CDNS_I2C_TRANSFER_SIZE	(CDNS_I2C_MAX_TRANSFER_SIZE - 3) @@ -175,7 +173,6 @@ enum cdns_i2c_slave_state {   * @send_count:		Number of bytes still expected to send   * @recv_count:		Number of bytes still expected to receive   * @curr_recv_count:	Number of bytes to be received in current transfer - * @irq:		IRQ number   * @input_clk:		Input clock to I2C controller   * @i2c_clk:		Maximum I2C clock speed   * @bus_hold_flag:	Flag used in repeated start for clearing HOLD bit @@ -200,7 +197,6 @@ struct cdns_i2c {  	unsigned int send_count;  	unsigned int recv_count;  	unsigned int curr_recv_count; -	int irq;  	unsigned long input_clk;  	unsigned int i2c_clk;  	unsigned int bus_hold_flag; @@ -616,9 +612,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)  	}  	/* Determine hold_clear based on number of bytes to receive and hold flag */ -	if (!id->bus_hold_flag && -	    ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) && -	    (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) { +	if (!id->bus_hold_flag && id->recv_count <= CDNS_I2C_FIFO_DEPTH) {  		if (cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & CDNS_I2C_CR_HOLD) {  			hold_clear = true;  			if (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) @@ -1246,7 +1240,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)  {  	struct resource *r_mem;  	struct cdns_i2c *id; -	int ret; +	int ret, irq;  	const struct of_device_id *match;  	id = devm_kzalloc(&pdev->dev, sizeof(*id), GFP_KERNEL); @@ -1277,10 +1271,9 @@ static int cdns_i2c_probe(struct platform_device *pdev)  	if (IS_ERR(id->membase))  		return PTR_ERR(id->membase); -	ret = platform_get_irq(pdev, 0); -	if (ret < 0) -		return ret; -	id->irq = ret; +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) +		return irq;  	id->adap.owner = THIS_MODULE;  	id->adap.dev.of_node = pdev->dev.of_node; @@ -1331,10 +1324,10 @@ static int cdns_i2c_probe(struct platform_device *pdev)  		goto err_clk_dis;  	} -	ret = devm_request_irq(&pdev->dev, id->irq, cdns_i2c_isr, 0, +	ret = devm_request_irq(&pdev->dev, irq, cdns_i2c_isr, 0,  				 DRIVER_NAME, id);  	if (ret) { -		dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); +		dev_err(&pdev->dev, "cannot get irq %d\n", irq);  		goto err_clk_dis;  	}  	cdns_i2c_init(id); @@ -1344,7 +1337,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)  		goto err_clk_dis;  	dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n", -		 id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq); +		 id->i2c_clk / 1000, (unsigned long)r_mem->start, irq);  	return 0; diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 190abdc46dd3..2b2c3d090089 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -380,6 +380,49 @@ static struct i2c_board_info lenovo_yogabook1_board_info = {  	.platform_data = &bq2589x_pdata,  }; +/********** Lenovo Yogabook YT3-X90F charger settings **********/ +static const char * const lenovo_yt3_bq25892_1_suppliers[] = { "cht_wcove_pwrsrc" }; + +/* + * bq25892 charger settings for the round li-ion cells in the hinge, + * this is the main / biggest battery. + */ +static const struct property_entry lenovo_yt3_bq25892_1_props[] = { +	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_1_suppliers), +	PROPERTY_ENTRY_STRING("linux,secondary-charger-name", "bq25890-charger-0"), +	PROPERTY_ENTRY_U32("linux,iinlim-percentage", 60), +	PROPERTY_ENTRY_U32("linux,pump-express-vbus-max", 12000000), +	PROPERTY_ENTRY_BOOL("linux,skip-reset"), +	/* +	 * The firmware sets everything to the defaults, leading to a low(ish) +	 * charge-current and battery-voltage of 2048mA resp 4.2V. Use the +	 * Android values instead of "linux,read-back-settings" to fix this. +	 */ +	PROPERTY_ENTRY_U32("ti,charge-current", 3072000), +	PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000), +	PROPERTY_ENTRY_U32("ti,termination-current", 128000), +	PROPERTY_ENTRY_U32("ti,precharge-current", 128000), +	PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000), +	PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"), +	/* Set 5V boost current-limit to 1.2A (MAX/POR values are 2.45A/1.4A) */ +	PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000), +	PROPERTY_ENTRY_U32("ti,boost-max-current", 1200000), +	{ } +}; + +static const struct software_node lenovo_yt3_bq25892_1_node = { +	.properties = lenovo_yt3_bq25892_1_props, +}; + +/* bq25892 charger for the round li-ion cells in the hinge */ +static struct i2c_board_info lenovo_yoga_tab3_board_info = { +	.type = "bq25892", +	.addr = 0x6b, +	.dev_name = "bq25892_1", +	.swnode = &lenovo_yt3_bq25892_1_node, +	.platform_data = &bq2589x_pdata, +}; +  static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)  {  	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); @@ -459,6 +502,9 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)  	case INTEL_CHT_WC_LENOVO_YOGABOOK1:  		board_info = &lenovo_yogabook1_board_info;  		break; +	case INTEL_CHT_WC_LENOVO_YT3_X90: +		board_info = &lenovo_yoga_tab3_board_info; +		break;  	default:  		dev_warn(&pdev->dev, "Unknown model, not instantiating charger device\n");  		break; diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c index a3240ece55b2..0dc6b1ce663f 100644 --- a/drivers/i2c/busses/i2c-designware-common.c +++ b/drivers/i2c/busses/i2c-designware-common.c @@ -351,7 +351,8 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)  		 *  		 * If your hardware is free from tHD;STA issue, try this one.  		 */ -		return DIV_ROUND_CLOSEST(ic_clk * tSYMBOL, MICRO) - 8 + offset; +		return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * tSYMBOL, MICRO) - +		       8 + offset;  	else  		/*  		 * Conditional expression: @@ -367,7 +368,8 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)  		 * The reason why we need to take into account "tf" here,  		 * is the same as described in i2c_dw_scl_lcnt().  		 */ -		return DIV_ROUND_CLOSEST(ic_clk * (tSYMBOL + tf), MICRO) - 3 + offset; +		return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tSYMBOL + tf), MICRO) - +		       3 + offset;  }  u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) @@ -383,12 +385,13 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)  	 * account the fall time of SCL signal (tf).  Default tf value  	 * should be 0.3 us, for safety.  	 */ -	return DIV_ROUND_CLOSEST(ic_clk * (tLOW + tf), MICRO) - 1 + offset; +	return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tLOW + tf), MICRO) - +	       1 + offset;  }  int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)  { -	u32 reg; +	unsigned int reg;  	int ret;  	ret = i2c_dw_acquire_lock(dev); @@ -439,7 +442,7 @@ err_release_lock:  void __i2c_dw_disable(struct dw_i2c_dev *dev)  {  	int timeout = 100; -	u32 status; +	unsigned int status;  	do {  		__i2c_dw_disable_nowait(dev); @@ -462,7 +465,7 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)  	dev_warn(dev->dev, "timeout in disabling adapter\n");  } -unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev) +u32 i2c_dw_clk_rate(struct dw_i2c_dev *dev)  {  	/*  	 * Clock is not necessary if we got LCNT/HCNT values directly from @@ -524,7 +527,7 @@ void i2c_dw_release_lock(struct dw_i2c_dev *dev)   */  int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)  { -	u32 status; +	unsigned int status;  	int ret;  	ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status, @@ -568,7 +571,8 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)  int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)  { -	u32 param, tx_fifo_depth, rx_fifo_depth; +	u32 tx_fifo_depth, rx_fifo_depth; +	unsigned int param;  	int ret;  	/* @@ -608,7 +612,7 @@ u32 i2c_dw_func(struct i2c_adapter *adap)  void i2c_dw_disable(struct dw_i2c_dev *dev)  { -	u32 dummy; +	unsigned int dummy;  	int ret;  	ret = i2c_dw_acquire_lock(dev); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 95ebc5eaa5d1..050d8c63ad3c 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -37,6 +37,7 @@  #define DW_IC_CON_STOP_DET_IFADDRESSED		BIT(7)  #define DW_IC_CON_TX_EMPTY_CTRL			BIT(8)  #define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL		BIT(9) +#define DW_IC_CON_BUS_CLEAR_CTRL		BIT(11)  #define DW_IC_DATA_CMD_DAT			GENMASK(7, 0) @@ -264,7 +265,7 @@ struct dw_i2c_dev {  	u8			*rx_buf;  	int			msg_err;  	unsigned int		status; -	u32			abort_source; +	unsigned int		abort_source;  	int			irq;  	u32			flags;  	struct i2c_adapter	adapter; @@ -320,7 +321,7 @@ int i2c_dw_init_regmap(struct dw_i2c_dev *dev);  u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);  u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);  int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev); -unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev); +u32 i2c_dw_clk_rate(struct dw_i2c_dev *dev);  int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);  int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);  void i2c_dw_release_lock(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 45f569155bfe..55ea91a63382 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -39,7 +39,7 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)  static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)  { -	u32 comp_param1; +	unsigned int comp_param1;  	u32 sda_falling_time, scl_falling_time;  	struct i2c_timings *t = &dev->timings;  	const char *fp_str = ""; @@ -211,7 +211,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)  {  	struct i2c_msg *msgs = dev->msgs;  	u32 ic_con = 0, ic_tar = 0; -	u32 dummy; +	unsigned int dummy;  	/* Disable the adapter */  	__i2c_dw_disable(dev); @@ -287,7 +287,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,  	int msg_wrt_idx, msg_itr_lmt, buf_len, data_idx;  	int cmd = 0, status;  	u8 *tx_buf; -	u32 val; +	unsigned int val;  	/*  	 * In order to enable the interrupt for UCSI i.e. AMD NAVI GPU card, @@ -505,7 +505,8 @@ i2c_dw_read(struct dw_i2c_dev *dev)  	unsigned int rx_valid;  	for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) { -		u32 len, tmp; +		unsigned int tmp; +		u32 len;  		u8 *buf;  		if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) @@ -653,7 +654,7 @@ static const struct i2c_adapter_quirks i2c_dw_quirks = {  static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)  { -	u32 stat, dummy; +	unsigned int stat, dummy;  	/*  	 * The IC_INTR_STAT register just indicates "enabled" interrupts. @@ -714,7 +715,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)  static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)  {  	struct dw_i2c_dev *dev = dev_id; -	u32 stat, enabled; +	unsigned int stat, enabled;  	regmap_read(dev->map, DW_IC_ENABLE, &enabled);  	regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat); @@ -865,6 +866,7 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)  {  	struct i2c_adapter *adap = &dev->adapter;  	unsigned long irq_flags; +	unsigned int ic_con;  	int ret;  	init_completion(&dev->cmd_complete); @@ -884,6 +886,25 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)  	if (ret)  		return ret; +	/* Lock the bus for accessing DW_IC_CON */ +	ret = i2c_dw_acquire_lock(dev); +	if (ret) +		return ret; + +	/* +	 * On AMD platforms BIOS advertises the bus clear feature +	 * and enables the SCL/SDA stuck low. SMU FW does the +	 * bus recovery process. Driver should not ignore this BIOS +	 * advertisement of bus clear feature. +	 */ +	ret = regmap_read(dev->map, DW_IC_CON, &ic_con); +	i2c_dw_release_lock(dev); +	if (ret) +		return ret; + +	if (ic_con & DW_IC_CON_BUS_CLEAR_CTRL) +		dev->master_cfg |= DW_IC_CON_BUS_CLEAR_CTRL; +  	ret = dev->init(dev);  	if (ret)  		return ret; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index e499f96506c5..782fe1ef3ca1 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -396,6 +396,8 @@ static const struct pci_device_id i2_designware_pci_ids[] = {  	{ PCI_VDEVICE(ATI,  0x73a4), navi_amd },  	{ PCI_VDEVICE(ATI,  0x73e4), navi_amd },  	{ PCI_VDEVICE(ATI,  0x73c4), navi_amd }, +	{ PCI_VDEVICE(ATI,  0x7444), navi_amd }, +	{ PCI_VDEVICE(ATI,  0x7464), navi_amd },  	{ 0,}  };  MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index ba043b547393..74182db03a88 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -351,13 +351,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)  	if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {  		dev_pm_set_driver_flags(&pdev->dev, -					DPM_FLAG_SMART_PREPARE | -					DPM_FLAG_MAY_SKIP_RESUME); +					DPM_FLAG_SMART_PREPARE);  	} else {  		dev_pm_set_driver_flags(&pdev->dev,  					DPM_FLAG_SMART_PREPARE | -					DPM_FLAG_SMART_SUSPEND | -					DPM_FLAG_MAY_SKIP_RESUME); +					DPM_FLAG_SMART_SUSPEND);  	}  	device_enable_async_suspend(&pdev->dev); @@ -419,21 +417,8 @@ static int dw_i2c_plat_prepare(struct device *dev)  	 */  	return !has_acpi_companion(dev);  } - -static void dw_i2c_plat_complete(struct device *dev) -{ -	/* -	 * The device can only be in runtime suspend at this point if it has not -	 * been resumed throughout the ending system suspend/resume cycle, so if -	 * the platform firmware might mess up with it, request the runtime PM -	 * framework to resume it. -	 */ -	if (pm_runtime_suspended(dev) && pm_resume_via_firmware()) -		pm_request_resume(dev); -}  #else  #define dw_i2c_plat_prepare	NULL -#define dw_i2c_plat_complete	NULL  #endif  #ifdef CONFIG_PM @@ -483,7 +468,6 @@ static int __maybe_unused dw_i2c_plat_resume(struct device *dev)  static const struct dev_pm_ops dw_i2c_dev_pm_ops = {  	.prepare = dw_i2c_plat_prepare, -	.complete = dw_i2c_plat_complete,  	SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)  	SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, dw_i2c_plat_runtime_resume, NULL)  }; diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index c6d2e4c2ac23..cec25054bb24 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -98,7 +98,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)  static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)  { -	u32 stat, dummy; +	unsigned int stat, dummy;  	/*  	 * The IC_INTR_STAT register just indicates "enabled" interrupts. @@ -150,7 +150,7 @@ static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)  static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)  {  	struct dw_i2c_dev *dev = dev_id; -	u32 raw_stat, stat, enabled, tmp; +	unsigned int raw_stat, stat, enabled, tmp;  	u8 val = 0, slave_activity;  	regmap_read(dev->map, DW_IC_ENABLE, &enabled); diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 0e4385a9bcf7..1794c0399f22 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -13,9 +13,9 @@  #include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/module.h> -#include <linux/of.h>  #include <linux/platform_data/i2c-gpio.h>  #include <linux/platform_device.h> +#include <linux/property.h>  #include <linux/slab.h>  struct i2c_gpio_private_data { @@ -300,22 +300,29 @@ static inline void i2c_gpio_fault_injector_init(struct platform_device *pdev) {}  static inline void i2c_gpio_fault_injector_exit(struct platform_device *pdev) {}  #endif /* CONFIG_I2C_GPIO_FAULT_INJECTOR*/ -static void of_i2c_gpio_get_props(struct device_node *np, -				  struct i2c_gpio_platform_data *pdata) +/* Get i2c-gpio properties from DT or ACPI table */ +static void i2c_gpio_get_properties(struct device *dev, +				    struct i2c_gpio_platform_data *pdata)  {  	u32 reg; -	of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); +	device_property_read_u32(dev, "i2c-gpio,delay-us", &pdata->udelay); -	if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) +	if (!device_property_read_u32(dev, "i2c-gpio,timeout-ms", ®))  		pdata->timeout = msecs_to_jiffies(reg);  	pdata->sda_is_open_drain = -		of_property_read_bool(np, "i2c-gpio,sda-open-drain"); +		device_property_read_bool(dev, "i2c-gpio,sda-open-drain");  	pdata->scl_is_open_drain = -		of_property_read_bool(np, "i2c-gpio,scl-open-drain"); +		device_property_read_bool(dev, "i2c-gpio,scl-open-drain");  	pdata->scl_is_output_only = -		of_property_read_bool(np, "i2c-gpio,scl-output-only"); +		device_property_read_bool(dev, "i2c-gpio,scl-output-only"); +	pdata->sda_is_output_only = +		device_property_read_bool(dev, "i2c-gpio,sda-output-only"); +	pdata->sda_has_no_pullup = +		device_property_read_bool(dev, "i2c-gpio,sda-has-no-pullup"); +	pdata->scl_has_no_pullup = +		device_property_read_bool(dev, "i2c-gpio,scl-has-no-pullup");  }  static struct gpio_desc *i2c_gpio_get_desc(struct device *dev, @@ -361,7 +368,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	struct i2c_algo_bit_data *bit_data;  	struct i2c_adapter *adap;  	struct device *dev = &pdev->dev; -	struct device_node *np = dev->of_node; +	struct fwnode_handle *fwnode = dev_fwnode(dev);  	enum gpiod_flags gflags;  	int ret; @@ -373,8 +380,8 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	bit_data = &priv->bit_data;  	pdata = &priv->pdata; -	if (np) { -		of_i2c_gpio_get_props(np, pdata); +	if (fwnode) { +		i2c_gpio_get_properties(dev, pdata);  	} else {  		/*  		 * If all platform data settings are zero it is OK @@ -392,7 +399,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	 * handle them as we handle any other output. Else we enforce open  	 * drain as this is required for an I2C bus.  	 */ -	if (pdata->sda_is_open_drain) +	if (pdata->sda_is_open_drain || pdata->sda_has_no_pullup)  		gflags = GPIOD_OUT_HIGH;  	else  		gflags = GPIOD_OUT_HIGH_OPEN_DRAIN; @@ -400,7 +407,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	if (IS_ERR(priv->sda))  		return PTR_ERR(priv->sda); -	if (pdata->scl_is_open_drain) +	if (pdata->scl_is_open_drain || pdata->scl_has_no_pullup)  		gflags = GPIOD_OUT_HIGH;  	else  		gflags = GPIOD_OUT_HIGH_OPEN_DRAIN; @@ -418,7 +425,8 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	if (!pdata->scl_is_output_only)  		bit_data->getscl = i2c_gpio_getscl; -	bit_data->getsda = i2c_gpio_getsda; +	if (!pdata->sda_is_output_only) +		bit_data->getsda = i2c_gpio_getsda;  	if (pdata->udelay)  		bit_data->udelay = pdata->udelay; @@ -435,7 +443,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	bit_data->data = priv;  	adap->owner = THIS_MODULE; -	if (np) +	if (fwnode)  		strscpy(adap->name, dev_name(dev), sizeof(adap->name));  	else  		snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); @@ -443,7 +451,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	adap->algo_data = bit_data;  	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;  	adap->dev.parent = dev; -	adap->dev.of_node = np; +	device_set_node(&adap->dev, fwnode);  	adap->nr = pdev->id;  	ret = i2c_bit_add_numbered_bus(adap); @@ -489,10 +497,17 @@ static const struct of_device_id i2c_gpio_dt_ids[] = {  MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); +static const struct acpi_device_id i2c_gpio_acpi_match[] = { +	{ "LOON0005" }, /* LoongArch */ +	{ } +}; +MODULE_DEVICE_TABLE(acpi, i2c_gpio_acpi_match); +  static struct platform_driver i2c_gpio_driver = {  	.driver		= {  		.name	= "i2c-gpio",  		.of_match_table	= i2c_gpio_dt_ids, +		.acpi_match_table = i2c_gpio_acpi_match,  	},  	.probe		= i2c_gpio_probe,  	.remove		= i2c_gpio_remove, diff --git a/drivers/i2c/busses/i2c-gxp.c b/drivers/i2c/busses/i2c-gxp.c new file mode 100644 index 000000000000..d4b55d989a26 --- /dev/null +++ b/drivers/i2c/busses/i2c-gxp.c @@ -0,0 +1,611 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */ + +#include <linux/err.h> +#include <linux/io.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> + +#define GXP_MAX_I2C_ENGINE 10 +static const char * const gxp_i2c_name[] = { +	"gxp-i2c0", "gxp-i2c1", "gxp-i2c2", "gxp-i2c3", +	"gxp-i2c4", "gxp-i2c5", "gxp-i2c6", "gxp-i2c7", +	"gxp-i2c8", "gxp-i2c9" }; + +/* GXP I2C Global interrupt status/enable register*/ +#define GXP_I2CINTSTAT		0x00 +#define GXP_I2CINTEN		0x04 + +/* GXP I2C registers */ +#define GXP_I2CSTAT		0x00 +#define MASK_STOP_EVENT		0x20 +#define MASK_ACK		0x08 +#define MASK_RW			0x04 +#define GXP_I2CEVTERR		0x01 +#define MASK_SLAVE_CMD_EVENT	0x01 +#define MASK_SLAVE_DATA_EVENT	0x02 +#define MASK_MASTER_EVENT	0x10 +#define GXP_I2CSNPDAT		0x02 +#define GXP_I2CMCMD		0x04 +#define GXP_I2CSCMD		0x06 +#define GXP_I2CSNPAA		0x09 +#define GXP_I2CADVFEAT		0x0A +#define GXP_I2COWNADR		0x0B +#define GXP_I2CFREQDIV		0x0C +#define GXP_I2CFLTFAIR		0x0D +#define GXP_I2CTMOEDG		0x0E +#define GXP_I2CCYCTIM		0x0F + +/* I2CSCMD Bits */ +#define SNOOP_EVT_CLR		0x80 +#define SLAVE_EVT_CLR		0x40 +#define	SNOOP_EVT_MASK		0x20 +#define SLAVE_EVT_MASK		0x10 +#define SLAVE_ACK_ENAB		0x08 +#define SLAVE_EVT_STALL		0x01 + +/* I2CMCMD Bits */ +#define MASTER_EVT_CLR		0x80 +#define MASTER_ACK_ENAB		0x08 +#define RW_CMD			0x04 +#define STOP_CMD		0x02 +#define START_CMD		0x01 + +/* I2CTMOEDG value */ +#define GXP_DATA_EDGE_RST_CTRL	0x0a /* 30ns */ + +/* I2CFLTFAIR Bits */ +#define FILTER_CNT		0x30 +#define FAIRNESS_CNT		0x02 + +enum { +	GXP_I2C_IDLE = 0, +	GXP_I2C_ADDR_PHASE, +	GXP_I2C_RDATA_PHASE, +	GXP_I2C_WDATA_PHASE, +	GXP_I2C_ADDR_NACK, +	GXP_I2C_DATA_NACK, +	GXP_I2C_ERROR, +	GXP_I2C_COMP +}; + +struct gxp_i2c_drvdata { +	struct device *dev; +	void __iomem *base; +	struct i2c_timings t; +	u32 engine; +	int irq; +	struct completion completion; +	struct i2c_adapter adapter; +	struct i2c_msg *curr_msg; +	int msgs_remaining; +	int msgs_num; +	u8 *buf; +	size_t buf_remaining; +	unsigned char state; +	struct i2c_client *slave; +	unsigned char stopped; +}; + +static struct regmap *i2cg_map; + +static void gxp_i2c_start(struct gxp_i2c_drvdata *drvdata) +{ +	u16 value; + +	drvdata->buf = drvdata->curr_msg->buf; +	drvdata->buf_remaining = drvdata->curr_msg->len; + +	/* Note: Address in struct i2c_msg is 7 bits */ +	value = drvdata->curr_msg->addr << 9; + +	/* Read or Write */ +	value |= drvdata->curr_msg->flags & I2C_M_RD ? RW_CMD | START_CMD : START_CMD; + +	drvdata->state = GXP_I2C_ADDR_PHASE; +	writew(value, drvdata->base + GXP_I2CMCMD); +} + +static int gxp_i2c_master_xfer(struct i2c_adapter *adapter, +			       struct i2c_msg *msgs, int num) +{ +	int ret; +	struct gxp_i2c_drvdata *drvdata = i2c_get_adapdata(adapter); +	unsigned long time_left; + +	drvdata->msgs_remaining = num; +	drvdata->curr_msg = msgs; +	drvdata->msgs_num = num; +	reinit_completion(&drvdata->completion); + +	gxp_i2c_start(drvdata); + +	time_left = wait_for_completion_timeout(&drvdata->completion, +						adapter->timeout); +	ret = num - drvdata->msgs_remaining; +	if (time_left == 0) +		return -ETIMEDOUT; + +	if (drvdata->state == GXP_I2C_ADDR_NACK) +		return -ENXIO; + +	if (drvdata->state == GXP_I2C_DATA_NACK) +		return -EIO; + +	return ret; +} + +static u32 gxp_i2c_func(struct i2c_adapter *adap) +{ +	if (IS_ENABLED(CONFIG_I2C_SLAVE)) +		return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE; + +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +#if IS_ENABLED(CONFIG_I2C_SLAVE) +static int gxp_i2c_reg_slave(struct i2c_client *slave) +{ +	struct gxp_i2c_drvdata *drvdata = i2c_get_adapdata(slave->adapter); + +	if (drvdata->slave) +		return -EBUSY; + +	if (slave->flags & I2C_CLIENT_TEN) +		return -EAFNOSUPPORT; + +	drvdata->slave = slave; + +	writeb(slave->addr << 1, drvdata->base + GXP_I2COWNADR); +	writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK | SLAVE_ACK_ENAB | +	       SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD); + +	return 0; +} + +static int gxp_i2c_unreg_slave(struct i2c_client *slave) +{ +	struct gxp_i2c_drvdata *drvdata = i2c_get_adapdata(slave->adapter); + +	WARN_ON(!drvdata->slave); + +	writeb(0x00, drvdata->base + GXP_I2COWNADR); +	writeb(SNOOP_EVT_CLR | SLAVE_EVT_CLR | SNOOP_EVT_MASK | +	       SLAVE_EVT_MASK, drvdata->base + GXP_I2CSCMD); + +	drvdata->slave = NULL; + +	return 0; +} +#endif + +static const struct i2c_algorithm gxp_i2c_algo = { +	.master_xfer   = gxp_i2c_master_xfer, +	.functionality = gxp_i2c_func, +#if IS_ENABLED(CONFIG_I2C_SLAVE) +	.reg_slave     = gxp_i2c_reg_slave, +	.unreg_slave   = gxp_i2c_unreg_slave, +#endif +}; + +static void gxp_i2c_stop(struct gxp_i2c_drvdata *drvdata) +{ +	/* Clear event and send stop */ +	writeb(MASTER_EVT_CLR | STOP_CMD, drvdata->base + GXP_I2CMCMD); + +	complete(&drvdata->completion); +} + +static void gxp_i2c_restart(struct gxp_i2c_drvdata *drvdata) +{ +	u16 value; + +	drvdata->buf = drvdata->curr_msg->buf; +	drvdata->buf_remaining = drvdata->curr_msg->len; + +	value = drvdata->curr_msg->addr << 9; + +	if (drvdata->curr_msg->flags & I2C_M_RD) { +		/* Read and clear master event */ +		value |= MASTER_EVT_CLR | RW_CMD | START_CMD; +	} else { +		/* Write and clear master event */ +		value |= MASTER_EVT_CLR | START_CMD; +	} + +	drvdata->state = GXP_I2C_ADDR_PHASE; + +	writew(value, drvdata->base + GXP_I2CMCMD); +} + +static void gxp_i2c_chk_addr_ack(struct gxp_i2c_drvdata *drvdata) +{ +	u16 value; + +	value = readb(drvdata->base + GXP_I2CSTAT); +	if (!(value & MASK_ACK)) { +		/* Got no ack, stop */ +		drvdata->state = GXP_I2C_ADDR_NACK; +		gxp_i2c_stop(drvdata); +		return; +	} + +	if (drvdata->curr_msg->flags & I2C_M_RD) { +		/* Start to read data from slave */ +		if (drvdata->buf_remaining == 0) { +			/* No more data to read, stop */ +			drvdata->msgs_remaining--; +			drvdata->state = GXP_I2C_COMP; +			gxp_i2c_stop(drvdata); +			return; +		} +		drvdata->state = GXP_I2C_RDATA_PHASE; + +		if (drvdata->buf_remaining == 1) { +			/* The last data, do not ack */ +			writeb(MASTER_EVT_CLR | RW_CMD, +			       drvdata->base + GXP_I2CMCMD); +		} else { +			/* Read data and ack it */ +			writeb(MASTER_EVT_CLR | MASTER_ACK_ENAB | +			       RW_CMD, drvdata->base + GXP_I2CMCMD); +		} +	} else { +		/* Start to write first data to slave */ +		if (drvdata->buf_remaining == 0) { +			/* No more data to write, stop */ +			drvdata->msgs_remaining--; +			drvdata->state = GXP_I2C_COMP; +			gxp_i2c_stop(drvdata); +			return; +		} +		value = *drvdata->buf; +		value = value << 8; +		/* Clear master event */ +		value |= MASTER_EVT_CLR; +		drvdata->buf++; +		drvdata->buf_remaining--; +		drvdata->state = GXP_I2C_WDATA_PHASE; +		writew(value, drvdata->base + GXP_I2CMCMD); +	} +} + +static void gxp_i2c_ack_data(struct gxp_i2c_drvdata *drvdata) +{ +	u8 value; + +	/* Store the data returned */ +	value = readb(drvdata->base + GXP_I2CSNPDAT); +	*drvdata->buf = value; +	drvdata->buf++; +	drvdata->buf_remaining--; + +	if (drvdata->buf_remaining == 0) { +		/* No more data, this message is completed. */ +		drvdata->msgs_remaining--; + +		if (drvdata->msgs_remaining == 0) { +			/* No more messages, stop */ +			drvdata->state = GXP_I2C_COMP; +			gxp_i2c_stop(drvdata); +			return; +		} +		/* Move to next message and start transfer */ +		drvdata->curr_msg++; +		gxp_i2c_restart(drvdata); +		return; +	} + +	/* Ack the slave to make it send next byte */ +	drvdata->state = GXP_I2C_RDATA_PHASE; +	if (drvdata->buf_remaining == 1) { +		/* The last data, do not ack */ +		writeb(MASTER_EVT_CLR | RW_CMD, +		       drvdata->base + GXP_I2CMCMD); +	} else { +		/* Read data and ack it */ +		writeb(MASTER_EVT_CLR | MASTER_ACK_ENAB | +		       RW_CMD, drvdata->base + GXP_I2CMCMD); +	} +} + +static void gxp_i2c_chk_data_ack(struct gxp_i2c_drvdata *drvdata) +{ +	u16 value; + +	value = readb(drvdata->base + GXP_I2CSTAT); +	if (!(value & MASK_ACK)) { +		/* Received No ack, stop */ +		drvdata->state = GXP_I2C_DATA_NACK; +		gxp_i2c_stop(drvdata); +		return; +	} + +	/* Got ack, check if there is more data to write */ +	if (drvdata->buf_remaining == 0) { +		/* No more data, this message is completed */ +		drvdata->msgs_remaining--; + +		if (drvdata->msgs_remaining == 0) { +			/* No more messages, stop */ +			drvdata->state = GXP_I2C_COMP; +			gxp_i2c_stop(drvdata); +			return; +		} +		/* Move to next message and start transfer */ +		drvdata->curr_msg++; +		gxp_i2c_restart(drvdata); +		return; +	} + +	/* Write data to slave */ +	value = *drvdata->buf; +	value = value << 8; + +	/* Clear master event */ +	value |= MASTER_EVT_CLR; +	drvdata->buf++; +	drvdata->buf_remaining--; +	drvdata->state = GXP_I2C_WDATA_PHASE; +	writew(value, drvdata->base + GXP_I2CMCMD); +} + +#if IS_ENABLED(CONFIG_I2C_SLAVE) +static bool gxp_i2c_slave_irq_handler(struct gxp_i2c_drvdata *drvdata) +{ +	u8 value; +	u8 buf; +	int ret; + +	value = readb(drvdata->base + GXP_I2CEVTERR); + +	/* Received start or stop event */ +	if (value & MASK_SLAVE_CMD_EVENT) { +		value = readb(drvdata->base + GXP_I2CSTAT); +		/* Master sent stop */ +		if (value & MASK_STOP_EVENT) { +			if (drvdata->stopped == 0) +				i2c_slave_event(drvdata->slave, I2C_SLAVE_STOP, &buf); +			writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK | +			       SLAVE_ACK_ENAB | SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD); +			drvdata->stopped = 1; +		} else { +			/* Master sent start and  wants to read */ +			drvdata->stopped = 0; +			if (value & MASK_RW) { +				i2c_slave_event(drvdata->slave, +						I2C_SLAVE_READ_REQUESTED, &buf); +				value = buf << 8 | (SLAVE_EVT_CLR | SNOOP_EVT_MASK | +						    SLAVE_EVT_STALL); +				writew(value, drvdata->base + GXP_I2CSCMD); +			} else { +				/* Master wants to write to us */ +				ret = i2c_slave_event(drvdata->slave, +						      I2C_SLAVE_WRITE_REQUESTED, &buf); +				if (!ret) { +					/* Ack next byte from master */ +					writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK | +					       SLAVE_ACK_ENAB | SLAVE_EVT_STALL, +					       drvdata->base + GXP_I2CSCMD); +				} else { +					/* Nack next byte from master */ +					writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK | +					       SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD); +				} +			} +		} +	} else if (value & MASK_SLAVE_DATA_EVENT) { +		value = readb(drvdata->base + GXP_I2CSTAT); +		/* Master wants to read */ +		if (value & MASK_RW) { +			/* Master wants another byte */ +			if (value & MASK_ACK) { +				i2c_slave_event(drvdata->slave, +						I2C_SLAVE_READ_PROCESSED, &buf); +				value = buf << 8 | (SLAVE_EVT_CLR | SNOOP_EVT_MASK | +						    SLAVE_EVT_STALL); +				writew(value, drvdata->base + GXP_I2CSCMD); +			} else { +				/* No more bytes needed */ +				writew(SLAVE_EVT_CLR | SNOOP_EVT_MASK | +				       SLAVE_ACK_ENAB | SLAVE_EVT_STALL, +				       drvdata->base + GXP_I2CSCMD); +			} +		} else { +			/* Master wants to write to us */ +			value = readb(drvdata->base + GXP_I2CSNPDAT); +			buf = (uint8_t)value; +			ret = i2c_slave_event(drvdata->slave, +					      I2C_SLAVE_WRITE_RECEIVED, &buf); +			if (!ret) { +				/* Ack next byte from master */ +				writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK | +				       SLAVE_ACK_ENAB | SLAVE_EVT_STALL, +				       drvdata->base + GXP_I2CSCMD); +			} else { +				/* Nack next byte from master */ +				writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK | +				       SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD); +			} +		} +	} else { +		return false; +	} + +	return true; +} +#endif + +static irqreturn_t gxp_i2c_irq_handler(int irq, void *_drvdata) +{ +	struct gxp_i2c_drvdata *drvdata = (struct gxp_i2c_drvdata *)_drvdata; +	u32 value; + +	/* Check if the interrupt is for the current engine */ +	regmap_read(i2cg_map, GXP_I2CINTSTAT, &value); +	if (!(value & BIT(drvdata->engine))) +		return IRQ_NONE; + +	value = readb(drvdata->base + GXP_I2CEVTERR); + +	/* Error */ +	if (value & ~(MASK_MASTER_EVENT | MASK_SLAVE_CMD_EVENT | +				MASK_SLAVE_DATA_EVENT)) { +		/* Clear all events */ +		writeb(0x00, drvdata->base + GXP_I2CEVTERR); +		drvdata->state = GXP_I2C_ERROR; +		gxp_i2c_stop(drvdata); +		return IRQ_HANDLED; +	} + +	if (IS_ENABLED(CONFIG_I2C_SLAVE)) { +		/* Slave mode */ +		if (value & (MASK_SLAVE_CMD_EVENT | MASK_SLAVE_DATA_EVENT)) { +			if (gxp_i2c_slave_irq_handler(drvdata)) +				return IRQ_HANDLED; +			return IRQ_NONE; +		} +	} + +	/*  Master mode */ +	switch (drvdata->state) { +	case GXP_I2C_ADDR_PHASE: +		gxp_i2c_chk_addr_ack(drvdata); +		break; + +	case GXP_I2C_RDATA_PHASE: +		gxp_i2c_ack_data(drvdata); +		break; + +	case GXP_I2C_WDATA_PHASE: +		gxp_i2c_chk_data_ack(drvdata); +		break; +	} + +	return IRQ_HANDLED; +} + +static void gxp_i2c_init(struct gxp_i2c_drvdata *drvdata) +{ +	drvdata->state = GXP_I2C_IDLE; +	writeb(2000000 / drvdata->t.bus_freq_hz, +	       drvdata->base + GXP_I2CFREQDIV); +	writeb(FILTER_CNT | FAIRNESS_CNT, +	       drvdata->base + GXP_I2CFLTFAIR); +	writeb(GXP_DATA_EDGE_RST_CTRL, drvdata->base + GXP_I2CTMOEDG); +	writeb(0x00, drvdata->base + GXP_I2CCYCTIM); +	writeb(0x00, drvdata->base + GXP_I2CSNPAA); +	writeb(0x00, drvdata->base + GXP_I2CADVFEAT); +	writeb(SNOOP_EVT_CLR | SLAVE_EVT_CLR | SNOOP_EVT_MASK | +	       SLAVE_EVT_MASK, drvdata->base + GXP_I2CSCMD); +	writeb(MASTER_EVT_CLR, drvdata->base + GXP_I2CMCMD); +	writeb(0x00, drvdata->base + GXP_I2CEVTERR); +	writeb(0x00, drvdata->base + GXP_I2COWNADR); +} + +static int gxp_i2c_probe(struct platform_device *pdev) +{ +	struct gxp_i2c_drvdata *drvdata; +	int rc; +	struct i2c_adapter *adapter; + +	if (!i2cg_map) { +		i2cg_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, +							   "hpe,sysreg"); +		if (IS_ERR(i2cg_map)) { +			return dev_err_probe(&pdev->dev, PTR_ERR(i2cg_map), +					     "failed to map i2cg_handle\n"); +		} + +		/* Disable interrupt */ +		regmap_update_bits(i2cg_map, GXP_I2CINTEN, 0x00000FFF, 0); +	} + +	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), +			       GFP_KERNEL); +	if (!drvdata) +		return -ENOMEM; + +	platform_set_drvdata(pdev, drvdata); +	drvdata->dev = &pdev->dev; +	init_completion(&drvdata->completion); + +	drvdata->base = devm_platform_ioremap_resource(pdev, 0); +	if (IS_ERR(drvdata->base)) +		return PTR_ERR(drvdata->base); + +	/* Use physical memory address to determine which I2C engine this is. */ +	drvdata->engine = ((size_t)drvdata->base & 0xf00) >> 8; + +	if (drvdata->engine >= GXP_MAX_I2C_ENGINE) { +		return dev_err_probe(&pdev->dev, -EINVAL, "i2c engine% is unsupported\n", +			drvdata->engine); +	} + +	rc = platform_get_irq(pdev, 0); +	if (rc < 0) +		return rc; + +	drvdata->irq = rc; +	rc = devm_request_irq(&pdev->dev, drvdata->irq, gxp_i2c_irq_handler, +			      IRQF_SHARED, gxp_i2c_name[drvdata->engine], drvdata); +	if (rc < 0) +		return dev_err_probe(&pdev->dev, rc, "irq request failed\n"); + +	i2c_parse_fw_timings(&pdev->dev, &drvdata->t, true); + +	gxp_i2c_init(drvdata); + +	/* Enable interrupt */ +	regmap_update_bits(i2cg_map, GXP_I2CINTEN, BIT(drvdata->engine), +			   BIT(drvdata->engine)); + +	adapter = &drvdata->adapter; +	i2c_set_adapdata(adapter, drvdata); + +	adapter->owner = THIS_MODULE; +	strscpy(adapter->name, "HPE GXP I2C adapter", sizeof(adapter->name)); +	adapter->algo = &gxp_i2c_algo; +	adapter->dev.parent = &pdev->dev; +	adapter->dev.of_node = pdev->dev.of_node; + +	rc = i2c_add_adapter(adapter); +	if (rc) +		return dev_err_probe(&pdev->dev, rc, "i2c add adapter failed\n"); + +	return 0; +} + +static int gxp_i2c_remove(struct platform_device *pdev) +{ +	struct gxp_i2c_drvdata *drvdata = platform_get_drvdata(pdev); + +	/* Disable interrupt */ +	regmap_update_bits(i2cg_map, GXP_I2CINTEN, BIT(drvdata->engine), 0); +	i2c_del_adapter(&drvdata->adapter); + +	return 0; +} + +static const struct of_device_id gxp_i2c_of_match[] = { +	{ .compatible = "hpe,gxp-i2c" }, +	{}, +}; +MODULE_DEVICE_TABLE(of, gxp_i2c_of_match); + +static struct platform_driver gxp_i2c_driver = { +	.probe	= gxp_i2c_probe, +	.remove = gxp_i2c_remove, +	.driver = { +		.name = "gxp-i2c", +		.of_match_table = gxp_i2c_of_match, +	}, +}; +module_platform_driver(gxp_i2c_driver); + +MODULE_AUTHOR("Nick Hawkins <[email protected]>"); +MODULE_DESCRIPTION("HPE GXP I2C bus driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 1fda1eaa6d6a..ac5326747c51 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -434,7 +434,7 @@ static int i801_wait_intr(struct i801_priv *priv)  		busy = status & SMBHSTSTS_HOST_BUSY;  		status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR;  		if (!busy && status) -			return status; +			return status & STATUS_ERROR_FLAGS;  	} while (time_is_after_eq_jiffies(timeout));  	return -ETIMEDOUT; @@ -458,26 +458,20 @@ static int i801_wait_byte_done(struct i801_priv *priv)  static int i801_transaction(struct i801_priv *priv, int xact)  { -	int status;  	unsigned long result;  	const struct i2c_adapter *adap = &priv->adapter; -	status = i801_check_pre(priv); -	if (status < 0) -		return status; -  	if (priv->features & FEATURE_IRQ) {  		reinit_completion(&priv->done);  		outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,  		       SMBHSTCNT(priv));  		result = wait_for_completion_timeout(&priv->done, adap->timeout); -		return i801_check_post(priv, result ? priv->status : -ETIMEDOUT); +		return result ? priv->status : -ETIMEDOUT;  	}  	outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); -	status = i801_wait_intr(priv); -	return i801_check_post(priv, status); +	return i801_wait_intr(priv);  }  static int i801_block_transaction_by_block(struct i801_priv *priv, @@ -511,19 +505,23 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,  	status = i801_transaction(priv, xact);  	if (status) -		return status; +		goto out;  	if (read_write == I2C_SMBUS_READ ||  	    command == I2C_SMBUS_BLOCK_PROC_CALL) {  		len = inb_p(SMBHSTDAT0(priv)); -		if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) -			return -EPROTO; +		if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { +			status = -EPROTO; +			goto out; +		}  		data->block[0] = len;  		for (i = 0; i < len; i++)  			data->block[i + 1] = inb_p(SMBBLKDAT(priv));  	} -	return 0; +out: +	outb_p(inb_p(SMBAUXCTL(priv)) & ~SMBAUXCTL_E32B, SMBAUXCTL(priv)); +	return status;  }  static void i801_isr_byte_done(struct i801_priv *priv) @@ -558,9 +556,6 @@ static void i801_isr_byte_done(struct i801_priv *priv)  		/* Write next byte, except for IRQ after last byte */  		outb_p(priv->data[++priv->count], SMBBLKDAT(priv));  	} - -	/* Clear BYTE_DONE to continue with next byte */ -	outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));  }  static irqreturn_t i801_host_notify_isr(struct i801_priv *priv) @@ -590,7 +585,6 @@ static irqreturn_t i801_host_notify_isr(struct i801_priv *priv)   *      BUS_ERR - SMI# transaction collision   *      FAILED - transaction was canceled due to a KILL request   *    When any of these occur, update ->status and signal completion. - *    ->status must be cleared before kicking off the next transaction.   *   * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt   *    occurs for each byte of a byte-by-byte to prepare the next byte. @@ -615,25 +609,20 @@ static irqreturn_t i801_isr(int irq, void *dev_id)  	}  	status = inb_p(SMBHSTSTS(priv)); -	if (status & SMBHSTSTS_BYTE_DONE) +	if ((status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS)) == SMBHSTSTS_BYTE_DONE)  		i801_isr_byte_done(priv);  	/* -	 * Clear remaining IRQ sources: Completion of last command, errors -	 * and the SMB_ALERT signal. SMB_ALERT status is set after signal -	 * assertion independently of the interrupt generation being blocked -	 * or not so clear it always when the status is set. -	 */ -	status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS | SMBHSTSTS_SMBALERT_STS; -	if (status) -		outb_p(status, SMBHSTSTS(priv)); -	status &= ~SMBHSTSTS_SMBALERT_STS; /* SMB_ALERT not reported */ -	/* -	 * Report transaction result. -	 * ->status must be cleared before the next transaction is started. +	 * Clear IRQ sources: SMB_ALERT status is set after signal assertion +	 * independently of the interrupt generation being blocked or not +	 * so clear it always when the status is set.  	 */ +	status &= STATUS_FLAGS | SMBHSTSTS_SMBALERT_STS; +	outb_p(status, SMBHSTSTS(priv)); + +	status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR;  	if (status) { -		priv->status = status; +		priv->status = status & STATUS_ERROR_FLAGS;  		complete(&priv->done);  	} @@ -658,10 +647,6 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,  	if (command == I2C_SMBUS_BLOCK_PROC_CALL)  		return -EOPNOTSUPP; -	status = i801_check_pre(priv); -	if (status < 0) -		return status; -  	len = data->block[0];  	if (read_write == I2C_SMBUS_WRITE) { @@ -687,7 +672,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,  		reinit_completion(&priv->done);  		outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));  		result = wait_for_completion_timeout(&priv->done, adap->timeout); -		return i801_check_post(priv, result ? priv->status : -ETIMEDOUT); +		return result ? priv->status : -ETIMEDOUT;  	}  	for (i = 1; i <= len; i++) { @@ -701,7 +686,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,  		status = i801_wait_byte_done(priv);  		if (status) -			goto exit; +			return status;  		if (i == 1 && read_write == I2C_SMBUS_READ  		 && command != I2C_SMBUS_I2C_BLOCK_DATA) { @@ -731,14 +716,82 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,  		outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));  	} -	status = i801_wait_intr(priv); -exit: -	return i801_check_post(priv, status); +	return i801_wait_intr(priv); +} + +static void i801_set_hstadd(struct i801_priv *priv, u8 addr, char read_write) +{ +	outb_p((addr << 1) | (read_write & 0x01), SMBHSTADD(priv)); +} + +/* Single value transaction function */ +static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data *data, +				   u8 addr, u8 hstcmd, char read_write, int command) +{ +	int xact, ret; + +	switch (command) { +	case I2C_SMBUS_QUICK: +		i801_set_hstadd(priv, addr, read_write); +		xact = I801_QUICK; +		break; +	case I2C_SMBUS_BYTE: +		i801_set_hstadd(priv, addr, read_write); +		if (read_write == I2C_SMBUS_WRITE) +			outb_p(hstcmd, SMBHSTCMD(priv)); +		xact = I801_BYTE; +		break; +	case I2C_SMBUS_BYTE_DATA: +		i801_set_hstadd(priv, addr, read_write); +		if (read_write == I2C_SMBUS_WRITE) +			outb_p(data->byte, SMBHSTDAT0(priv)); +		outb_p(hstcmd, SMBHSTCMD(priv)); +		xact = I801_BYTE_DATA; +		break; +	case I2C_SMBUS_WORD_DATA: +		i801_set_hstadd(priv, addr, read_write); +		if (read_write == I2C_SMBUS_WRITE) { +			outb_p(data->word & 0xff, SMBHSTDAT0(priv)); +			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); +		} +		outb_p(hstcmd, SMBHSTCMD(priv)); +		xact = I801_WORD_DATA; +		break; +	case I2C_SMBUS_PROC_CALL: +		i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE); +		outb_p(data->word & 0xff, SMBHSTDAT0(priv)); +		outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); +		outb_p(hstcmd, SMBHSTCMD(priv)); +		read_write = I2C_SMBUS_READ; +		xact = I801_PROC_CALL; +		break; +	default: +		pci_err(priv->pci_dev, "Unsupported transaction %d\n", command); +		return -EOPNOTSUPP; +	} + +	ret = i801_transaction(priv, xact); +	if (ret || read_write == I2C_SMBUS_WRITE) +		return ret; + +	switch (command) { +	case I2C_SMBUS_BYTE: +	case I2C_SMBUS_BYTE_DATA: +		data->byte = inb_p(SMBHSTDAT0(priv)); +		break; +	case I2C_SMBUS_WORD_DATA: +	case I2C_SMBUS_PROC_CALL: +		data->word = inb_p(SMBHSTDAT0(priv)) + +			     (inb_p(SMBHSTDAT1(priv)) << 8); +		break; +	} + +	return 0;  }  /* Block transaction function */  static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data, -				  char read_write, int command) +				  u8 addr, u8 hstcmd, char read_write, int command)  {  	int result = 0;  	unsigned char hostc; @@ -748,7 +801,29 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *  	else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)  		return -EPROTO; -	if (command == I2C_SMBUS_I2C_BLOCK_DATA) { +	switch (command) { +	case I2C_SMBUS_BLOCK_DATA: +		i801_set_hstadd(priv, addr, read_write); +		outb_p(hstcmd, SMBHSTCMD(priv)); +		break; +	case I2C_SMBUS_I2C_BLOCK_DATA: +		/* +		 * NB: page 240 of ICH5 datasheet shows that the R/#W +		 * bit should be cleared here, even when reading. +		 * However if SPD Write Disable is set (Lynx Point and later), +		 * the read will fail if we don't set the R/#W bit. +		 */ +		i801_set_hstadd(priv, addr, +				priv->original_hstcfg & SMBHSTCFG_SPD_WD ? +				read_write : I2C_SMBUS_WRITE); +		if (read_write == I2C_SMBUS_READ) { +			/* NB: page 240 of ICH5 datasheet also shows +			 * that DATA1 is the cmd field when reading +			 */ +			outb_p(hstcmd, SMBHSTDAT1(priv)); +		} else +			outb_p(hstcmd, SMBHSTCMD(priv)); +  		if (read_write == I2C_SMBUS_WRITE) {  			/* set I2C_EN bit in configuration register */  			pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc); @@ -759,6 +834,12 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *  				"I2C block read is unsupported!\n");  			return -EOPNOTSUPP;  		} +		break; +	case I2C_SMBUS_BLOCK_PROC_CALL: +		/* Needs to be flagged as write transaction */ +		i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE); +		outb_p(hstcmd, SMBHSTCMD(priv)); +		break;  	}  	/* Experience has shown that the block buffer can only be used for @@ -787,9 +868,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,  		       unsigned short flags, char read_write, u8 command,  		       int size, union i2c_smbus_data *data)  { -	int hwpec; -	int block = 0; -	int ret, xact; +	int hwpec, ret;  	struct i801_priv *priv = i2c_get_adapdata(adap);  	mutex_lock(&priv->acpi_lock); @@ -800,127 +879,34 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,  	pm_runtime_get_sync(&priv->pci_dev->dev); +	ret = i801_check_pre(priv); +	if (ret) +		goto out; +  	hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)  		&& size != I2C_SMBUS_QUICK  		&& size != I2C_SMBUS_I2C_BLOCK_DATA; -	switch (size) { -	case I2C_SMBUS_QUICK: -		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), -		       SMBHSTADD(priv)); -		xact = I801_QUICK; -		break; -	case I2C_SMBUS_BYTE: -		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), -		       SMBHSTADD(priv)); -		if (read_write == I2C_SMBUS_WRITE) -			outb_p(command, SMBHSTCMD(priv)); -		xact = I801_BYTE; -		break; -	case I2C_SMBUS_BYTE_DATA: -		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), -		       SMBHSTADD(priv)); -		outb_p(command, SMBHSTCMD(priv)); -		if (read_write == I2C_SMBUS_WRITE) -			outb_p(data->byte, SMBHSTDAT0(priv)); -		xact = I801_BYTE_DATA; -		break; -	case I2C_SMBUS_WORD_DATA: -		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), -		       SMBHSTADD(priv)); -		outb_p(command, SMBHSTCMD(priv)); -		if (read_write == I2C_SMBUS_WRITE) { -			outb_p(data->word & 0xff, SMBHSTDAT0(priv)); -			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); -		} -		xact = I801_WORD_DATA; -		break; -	case I2C_SMBUS_PROC_CALL: -		outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); -		outb_p(command, SMBHSTCMD(priv)); -		outb_p(data->word & 0xff, SMBHSTDAT0(priv)); -		outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); -		xact = I801_PROC_CALL; -		read_write = I2C_SMBUS_READ; -		break; -	case I2C_SMBUS_BLOCK_DATA: -		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), -		       SMBHSTADD(priv)); -		outb_p(command, SMBHSTCMD(priv)); -		block = 1; -		break; -	case I2C_SMBUS_I2C_BLOCK_DATA: -		/* -		 * NB: page 240 of ICH5 datasheet shows that the R/#W -		 * bit should be cleared here, even when reading. -		 * However if SPD Write Disable is set (Lynx Point and later), -		 * the read will fail if we don't set the R/#W bit. -		 */ -		outb_p(((addr & 0x7f) << 1) | -		       ((priv->original_hstcfg & SMBHSTCFG_SPD_WD) ? -			(read_write & 0x01) : 0), -		       SMBHSTADD(priv)); -		if (read_write == I2C_SMBUS_READ) { -			/* NB: page 240 of ICH5 datasheet also shows -			 * that DATA1 is the cmd field when reading */ -			outb_p(command, SMBHSTDAT1(priv)); -		} else -			outb_p(command, SMBHSTCMD(priv)); -		block = 1; -		break; -	case I2C_SMBUS_BLOCK_PROC_CALL: -		/* -		 * Bit 0 of the slave address register always indicate a write -		 * command. -		 */ -		outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); -		outb_p(command, SMBHSTCMD(priv)); -		block = 1; -		break; -	default: -		dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", -			size); -		ret = -EOPNOTSUPP; -		goto out; -	} -  	if (hwpec)	/* enable/disable hardware PEC */  		outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));  	else  		outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),  		       SMBAUXCTL(priv)); -	if (block) -		ret = i801_block_transaction(priv, data, read_write, size); +	if (size == I2C_SMBUS_BLOCK_DATA || +	    size == I2C_SMBUS_I2C_BLOCK_DATA || +	    size == I2C_SMBUS_BLOCK_PROC_CALL) +		ret = i801_block_transaction(priv, data, addr, command, read_write, size);  	else -		ret = i801_transaction(priv, xact); - -	/* Some BIOSes don't like it when PEC is enabled at reboot or resume -	   time, so we forcibly disable it after every transaction. Turn off -	   E32B for the same reason. */ -	if (hwpec || block) -		outb_p(inb_p(SMBAUXCTL(priv)) & -		       ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); - -	if (block) -		goto out; -	if (ret) -		goto out; -	if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) -		goto out; +		ret = i801_simple_transaction(priv, data, addr, command, read_write, size); -	switch (xact) { -	case I801_BYTE:	/* Result put in SMBHSTDAT0 */ -	case I801_BYTE_DATA: -		data->byte = inb_p(SMBHSTDAT0(priv)); -		break; -	case I801_WORD_DATA: -	case I801_PROC_CALL: -		data->word = inb_p(SMBHSTDAT0(priv)) + -			     (inb_p(SMBHSTDAT1(priv)) << 8); -		break; -	} +	ret = i801_check_post(priv, ret); +	/* Some BIOSes don't like it when PEC is enabled at reboot or resume +	 * time, so we forcibly disable it after every transaction. +	 */ +	if (hwpec) +		outb_p(inb_p(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv));  out:  	/*  	 * Unlock the SMBus device for use by BIOS/ACPI, @@ -1667,6 +1653,10 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)  	}  	priv->features &= ~disable_features; +	/* The block process call uses block buffer mode */ +	if (!(priv->features & FEATURE_BLOCK_BUFFER)) +		priv->features &= ~FEATURE_BLOCK_PROC; +  	err = pcim_enable_device(dev);  	if (err) {  		dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", @@ -1714,11 +1704,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)  		outb_p(inb_p(SMBAUXCTL(priv)) &  		       ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); -	/* Remember original Interrupt and Host Notify settings */ -	priv->original_hstcnt = inb_p(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL; -	if (priv->features & FEATURE_HOST_NOTIFY) -		priv->original_slvcmd = inb_p(SMBSLVCMD(priv)); -  	/* Default timeout in interrupt mode: 200 ms */  	priv->adapter.timeout = HZ / 5; @@ -1748,6 +1733,15 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)  	dev_info(&dev->dev, "SMBus using %s\n",  		 priv->features & FEATURE_IRQ ? "PCI interrupt" : "polling"); +	/* Host notification uses an interrupt */ +	if (!(priv->features & FEATURE_IRQ)) +		priv->features &= ~FEATURE_HOST_NOTIFY; + +	/* Remember original Interrupt and Host Notify settings */ +	priv->original_hstcnt = inb_p(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL; +	if (priv->features & FEATURE_HOST_NOTIFY) +		priv->original_slvcmd = inb_p(SMBSLVCMD(priv)); +  	i801_add_tco(priv);  	snprintf(priv->adapter.name, sizeof(priv->adapter.name), diff --git a/drivers/i2c/busses/i2c-ls2x.c b/drivers/i2c/busses/i2c-ls2x.c new file mode 100644 index 000000000000..ebae6035701d --- /dev/null +++ b/drivers/i2c/busses/i2c-ls2x.c @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Loongson-2K/Loongson LS7A I2C master mode driver + * + * Copyright (C) 2013 Loongson Technology Corporation Limited. + * Copyright (C) 2014-2017 Lemote, Inc. + * Copyright (C) 2018-2022 Loongson Technology Corporation Limited. + * + * Originally written by liushaozong + * Rewritten for mainline by Binbin Zhou <[email protected]> + */ + +#include <linux/bits.h> +#include <linux/completion.h> +#include <linux/device.h> +#include <linux/iopoll.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/platform_device.h> +#include <linux/property.h> +#include <linux/units.h> + +/* I2C Registers */ +#define I2C_LS2X_PRER		0x0 /* Freq Division Register(16 bits) */ +#define I2C_LS2X_CTR		0x2 /* Control Register */ +#define I2C_LS2X_TXR		0x3 /* Transport Data Register */ +#define I2C_LS2X_RXR		0x3 /* Receive Data Register */ +#define I2C_LS2X_CR		0x4 /* Command Control Register */ +#define I2C_LS2X_SR		0x4 /* State Register */ + +/* Command Control Register Bit */ +#define LS2X_CR_START		BIT(7) /* Start signal */ +#define LS2X_CR_STOP		BIT(6) /* Stop signal */ +#define LS2X_CR_READ		BIT(5) /* Read signal */ +#define LS2X_CR_WRITE		BIT(4) /* Write signal */ +#define LS2X_CR_ACK		BIT(3) /* Response signal */ +#define LS2X_CR_IACK		BIT(0) /* Interrupt response signal */ + +/* State Register Bit */ +#define LS2X_SR_NOACK		BIT(7) /* Receive NACK */ +#define LS2X_SR_BUSY		BIT(6) /* Bus busy state */ +#define LS2X_SR_AL		BIT(5) /* Arbitration lost */ +#define LS2X_SR_TIP		BIT(1) /* Transmission state */ +#define LS2X_SR_IF		BIT(0) /* Interrupt flag */ + +/* Control Register Bit */ +#define LS2X_CTR_EN		BIT(7) /* 0: I2c frequency setting 1: Normal */ +#define LS2X_CTR_IEN		BIT(6) /* Enable i2c interrupt */ +#define LS2X_CTR_MST		BIT(5) /* 0: Slave mode 1: Master mode */ +#define CTR_FREQ_MASK		GENMASK(7, 6) +#define CTR_READY_MASK		GENMASK(7, 5) + +/* The PCLK frequency from LPB */ +#define LS2X_I2C_PCLK_FREQ	(50 * HZ_PER_MHZ) + +/* The default bus frequency, which is an empirical value */ +#define LS2X_I2C_FREQ_STD	(33 * HZ_PER_KHZ) + +struct ls2x_i2c_priv { +	struct i2c_adapter	adapter; +	void __iomem		*base; +	struct i2c_timings	i2c_t; +	struct completion	cmd_complete; +}; + +/* + * Interrupt service routine. + * This gets called whenever an I2C interrupt occurs. + */ +static irqreturn_t ls2x_i2c_isr(int this_irq, void *dev_id) +{ +	struct ls2x_i2c_priv *priv = dev_id; + +	if (!(readb(priv->base + I2C_LS2X_SR) & LS2X_SR_IF)) +		return IRQ_NONE; + +	writeb(LS2X_CR_IACK, priv->base + I2C_LS2X_CR); +	complete(&priv->cmd_complete); +	return IRQ_HANDLED; +} + +/* + * The ls2x i2c controller supports standard mode and fast mode, so the + * maximum bus frequency is '400kHz'. + * The bus frequency is set to the empirical value of '33KHz' by default, + * but it can also be taken from ACPI or FDT for compatibility with more + * devices. + */ +static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv) +{ +	struct i2c_timings *t = &priv->i2c_t; +	struct device *dev = priv->adapter.dev.parent; +	u32 acpi_speed = i2c_acpi_find_bus_speed(dev); + +	i2c_parse_fw_timings(dev, t, false); + +	if (acpi_speed || t->bus_freq_hz) +		t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed); +	else +		t->bus_freq_hz = LS2X_I2C_FREQ_STD; + +	/* Calculate and set i2c frequency. */ +	writew(LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1, +	       priv->base + I2C_LS2X_PRER); +} + +static void ls2x_i2c_init(struct ls2x_i2c_priv *priv) +{ +	/* Set i2c frequency setting mode and disable interrupts. */ +	writeb(readb(priv->base + I2C_LS2X_CTR) & ~CTR_FREQ_MASK, +	       priv->base + I2C_LS2X_CTR); + +	ls2x_i2c_adjust_bus_speed(priv); + +	/* Set i2c normal operating mode and enable interrupts. */ +	writeb(readb(priv->base + I2C_LS2X_CTR) | CTR_READY_MASK, +	       priv->base + I2C_LS2X_CTR); +} + +static int ls2x_i2c_xfer_byte(struct ls2x_i2c_priv *priv, u8 txdata, u8 *rxdatap) +{ +	u8 rxdata; +	unsigned long time_left; + +	writeb(txdata, priv->base + I2C_LS2X_CR); + +	time_left = wait_for_completion_timeout(&priv->cmd_complete, +						priv->adapter.timeout); +	if (!time_left) +		return -ETIMEDOUT; + +	rxdata = readb(priv->base + I2C_LS2X_SR); +	if (rxdatap) +		*rxdatap = rxdata; + +	return 0; +} + +static int ls2x_i2c_send_byte(struct ls2x_i2c_priv *priv, u8 txdata) +{ +	int ret; +	u8 rxdata; + +	ret = ls2x_i2c_xfer_byte(priv, txdata, &rxdata); +	if (ret) +		return ret; + +	if (rxdata & LS2X_SR_AL) +		return -EAGAIN; + +	if (rxdata & LS2X_SR_NOACK) +		return -ENXIO; + +	return 0; +} + +static int ls2x_i2c_stop(struct ls2x_i2c_priv *priv) +{ +	u8 value; + +	writeb(LS2X_CR_STOP, priv->base + I2C_LS2X_CR); +	return readb_poll_timeout(priv->base + I2C_LS2X_SR, value, +				  !(value & LS2X_SR_BUSY), 100, +				  jiffies_to_usecs(priv->adapter.timeout)); +} + +static int ls2x_i2c_start(struct ls2x_i2c_priv *priv, struct i2c_msg *msgs) +{ +	reinit_completion(&priv->cmd_complete); + +	writeb(i2c_8bit_addr_from_msg(msgs), priv->base + I2C_LS2X_TXR); +	return ls2x_i2c_send_byte(priv, LS2X_CR_START | LS2X_CR_WRITE); +} + +static int ls2x_i2c_rx(struct ls2x_i2c_priv *priv, struct i2c_msg *msg) +{ +	int ret; +	u8 rxdata, *buf = msg->buf; +	u16 len = msg->len; + +	/* Contains steps to send start condition and address. */ +	ret = ls2x_i2c_start(priv, msg); +	if (ret) +		return ret; + +	while (len--) { +		ret = ls2x_i2c_xfer_byte(priv, +					 LS2X_CR_READ | (len ? 0 : LS2X_CR_ACK), +					 &rxdata); +		if (ret) +			return ret; + +		*buf++ = readb(priv->base + I2C_LS2X_RXR); +	} + +	return 0; +} + +static int ls2x_i2c_tx(struct ls2x_i2c_priv *priv, struct i2c_msg *msg) +{ +	int ret; +	u8 *buf = msg->buf; +	u16 len = msg->len; + +	/* Contains steps to send start condition and address. */ +	ret = ls2x_i2c_start(priv, msg); +	if (ret) +		return ret; + +	while (len--) { +		writeb(*buf++, priv->base + I2C_LS2X_TXR); + +		ret = ls2x_i2c_send_byte(priv, LS2X_CR_WRITE); +		if (ret) +			return ret; +	} + +	return 0; +} + +static int ls2x_i2c_xfer_one(struct ls2x_i2c_priv *priv, +			     struct i2c_msg *msg, bool stop) +{ +	int ret; + +	if (msg->flags & I2C_M_RD) +		ret = ls2x_i2c_rx(priv, msg); +	else +		ret = ls2x_i2c_tx(priv, msg); + +	if (ret < 0) { +		/* Fatel error. Needs reinit. */ +		if (ret == -ETIMEDOUT) +			ls2x_i2c_init(priv); + +		return ret; +	} + +	if (stop) { +		/* Failed to issue STOP. Needs reinit. */ +		ret = ls2x_i2c_stop(priv); +		if (ret) +			ls2x_i2c_init(priv); +	} + +	return ret; +} + +static int ls2x_i2c_master_xfer(struct i2c_adapter *adap, +				struct i2c_msg *msgs, int num) +{ +	int ret; +	struct i2c_msg *msg, *emsg = msgs + num; +	struct ls2x_i2c_priv *priv = i2c_get_adapdata(adap); + +	for (msg = msgs; msg < emsg; msg++) { +		ret = ls2x_i2c_xfer_one(priv, msg, msg == emsg - 1); +		if (ret) +			return ret; +	} + +	return num; +} + +static unsigned int ls2x_i2c_func(struct i2c_adapter *adap) +{ +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm ls2x_i2c_algo = { +	.master_xfer	= ls2x_i2c_master_xfer, +	.functionality	= ls2x_i2c_func, +}; + +static int ls2x_i2c_probe(struct platform_device *pdev) +{ +	int ret, irq; +	struct i2c_adapter *adap; +	struct ls2x_i2c_priv *priv; +	struct device *dev = &pdev->dev; + +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	/* Map hardware registers */ +	priv->base = devm_platform_ioremap_resource(pdev, 0); +	if (IS_ERR(priv->base)) +		return PTR_ERR(priv->base); + +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) +		return irq; + +	/* Add the i2c adapter */ +	adap = &priv->adapter; +	adap->retries = 5; +	adap->nr = pdev->id; +	adap->dev.parent = dev; +	adap->owner = THIS_MODULE; +	adap->algo = &ls2x_i2c_algo; +	adap->timeout = msecs_to_jiffies(100); +	device_set_node(&adap->dev, dev_fwnode(dev)); +	i2c_set_adapdata(adap, priv); +	strscpy(adap->name, pdev->name, sizeof(adap->name)); +	init_completion(&priv->cmd_complete); +	platform_set_drvdata(pdev, priv); + +	ls2x_i2c_init(priv); + +	ret = devm_request_irq(dev, irq, ls2x_i2c_isr, IRQF_SHARED, "ls2x-i2c", +			       priv); +	if (ret < 0) +		return dev_err_probe(dev, ret, "Unable to request irq %d\n", irq); + +	return devm_i2c_add_adapter(dev, adap); +} + +static int ls2x_i2c_suspend(struct device *dev) +{ +	struct ls2x_i2c_priv *priv = dev_get_drvdata(dev); + +	/* Disable interrupts */ +	writeb(readb(priv->base + I2C_LS2X_CTR) & ~LS2X_CTR_IEN, +	       priv->base + I2C_LS2X_CTR); + +	return 0; +} + +static int ls2x_i2c_resume(struct device *dev) +{ +	ls2x_i2c_init(dev_get_drvdata(dev)); +	return 0; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(ls2x_i2c_pm_ops, +				 ls2x_i2c_suspend, ls2x_i2c_resume, NULL); + +static const struct of_device_id ls2x_i2c_id_table[] = { +	{ .compatible = "loongson,ls2k-i2c" }, +	{ .compatible = "loongson,ls7a-i2c" }, +	{ /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ls2x_i2c_id_table); + +static const struct acpi_device_id ls2x_i2c_acpi_match[] = { +	{ "LOON0004" }, /* Loongson LS7A */ +	{ } +}; +MODULE_DEVICE_TABLE(acpi, ls2x_i2c_acpi_match); + +static struct platform_driver ls2x_i2c_driver = { +	.probe		= ls2x_i2c_probe, +	.driver		= { +		.name	= "ls2x-i2c", +		.pm	= pm_sleep_ptr(&ls2x_i2c_pm_ops), +		.of_match_table = ls2x_i2c_id_table, +		.acpi_match_table = ls2x_i2c_acpi_match, +	}, +}; +module_platform_driver(ls2x_i2c_driver); + +MODULE_DESCRIPTION("Loongson LS2X I2C Bus driver"); +MODULE_AUTHOR("Loongson Technology Corporation Limited"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index d80e59340d97..43dd966d5ef5 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -1366,20 +1366,17 @@ static int mtk_i2c_probe(struct platform_device *pdev)  {  	int ret = 0;  	struct mtk_i2c *i2c; -	struct resource *res;  	int i, irq, speed_clk;  	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);  	if (!i2c)  		return -ENOMEM; -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	i2c->base = devm_ioremap_resource(&pdev->dev, res); +	i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);  	if (IS_ERR(i2c->base))  		return PTR_ERR(i2c->base); -	res = platform_get_resource(pdev, IORESOURCE_MEM, 1); -	i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res); +	i2c->pdmabase = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);  	if (IS_ERR(i2c->pdmabase))  		return PTR_ERR(i2c->pdmabase); diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 5af5cffc444e..d113bed79545 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -826,8 +826,8 @@ static int mxs_i2c_probe(struct platform_device *pdev)  	/* Setup the DMA */  	i2c->dmach = dma_request_chan(dev, "rx-tx");  	if (IS_ERR(i2c->dmach)) { -		dev_err(dev, "Failed to request dma\n"); -		return PTR_ERR(i2c->dmach); +		return dev_err_probe(dev, PTR_ERR(i2c->dmach), +				     "Failed to request dma\n");  	}  	platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index 12e330cd7635..a8b99e7f6262 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -259,8 +259,8 @@ static const struct pci_device_id gpu_i2c_ids[] = {  MODULE_DEVICE_TABLE(pci, gpu_i2c_ids);  static const struct property_entry ccgx_props[] = { -	/* Use FW built for NVIDIA (nv) only */ -	PROPERTY_ENTRY_U16("ccgx,firmware-build", ('n' << 8) | 'v'), +	/* Use FW built for NVIDIA GPU only */ +	PROPERTY_ENTRY_STRING("firmware-name", "nvidia,gpu"),  	{ }  }; diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index a4b97fe3c3a5..01358472680c 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -811,9 +811,15 @@ static const struct cci_data cci_v2_data = {  static const struct of_device_id cci_dt_match[] = {  	{ .compatible = "qcom,msm8226-cci", .data = &cci_v1_data}, -	{ .compatible = "qcom,msm8916-cci", .data = &cci_v1_data},  	{ .compatible = "qcom,msm8974-cci", .data = &cci_v1_5_data},  	{ .compatible = "qcom,msm8996-cci", .data = &cci_v2_data}, + + +	/* +	 * Legacy compatibles kept for backwards compatibility. +	 * Do not add any new ones unless they introduce a new config +	 */ +	{ .compatible = "qcom,msm8916-cci", .data = &cci_v1_data},  	{ .compatible = "qcom,sdm845-cci", .data = &cci_v2_data},  	{ .compatible = "qcom,sm8250-cci", .data = &cci_v2_data},  	{ .compatible = "qcom,sm8450-cci", .data = &cci_v2_data}, diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index fd70794bfcee..83909b02a03e 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -14,7 +14,7 @@  #include <linux/of.h>  #include <linux/platform_device.h>  #include <linux/pm_runtime.h> -#include <linux/qcom-geni-se.h> +#include <linux/soc/qcom/geni-se.h>  #include <linux/spinlock.h>  #define SE_I2C_TX_TRANS_LEN		0x26c @@ -1025,7 +1025,7 @@ static const struct dev_pm_ops geni_i2c_pm_ops = {  									NULL)  }; -const struct geni_i2c_desc i2c_master_hub = { +static const struct geni_i2c_desc i2c_master_hub = {  	.has_core_clk = true,  	.icc_ddr = NULL,  	.no_dma_support = true, diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index d1658ed76562..b31cf4f18f85 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -80,7 +80,7 @@ enum {  #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */  /** - * struct i2c_spec_values: + * struct i2c_spec_values - I2C specification values for various modes   * @min_hold_start_ns: min hold time (repeated) START condition   * @min_low_ns: min LOW period of the SCL clock   * @min_high_ns: min HIGH period of the SCL cloc @@ -136,7 +136,7 @@ static const struct i2c_spec_values fast_mode_plus_spec = {  };  /** - * struct rk3x_i2c_calced_timings: + * struct rk3x_i2c_calced_timings - calculated V1 timings   * @div_low: Divider output for low   * @div_high: Divider output for high   * @tuning: Used to adjust setup/hold data time, @@ -159,7 +159,7 @@ enum rk3x_i2c_state {  };  /** - * struct rk3x_i2c_soc_data: + * struct rk3x_i2c_soc_data - SOC-specific data   * @grf_offset: offset inside the grf regmap for setting the i2c type   * @calc_timings: Callback function for i2c timing information calculated   */ @@ -239,7 +239,8 @@ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c)  }  /** - * Generate a START condition, which triggers a REG_INT_START interrupt. + * rk3x_i2c_start - Generate a START condition, which triggers a REG_INT_START interrupt. + * @i2c: target controller data   */  static void rk3x_i2c_start(struct rk3x_i2c *i2c)  { @@ -258,8 +259,8 @@ static void rk3x_i2c_start(struct rk3x_i2c *i2c)  }  /** - * Generate a STOP condition, which triggers a REG_INT_STOP interrupt. - * + * rk3x_i2c_stop - Generate a STOP condition, which triggers a REG_INT_STOP interrupt. + * @i2c: target controller data   * @error: Error code to return in rk3x_i2c_xfer   */  static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error) @@ -298,7 +299,8 @@ static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error)  }  /** - * Setup a read according to i2c->msg + * rk3x_i2c_prepare_read - Setup a read according to i2c->msg + * @i2c: target controller data   */  static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c)  { @@ -329,7 +331,8 @@ static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c)  }  /** - * Fill the transmit buffer with data from i2c->msg + * rk3x_i2c_fill_transmit_buf - Fill the transmit buffer with data from i2c->msg + * @i2c: target controller data   */  static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c)  { @@ -532,11 +535,10 @@ out:  }  /** - * Get timing values of I2C specification - * + * rk3x_i2c_get_spec - Get timing values of I2C specification   * @speed: Desired SCL frequency   * - * Returns: Matched i2c spec values. + * Return: Matched i2c_spec_values.   */  static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)  { @@ -549,13 +551,12 @@ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)  }  /** - * Calculate divider values for desired SCL frequency - * + * rk3x_i2c_v0_calc_timings - Calculate divider values for desired SCL frequency   * @clk_rate: I2C input clock rate   * @t: Known I2C timing information   * @t_calc: Caculated rk3x private timings that would be written into regs   * - * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case + * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case   * a best-effort divider value is returned in divs. If the target rate is   * too high, we silently use the highest possible rate.   */ @@ -710,13 +711,12 @@ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,  }  /** - * Calculate timing values for desired SCL frequency - * + * rk3x_i2c_v1_calc_timings - Calculate timing values for desired SCL frequency   * @clk_rate: I2C input clock rate   * @t: Known I2C timing information   * @t_calc: Caculated rk3x private timings that would be written into regs   * - * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case + * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case   * a best-effort divider value is returned in divs. If the target rate is   * too high, we silently use the highest possible rate.   * The following formulas are v1's method to calculate timings. @@ -960,14 +960,14 @@ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long  }  /** - * Setup I2C registers for an I2C operation specified by msgs, num. - * - * Must be called with i2c->lock held. - * + * rk3x_i2c_setup - Setup I2C registers for an I2C operation specified by msgs, num. + * @i2c: target controller data   * @msgs: I2C msgs to process   * @num: Number of msgs   * - * returns: Number of I2C msgs processed or negative in case of error + * Must be called with i2c->lock held. + * + * Return: Number of I2C msgs processed or negative in case of error   */  static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num)  { diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 36dab9cd208c..45e9df81345a 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -116,9 +116,6 @@ struct s3c24xx_i2c {  	struct s3c2410_platform_i2c	*pdata;  	struct gpio_desc	*gpios[2];  	struct pinctrl          *pctrl; -#if defined(CONFIG_ARM_S3C24XX_CPUFREQ) -	struct notifier_block	freq_transition; -#endif  	struct regmap		*sysreg;  	unsigned int		sys_i2c_cfg;  }; @@ -885,65 +882,6 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)  	return 0;  } -#if defined(CONFIG_ARM_S3C24XX_CPUFREQ) - -#define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition) - -static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, -					  unsigned long val, void *data) -{ -	struct s3c24xx_i2c *i2c = freq_to_i2c(nb); -	unsigned int got; -	int delta_f; -	int ret; - -	delta_f = clk_get_rate(i2c->clk) - i2c->clkrate; - -	/* if we're post-change and the input clock has slowed down -	 * or at pre-change and the clock is about to speed up, then -	 * adjust our clock rate. <0 is slow, >0 speedup. -	 */ - -	if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || -	    (val == CPUFREQ_PRECHANGE && delta_f > 0)) { -		i2c_lock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER); -		ret = s3c24xx_i2c_clockrate(i2c, &got); -		i2c_unlock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER); - -		if (ret < 0) -			dev_err(i2c->dev, "cannot find frequency (%d)\n", ret); -		else -			dev_info(i2c->dev, "setting freq %d\n", got); -	} - -	return 0; -} - -static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) -{ -	i2c->freq_transition.notifier_call = s3c24xx_i2c_cpufreq_transition; - -	return cpufreq_register_notifier(&i2c->freq_transition, -					 CPUFREQ_TRANSITION_NOTIFIER); -} - -static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) -{ -	cpufreq_unregister_notifier(&i2c->freq_transition, -				    CPUFREQ_TRANSITION_NOTIFIER); -} - -#else -static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) -{ -	return 0; -} - -static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) -{ -} -#endif -  #ifdef CONFIG_OF  static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)  { @@ -1152,13 +1090,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)  		}  	} -	ret = s3c24xx_i2c_register_cpufreq(i2c); -	if (ret < 0) { -		dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); -		clk_unprepare(i2c->clk); -		return ret; -	} -  	/*  	 * Note, previous versions of the driver used i2c_add_adapter()  	 * to add the bus at any number. We now pass the bus number via @@ -1175,7 +1106,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)  	ret = i2c_add_numbered_adapter(&i2c->adap);  	if (ret < 0) {  		pm_runtime_disable(&pdev->dev); -		s3c24xx_i2c_deregister_cpufreq(i2c);  		clk_unprepare(i2c->clk);  		return ret;  	} @@ -1192,8 +1122,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)  	pm_runtime_disable(&pdev->dev); -	s3c24xx_i2c_deregister_cpufreq(i2c); -  	i2c_del_adapter(&i2c->adap);  	return 0; diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index 88482316d22a..f823913b75a6 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -740,7 +740,6 @@ static int st_i2c_xfer(struct i2c_adapter *i2c_adap,  	return (ret < 0) ? ret : i;  } -#ifdef CONFIG_PM_SLEEP  static int st_i2c_suspend(struct device *dev)  {  	struct st_i2c_dev *i2c_dev = dev_get_drvdata(dev); @@ -762,11 +761,7 @@ static int st_i2c_resume(struct device *dev)  	return 0;  } -static SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume); -#define ST_I2C_PM	(&st_i2c_pm) -#else -#define ST_I2C_PM	NULL -#endif +static DEFINE_SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume);  static u32 st_i2c_func(struct i2c_adapter *adap)  { @@ -901,7 +896,7 @@ static struct platform_driver st_i2c_driver = {  	.driver = {  		.name = "st-i2c",  		.of_match_table = st_i2c_match, -		.pm = ST_I2C_PM, +		.pm = pm_sleep_ptr(&st_i2c_pm),  	},  	.probe = st_i2c_probe,  	.remove = st_i2c_remove, diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index bee5a2ef1f22..dbb792fc197e 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -32,6 +32,8 @@  #include <linux/pm_runtime.h>  #define DRIVER_NAME "xiic-i2c" +#define DYNAMIC_MODE_READ_BROKEN_BIT	BIT(0) +#define SMBUS_BLOCK_READ_MIN_LEN	3  enum xilinx_i2c_state {  	STATE_DONE, @@ -44,6 +46,12 @@ enum xiic_endian {  	BIG  }; +enum i2c_scl_freq { +	REG_VALUES_100KHZ = 0, +	REG_VALUES_400KHZ = 1, +	REG_VALUES_1MHZ = 2 +}; +  /**   * struct xiic_i2c - Internal representation of the XIIC I2C bus   * @dev: Pointer to device structure @@ -60,6 +68,12 @@ enum xiic_endian {   * @clk: Pointer to AXI4-lite input clock   * @state: See STATE_   * @singlemaster: Indicates bus is single master + * @dynamic: Mode of controller + * @prev_msg_tx: Previous message is Tx + * @quirks: To hold platform specific bug info + * @smbus_block_read: Flag to handle block read + * @input_clk: Input clock to I2C controller + * @i2c_clk: I2C SCL frequency   */  struct xiic_i2c {  	struct device *dev; @@ -76,6 +90,39 @@ struct xiic_i2c {  	struct clk *clk;  	enum xilinx_i2c_state state;  	bool singlemaster; +	bool dynamic; +	bool prev_msg_tx; +	u32 quirks; +	bool smbus_block_read; +	unsigned long input_clk; +	unsigned int i2c_clk; +}; + +struct xiic_version_data { +	u32 quirks; +}; + +/** + * struct timing_regs - AXI I2C timing registers that depend on I2C spec + * @tsusta: setup time for a repeated START condition + * @tsusto: setup time for a STOP condition + * @thdsta: hold time for a repeated START condition + * @tsudat: setup time for data + * @tbuf: bus free time between STOP and START + */ +struct timing_regs { +	unsigned int tsusta; +	unsigned int tsusto; +	unsigned int thdsta; +	unsigned int tsudat; +	unsigned int tbuf; +}; + +/* Reg values in ns derived from I2C spec and AXI I2C PG for different frequencies */ +static const struct timing_regs timing_reg_values[] = { +	{ 5700, 5000, 4300, 550, 5000 }, /* Reg values for 100KHz */ +	{ 900, 900, 900, 400, 1600 },    /* Reg values for 400KHz */ +	{ 380, 380, 380, 170, 620 },     /* Reg values for 1MHz   */  };  #define XIIC_MSB_OFFSET 0 @@ -96,6 +143,19 @@ struct xiic_i2c {  #define XIIC_RFD_REG_OFFSET  (0x20 + XIIC_REG_OFFSET)	/* Rx FIFO Depth reg  */  #define XIIC_GPO_REG_OFFSET  (0x24 + XIIC_REG_OFFSET)	/* Output Register    */ +/* + * Timing register offsets from RegisterBase. These are used only for + * setting i2c clock frequency for the line. + */ +#define XIIC_TSUSTA_REG_OFFSET (0x28 + XIIC_REG_OFFSET) /* TSUSTA Register */ +#define XIIC_TSUSTO_REG_OFFSET (0x2C + XIIC_REG_OFFSET) /* TSUSTO Register */ +#define XIIC_THDSTA_REG_OFFSET (0x30 + XIIC_REG_OFFSET) /* THDSTA Register */ +#define XIIC_TSUDAT_REG_OFFSET (0x34 + XIIC_REG_OFFSET) /* TSUDAT Register */ +#define XIIC_TBUF_REG_OFFSET   (0x38 + XIIC_REG_OFFSET) /* TBUF Register */ +#define XIIC_THIGH_REG_OFFSET  (0x3C + XIIC_REG_OFFSET) /* THIGH Register */ +#define XIIC_TLOW_REG_OFFSET   (0x40 + XIIC_REG_OFFSET) /* TLOW Register */ +#define XIIC_THDDAT_REG_OFFSET (0x44 + XIIC_REG_OFFSET) /* THDDAT Register */ +  /* Control Register masks */  #define XIIC_CR_ENABLE_DEVICE_MASK        0x01	/* Device enable = 1      */  #define XIIC_CR_TX_FIFO_RESET_MASK        0x02	/* Transmit FIFO reset=1  */ @@ -143,6 +203,9 @@ struct xiic_i2c {  #define XIIC_TX_DYN_START_MASK            0x0100 /* 1 = Set dynamic start */  #define XIIC_TX_DYN_STOP_MASK             0x0200 /* 1 = Set dynamic stop */ +/* Dynamic mode constants */ +#define MAX_READ_LENGTH_DYNAMIC                255 /* Max length for dynamic read */ +  /*   * The following constants define the register offsets for the Interrupt   * registers. There are some holes in the memory map for reserved addresses @@ -275,12 +338,120 @@ static int xiic_clear_rx_fifo(struct xiic_i2c *i2c)  	return 0;  } +static int xiic_wait_tx_empty(struct xiic_i2c *i2c) +{ +	u8 isr; +	unsigned long timeout; + +	timeout = jiffies + XIIC_I2C_TIMEOUT; +	for (isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); +		!(isr & XIIC_INTR_TX_EMPTY_MASK); +			isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET)) { +		if (time_after(jiffies, timeout)) { +			dev_err(i2c->dev, "Timeout waiting at Tx empty\n"); +			return -ETIMEDOUT; +		} +	} + +	return 0; +} + +/** + * xiic_setclk - Sets the configured clock rate + * @i2c: Pointer to the xiic device structure + * + * The timing register values are calculated according to the input clock + * frequency and configured scl frequency. For details, please refer the + * AXI I2C PG and NXP I2C Spec. + * Supported frequencies are 100KHz, 400KHz and 1MHz. + * + * Return: 0 on success (Supported frequency selected or not configurable in SW) + *        -EINVAL on failure (scl frequency not supported or THIGH is 0) + */ +static int xiic_setclk(struct xiic_i2c *i2c) +{ +	unsigned int clk_in_mhz; +	unsigned int index = 0; +	u32 reg_val; + +	dev_dbg(i2c->adap.dev.parent, +		"%s entry, i2c->input_clk: %ld, i2c->i2c_clk: %d\n", +		__func__, i2c->input_clk, i2c->i2c_clk); + +	/* If not specified in DT, do not configure in SW. Rely only on Vivado design */ +	if (!i2c->i2c_clk || !i2c->input_clk) +		return 0; + +	clk_in_mhz = DIV_ROUND_UP(i2c->input_clk, 1000000); + +	switch (i2c->i2c_clk) { +	case I2C_MAX_FAST_MODE_PLUS_FREQ: +		index = REG_VALUES_1MHZ; +		break; +	case I2C_MAX_FAST_MODE_FREQ: +		index = REG_VALUES_400KHZ; +		break; +	case I2C_MAX_STANDARD_MODE_FREQ: +		index = REG_VALUES_100KHZ; +		break; +	default: +		dev_warn(i2c->adap.dev.parent, "Unsupported scl frequency\n"); +		return -EINVAL; +	} + +	/* +	 * Value to be stored in a register is the number of clock cycles required +	 * for the time duration. So the time is divided by the input clock time +	 * period to get the number of clock cycles required. Refer Xilinx AXI I2C +	 * PG document and I2C specification for further details. +	 */ + +	/* THIGH - Depends on SCL clock frequency(i2c_clk) as below */ +	reg_val = (DIV_ROUND_UP(i2c->input_clk, 2 * i2c->i2c_clk)) - 7; +	if (reg_val == 0) +		return -EINVAL; + +	xiic_setreg32(i2c, XIIC_THIGH_REG_OFFSET, reg_val - 1); + +	/* TLOW - Value same as THIGH */ +	xiic_setreg32(i2c, XIIC_TLOW_REG_OFFSET, reg_val - 1); + +	/* TSUSTA */ +	reg_val = (timing_reg_values[index].tsusta * clk_in_mhz) / 1000; +	xiic_setreg32(i2c, XIIC_TSUSTA_REG_OFFSET, reg_val - 1); + +	/* TSUSTO */ +	reg_val = (timing_reg_values[index].tsusto * clk_in_mhz) / 1000; +	xiic_setreg32(i2c, XIIC_TSUSTO_REG_OFFSET, reg_val - 1); + +	/* THDSTA */ +	reg_val = (timing_reg_values[index].thdsta * clk_in_mhz) / 1000; +	xiic_setreg32(i2c, XIIC_THDSTA_REG_OFFSET, reg_val - 1); + +	/* TSUDAT */ +	reg_val = (timing_reg_values[index].tsudat * clk_in_mhz) / 1000; +	xiic_setreg32(i2c, XIIC_TSUDAT_REG_OFFSET, reg_val - 1); + +	/* TBUF */ +	reg_val = (timing_reg_values[index].tbuf * clk_in_mhz) / 1000; +	xiic_setreg32(i2c, XIIC_TBUF_REG_OFFSET, reg_val - 1); + +	/* THDDAT */ +	xiic_setreg32(i2c, XIIC_THDDAT_REG_OFFSET, 1); + +	return 0; +} +  static int xiic_reinit(struct xiic_i2c *i2c)  {  	int ret;  	xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); +	ret = xiic_setclk(i2c); +	if (ret) +		return ret; +  	/* Set receive Fifo depth to maximum (zero based). */  	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); @@ -314,15 +485,72 @@ static void xiic_deinit(struct xiic_i2c *i2c)  	xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK);  } +static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c) +{ +	u8 rxmsg_len, rfd_set = 0; + +	/* +	 * Clear the I2C_M_RECV_LEN flag to avoid setting +	 * message length again +	 */ +	i2c->rx_msg->flags &= ~I2C_M_RECV_LEN; + +	/* Set smbus_block_read flag to identify in isr */ +	i2c->smbus_block_read = true; + +	/* Read byte from rx fifo and set message length */ +	rxmsg_len = xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); + +	i2c->rx_msg->buf[i2c->rx_pos++] = rxmsg_len; + +	/* Check if received length is valid */ +	if (rxmsg_len <= I2C_SMBUS_BLOCK_MAX) { +		/* Set Receive fifo depth */ +		if (rxmsg_len > IIC_RX_FIFO_DEPTH) { +			/* +			 * When Rx msg len greater than or equal to Rx fifo capacity +			 * Receive fifo depth should set to Rx fifo capacity minus 1 +			 */ +			rfd_set = IIC_RX_FIFO_DEPTH - 1; +			i2c->rx_msg->len = rxmsg_len + 1; +		} else if ((rxmsg_len == 1) || +			(rxmsg_len == 0)) { +			/* +			 * Minimum of 3 bytes required to exit cleanly. 1 byte +			 * already received, Second byte is being received. Have +			 * to set NACK in read_rx before receiving the last byte +			 */ +			rfd_set = 0; +			i2c->rx_msg->len = SMBUS_BLOCK_READ_MIN_LEN; +		} else { +			/* +			 * When Rx msg len less than Rx fifo capacity +			 * Receive fifo depth should set to Rx msg len minus 2 +			 */ +			rfd_set = rxmsg_len - 2; +			i2c->rx_msg->len = rxmsg_len + 1; +		} +		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set); + +		return; +	} + +	/* Invalid message length, trigger STATE_ERROR with tx_msg_len in ISR */ +	i2c->tx_msg->len = 3; +	i2c->smbus_block_read = false; +	dev_err(i2c->adap.dev.parent, "smbus_block_read Invalid msg length\n"); +} +  static void xiic_read_rx(struct xiic_i2c *i2c)  { -	u8 bytes_in_fifo; +	u8 bytes_in_fifo, cr = 0, bytes_to_read = 0; +	u32 bytes_rem = 0;  	int i;  	bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1;  	dev_dbg(i2c->adap.dev.parent, -		"%s entry, bytes in fifo: %d, msg: %d, SR: 0x%x, CR: 0x%x\n", +		"%s entry, bytes in fifo: %d, rem: %d, SR: 0x%x, CR: 0x%x\n",  		__func__, bytes_in_fifo, xiic_rx_space(i2c),  		xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),  		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); @@ -330,13 +558,58 @@ static void xiic_read_rx(struct xiic_i2c *i2c)  	if (bytes_in_fifo > xiic_rx_space(i2c))  		bytes_in_fifo = xiic_rx_space(i2c); -	for (i = 0; i < bytes_in_fifo; i++) +	bytes_to_read = bytes_in_fifo; + +	if (!i2c->dynamic) { +		bytes_rem = xiic_rx_space(i2c) - bytes_in_fifo; + +		/* Set msg length if smbus_block_read */ +		if (i2c->rx_msg->flags & I2C_M_RECV_LEN) { +			xiic_smbus_block_read_setup(i2c); +			return; +		} + +		if (bytes_rem > IIC_RX_FIFO_DEPTH) { +			bytes_to_read = bytes_in_fifo; +		} else if (bytes_rem > 1) { +			bytes_to_read = bytes_rem - 1; +		} else if (bytes_rem == 1) { +			bytes_to_read = 1; +			/* Set NACK in CR to indicate slave transmitter */ +			cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); +			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr | +					XIIC_CR_NO_ACK_MASK); +		} else if (bytes_rem == 0) { +			bytes_to_read = bytes_in_fifo; + +			/* Generate stop on the bus if it is last message */ +			if (i2c->nmsgs == 1) { +				cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); +				xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & +						~XIIC_CR_MSMS_MASK); +			} + +			/* Make TXACK=0, clean up for next transaction */ +			cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); +			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & +					~XIIC_CR_NO_ACK_MASK); +		} +	} + +	/* Read the fifo */ +	for (i = 0; i < bytes_to_read; i++) {  		i2c->rx_msg->buf[i2c->rx_pos++] =  			xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); +	} -	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, -		(xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ? -		IIC_RX_FIFO_DEPTH - 1 :  xiic_rx_space(i2c) - 1); +	if (i2c->dynamic) { +		u8 bytes; + +		/* Receive remaining bytes if less than fifo depth */ +		bytes = min_t(u8, xiic_rx_space(i2c), IIC_RX_FIFO_DEPTH); +		bytes--; +		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, bytes); +	}  }  static int xiic_tx_fifo_space(struct xiic_i2c *i2c) @@ -360,7 +633,22 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c)  		if (!xiic_tx_space(i2c) && i2c->nmsgs == 1) {  			/* last message in transfer -> STOP */ -			data |= XIIC_TX_DYN_STOP_MASK; +			if (i2c->dynamic) { +				data |= XIIC_TX_DYN_STOP_MASK; +			} else { +				u8 cr; +				int status; + +				/* Wait till FIFO is empty so STOP is sent last */ +				status = xiic_wait_tx_empty(i2c); +				if (status) +					return; + +				/* Write to CR to stop */ +				cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); +				xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & +					     ~XIIC_CR_MSMS_MASK); +			}  			dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__);  		}  		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); @@ -401,7 +689,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id)  	dev_dbg(i2c->adap.dev.parent, "%s: SR: 0x%x, msg: %p, nmsgs: %d\n",  		__func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),  		i2c->tx_msg, i2c->nmsgs); - +	dev_dbg(i2c->adap.dev.parent, "%s, ISR: 0x%x, CR: 0x%x\n", +		__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), +		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));  	/* Service requesting interrupt */  	if ((pend & XIIC_INTR_ARB_LOST_MASK) || @@ -512,6 +802,12 @@ static irqreturn_t xiic_process(int irq, void *dev_id)  		/* The bus is not busy, disable BusNotBusy interrupt */  		xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK); +		if (i2c->tx_msg && i2c->smbus_block_read) { +			i2c->smbus_block_read = false; +			/* Set requested message len=1 to indicate STATE_DONE */ +			i2c->tx_msg->len = 1; +		} +  		if (!i2c->tx_msg)  			goto out; @@ -579,31 +875,113 @@ static int xiic_busy(struct xiic_i2c *i2c)  static void xiic_start_recv(struct xiic_i2c *i2c)  {  	u16 rx_watermark; +	u8 cr = 0, rfd_set = 0;  	struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg; -	/* Clear and enable Rx full interrupt. */ -	xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK); +	dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", +		__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), +		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); -	/* we want to get all but last byte, because the TX_ERROR IRQ is used -	 * to inidicate error ACK on the address, and negative ack on the last -	 * received byte, so to not mix them receive all but last. -	 * In the case where there is only one byte to receive -	 * we can check if ERROR and RX full is set at the same time -	 */ -	rx_watermark = msg->len; -	if (rx_watermark > IIC_RX_FIFO_DEPTH) -		rx_watermark = IIC_RX_FIFO_DEPTH; -	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, (u8)(rx_watermark - 1)); +	/* Disable Tx interrupts */ +	xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK | XIIC_INTR_TX_EMPTY_MASK); + +	if (i2c->dynamic) { +		u8 bytes; +		u16 val; + +		/* Clear and enable Rx full interrupt. */ +		xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | +				XIIC_INTR_TX_ERROR_MASK); + +		/* +		 * We want to get all but last byte, because the TX_ERROR IRQ +		 * is used to indicate error ACK on the address, and +		 * negative ack on the last received byte, so to not mix +		 * them receive all but last. +		 * In the case where there is only one byte to receive +		 * we can check if ERROR and RX full is set at the same time +		 */ +		rx_watermark = msg->len; +		bytes = min_t(u8, rx_watermark, IIC_RX_FIFO_DEPTH); + +		if (rx_watermark > 0) +			bytes--; +		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, bytes); -	if (!(msg->flags & I2C_M_NOSTART))  		/* write the address */  		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, -			i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK); +			      i2c_8bit_addr_from_msg(msg) | +			      XIIC_TX_DYN_START_MASK); + +		/* If last message, include dynamic stop bit with length */ +		val = (i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0; +		val |= msg->len; + +		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, val); + +		xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); +	} else { +		/* +		 * If previous message is Tx, make sure that Tx FIFO is empty +		 * before starting a new transfer as the repeated start in +		 * standard mode can corrupt the transaction if there are +		 * still bytes to be transmitted in FIFO +		 */ +		if (i2c->prev_msg_tx) { +			int status; + +			status = xiic_wait_tx_empty(i2c); +			if (status) +				return; +		} -	xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); +		cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); -	xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, -		msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0)); +		/* Set Receive fifo depth */ +		rx_watermark = msg->len; +		if (rx_watermark > IIC_RX_FIFO_DEPTH) { +			rfd_set = IIC_RX_FIFO_DEPTH - 1; +		} else if (rx_watermark == 1) { +			rfd_set = rx_watermark - 1; + +			/* Set No_ACK, except for smbus_block_read */ +			if (!(i2c->rx_msg->flags & I2C_M_RECV_LEN)) { +				/* Handle single byte transfer separately */ +				cr |= XIIC_CR_NO_ACK_MASK; +			} +		} else if (rx_watermark == 0) { +			rfd_set = rx_watermark; +		} else { +			rfd_set = rx_watermark - 2; +		} +		/* Check if RSTA should be set */ +		if (cr & XIIC_CR_MSMS_MASK) { +			/* Already a master, RSTA should be set */ +			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr | +					XIIC_CR_REPEATED_START_MASK) & +					~(XIIC_CR_DIR_IS_TX_MASK)); +		} + +		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set); + +		/* Clear and enable Rx full and transmit complete interrupts */ +		xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | +				XIIC_INTR_TX_ERROR_MASK); + +		/* Write the address */ +		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, +			      i2c_8bit_addr_from_msg(msg)); + +		/* Write to Control Register,to start transaction in Rx mode */ +		if ((cr & XIIC_CR_MSMS_MASK) == 0) { +			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr | +					XIIC_CR_MSMS_MASK) +					& ~(XIIC_CR_DIR_IS_TX_MASK)); +		} +		dev_dbg(i2c->adap.dev.parent, "%s end, ISR: 0x%x, CR: 0x%x\n", +			__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), +			xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); +	}  	if (i2c->nmsgs == 1)  		/* very last, enable bus not busy as well */ @@ -611,10 +989,17 @@ static void xiic_start_recv(struct xiic_i2c *i2c)  	/* the message is tx:ed */  	i2c->tx_pos = msg->len; + +	/* Enable interrupts */ +	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); + +	i2c->prev_msg_tx = false;  }  static void xiic_start_send(struct xiic_i2c *i2c)  { +	u8 cr = 0; +	u16 data;  	struct i2c_msg *msg = i2c->tx_msg;  	dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d", @@ -623,24 +1008,70 @@ static void xiic_start_send(struct xiic_i2c *i2c)  		__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),  		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); -	if (!(msg->flags & I2C_M_NOSTART)) { +	if (i2c->dynamic) {  		/* write the address */ -		u16 data = i2c_8bit_addr_from_msg(msg) | -			XIIC_TX_DYN_START_MASK; -		if ((i2c->nmsgs == 1) && msg->len == 0) +		data = i2c_8bit_addr_from_msg(msg) | +				XIIC_TX_DYN_START_MASK; + +		if (i2c->nmsgs == 1 && msg->len == 0)  			/* no data and last message -> add STOP */  			data |= XIIC_TX_DYN_STOP_MASK;  		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); -	} -	/* Clear any pending Tx empty, Tx Error and then enable them. */ -	xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK | -		XIIC_INTR_BNB_MASK | -		((i2c->nmsgs > 1 || xiic_tx_space(i2c)) ? -			XIIC_INTR_TX_HALF_MASK : 0)); +		/* Clear any pending Tx empty, Tx Error and then enable them */ +		xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | +				XIIC_INTR_TX_ERROR_MASK | +				XIIC_INTR_BNB_MASK | +				((i2c->nmsgs > 1 || xiic_tx_space(i2c)) ? +				XIIC_INTR_TX_HALF_MASK : 0)); + +		xiic_fill_tx_fifo(i2c); +	} else { +		/* +		 * If previous message is Tx, make sure that Tx FIFO is empty +		 * before starting a new transfer as the repeated start in +		 * standard mode can corrupt the transaction if there are +		 * still bytes to be transmitted in FIFO +		 */ +		if (i2c->prev_msg_tx) { +			int status; + +			status = xiic_wait_tx_empty(i2c); +			if (status) +				return; +		} +		/* Check if RSTA should be set */ +		cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); +		if (cr & XIIC_CR_MSMS_MASK) { +			/* Already a master, RSTA should be set */ +			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr | +					XIIC_CR_REPEATED_START_MASK | +					XIIC_CR_DIR_IS_TX_MASK) & +					~(XIIC_CR_NO_ACK_MASK)); +		} + +		/* Write address to FIFO */ +		data = i2c_8bit_addr_from_msg(msg); +		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); + +		/* Fill fifo */ +		xiic_fill_tx_fifo(i2c); -	xiic_fill_tx_fifo(i2c); +		if ((cr & XIIC_CR_MSMS_MASK) == 0) { +			/* Start Tx by writing to CR */ +			cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); +			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr | +					XIIC_CR_MSMS_MASK | +					XIIC_CR_DIR_IS_TX_MASK); +		} + +		/* Clear any pending Tx empty, Tx Error and then enable them */ +		xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | +				XIIC_INTR_TX_ERROR_MASK | +				XIIC_INTR_BNB_MASK); +	} +	i2c->prev_msg_tx = true;  }  static void __xiic_start_xfer(struct xiic_i2c *i2c) @@ -666,7 +1097,8 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c)  static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num)  { -	int ret; +	bool broken_read, max_read_len, smbus_blk_read; +	int ret, count;  	mutex_lock(&i2c->lock); @@ -679,6 +1111,34 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num)  	i2c->nmsgs = num;  	init_completion(&i2c->completion); +	/* Decide standard mode or Dynamic mode */ +	i2c->dynamic = true; + +	/* Initialize prev message type */ +	i2c->prev_msg_tx = false; + +	/* +	 * Scan through nmsgs, use dynamic mode when none of the below three +	 * conditions occur. We need standard mode even if one condition holds +	 * true in the entire array of messages in a single transfer. +	 * If read transaction as dynamic mode is broken for delayed reads +	 * in xlnx,axi-iic-2.0 / xlnx,xps-iic-2.00.a IP versions. +	 * If read length is > 255 bytes. +	 * If smbus_block_read transaction. +	 */ +	for (count = 0; count < i2c->nmsgs; count++) { +		broken_read = (i2c->quirks & DYNAMIC_MODE_READ_BROKEN_BIT) && +				(i2c->tx_msg[count].flags & I2C_M_RD); +		max_read_len = (i2c->tx_msg[count].flags & I2C_M_RD) && +				(i2c->tx_msg[count].len > MAX_READ_LENGTH_DYNAMIC); +		smbus_blk_read = (i2c->tx_msg[count].flags & I2C_M_RECV_LEN); + +		if (broken_read || max_read_len || smbus_blk_read) { +			i2c->dynamic = false; +			break; +		} +	} +  	ret = xiic_reinit(i2c);  	if (!ret)  		__xiic_start_xfer(i2c); @@ -714,10 +1174,6 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  		i2c->rx_msg = NULL;  		i2c->nmsgs = 0;  		err = -ETIMEDOUT; -	} else if (err < 0) {	/* Completion error */ -		i2c->tx_msg = NULL; -		i2c->rx_msg = NULL; -		i2c->nmsgs = 0;  	} else {  		err = (i2c->state == STATE_DONE) ? num : -EIO;  	} @@ -729,7 +1185,7 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)  static u32 xiic_func(struct i2c_adapter *adap)  { -	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;  }  static const struct i2c_algorithm xiic_algorithm = { @@ -737,21 +1193,30 @@ static const struct i2c_algorithm xiic_algorithm = {  	.functionality = xiic_func,  }; -static const struct i2c_adapter_quirks xiic_quirks = { -	.max_read_len = 255, -}; -  static const struct i2c_adapter xiic_adapter = {  	.owner = THIS_MODULE,  	.class = I2C_CLASS_DEPRECATED,  	.algo = &xiic_algorithm, -	.quirks = &xiic_quirks,  }; +static const struct xiic_version_data xiic_2_00 = { +	.quirks = DYNAMIC_MODE_READ_BROKEN_BIT, +}; + +#if defined(CONFIG_OF) +static const struct of_device_id xiic_of_match[] = { +	{ .compatible = "xlnx,xps-iic-2.00.a", .data = &xiic_2_00 }, +	{ .compatible = "xlnx,axi-iic-2.1", }, +	{}, +}; +MODULE_DEVICE_TABLE(of, xiic_of_match); +#endif +  static int xiic_i2c_probe(struct platform_device *pdev)  {  	struct xiic_i2c *i2c;  	struct xiic_i2c_platform_data *pdata; +	const struct of_device_id *match;  	struct resource *res;  	int ret, irq;  	u8 i; @@ -761,6 +1226,13 @@ static int xiic_i2c_probe(struct platform_device *pdev)  	if (!i2c)  		return -ENOMEM; +	match = of_match_node(xiic_of_match, pdev->dev.of_node); +	if (match && match->data) { +		const struct xiic_version_data *data = match->data; + +		i2c->quirks = data->quirks; +	} +  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	i2c->base = devm_ioremap_resource(&pdev->dev, res);  	if (IS_ERR(i2c->base)) @@ -798,6 +1270,15 @@ static int xiic_i2c_probe(struct platform_device *pdev)  	pm_runtime_use_autosuspend(i2c->dev);  	pm_runtime_set_active(i2c->dev);  	pm_runtime_enable(i2c->dev); + +	/* SCL frequency configuration */ +	i2c->input_clk = clk_get_rate(i2c->clk); +	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", +				   &i2c->i2c_clk); +	/* If clock-frequency not specified in DT, do not configure in SW */ +	if (ret || i2c->i2c_clk > I2C_MAX_FAST_MODE_PLUS_FREQ) +		i2c->i2c_clk = 0; +  	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,  					xiic_process, IRQF_ONESHOT,  					pdev->name, i2c); @@ -841,6 +1322,9 @@ static int xiic_i2c_probe(struct platform_device *pdev)  			i2c_new_client_device(&i2c->adap, pdata->devices + i);  	} +	dev_dbg(&pdev->dev, "mmio %08lx irq %d scl clock frequency %d\n", +		(unsigned long)res->start, irq, i2c->i2c_clk); +  	return 0;  err_clk_dis: @@ -875,14 +1359,6 @@ static int xiic_i2c_remove(struct platform_device *pdev)  	return 0;  } -#if defined(CONFIG_OF) -static const struct of_device_id xiic_of_match[] = { -	{ .compatible = "xlnx,xps-iic-2.00.a", }, -	{}, -}; -MODULE_DEVICE_TABLE(of, xiic_of_match); -#endif -  static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev)  {  	struct xiic_i2c *i2c = dev_get_drvdata(dev); diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c index 4dd777cc0c89..d6037a328669 100644 --- a/drivers/i2c/i2c-core-acpi.c +++ b/drivers/i2c/i2c-core-acpi.c @@ -442,18 +442,7 @@ EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle);  static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)  { -	struct device *dev; -	struct i2c_client *client; - -	dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev); -	if (!dev) -		return NULL; - -	client = i2c_verify_client(dev); -	if (!client) -		put_device(dev); - -	return client; +	return i2c_find_device_by_fwnode(acpi_fwnode_handle(adev));  }  static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value, diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 087e480b624c..ae3af738b03f 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -34,6 +34,7 @@  #include <linux/of.h>  #include <linux/of_irq.h>  #include <linux/pinctrl/consumer.h> +#include <linux/pinctrl/devinfo.h>  #include <linux/pm_domain.h>  #include <linux/pm_runtime.h>  #include <linux/pm_wakeirq.h> @@ -136,9 +137,9 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)  	return 0;  } -static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int i2c_device_uevent(const struct device *dev, struct kobj_uevent_env *env)  { -	struct i2c_client *client = to_i2c_client(dev); +	const struct i2c_client *client = to_i2c_client(dev);  	int rc;  	rc = of_device_uevent_modalias(dev, env); @@ -282,7 +283,9 @@ static void i2c_gpio_init_pinctrl_recovery(struct i2c_adapter *adap)  {  	struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;  	struct device *dev = &adap->dev; -	struct pinctrl *p = bri->pinctrl; +	struct pinctrl *p = bri->pinctrl ?: dev_pinctrl(dev->parent); + +	bri->pinctrl = p;  	/*  	 * we can't change states without pinctrl, so remove the states if @@ -558,15 +561,8 @@ static int i2c_device_probe(struct device *dev)  		goto err_detach_pm_domain;  	} -	/* -	 * When there are no more users of probe(), -	 * rename probe_new to probe. -	 */ -	if (driver->probe_new) -		status = driver->probe_new(client); -	else if (driver->probe) -		status = driver->probe(client, -				       i2c_match_id(driver->id_table, client)); +	if (driver->probe) +		status = driver->probe(client);  	else  		status = -EINVAL; @@ -1012,6 +1008,35 @@ void i2c_unregister_device(struct i2c_client *client)  }  EXPORT_SYMBOL_GPL(i2c_unregister_device); +/** + * i2c_find_device_by_fwnode() - find an i2c_client for the fwnode + * @fwnode: &struct fwnode_handle corresponding to the &struct i2c_client + * + * Look up and return the &struct i2c_client corresponding to the @fwnode. + * If no client can be found, or @fwnode is NULL, this returns NULL. + * + * The user must call put_device(&client->dev) once done with the i2c client. + */ +struct i2c_client *i2c_find_device_by_fwnode(struct fwnode_handle *fwnode) +{ +	struct i2c_client *client; +	struct device *dev; + +	if (!fwnode) +		return NULL; + +	dev = bus_find_device_by_fwnode(&i2c_bus_type, fwnode); +	if (!dev) +		return NULL; + +	client = i2c_verify_client(dev); +	if (!client) +		put_device(dev); + +	return client; +} +EXPORT_SYMBOL(i2c_find_device_by_fwnode); +  static const struct i2c_device_id dummy_id[] = {  	{ "dummy", 0 }, @@ -1025,7 +1050,7 @@ static int dummy_probe(struct i2c_client *client)  static struct i2c_driver dummy_driver = {  	.driver.name	= "dummy", -	.probe_new	= dummy_probe, +	.probe		= dummy_probe,  	.id_table	= dummy_id,  }; @@ -1761,6 +1786,75 @@ int devm_i2c_add_adapter(struct device *dev, struct i2c_adapter *adapter)  }  EXPORT_SYMBOL_GPL(devm_i2c_add_adapter); +static int i2c_dev_or_parent_fwnode_match(struct device *dev, const void *data) +{ +	if (dev_fwnode(dev) == data) +		return 1; + +	if (dev->parent && dev_fwnode(dev->parent) == data) +		return 1; + +	return 0; +} + +/** + * i2c_find_adapter_by_fwnode() - find an i2c_adapter for the fwnode + * @fwnode: &struct fwnode_handle corresponding to the &struct i2c_adapter + * + * Look up and return the &struct i2c_adapter corresponding to the @fwnode. + * If no adapter can be found, or @fwnode is NULL, this returns NULL. + * + * The user must call put_device(&adapter->dev) once done with the i2c adapter. + */ +struct i2c_adapter *i2c_find_adapter_by_fwnode(struct fwnode_handle *fwnode) +{ +	struct i2c_adapter *adapter; +	struct device *dev; + +	if (!fwnode) +		return NULL; + +	dev = bus_find_device(&i2c_bus_type, NULL, fwnode, +			      i2c_dev_or_parent_fwnode_match); +	if (!dev) +		return NULL; + +	adapter = i2c_verify_adapter(dev); +	if (!adapter) +		put_device(dev); + +	return adapter; +} +EXPORT_SYMBOL(i2c_find_adapter_by_fwnode); + +/** + * i2c_get_adapter_by_fwnode() - find an i2c_adapter for the fwnode + * @fwnode: &struct fwnode_handle corresponding to the &struct i2c_adapter + * + * Look up and return the &struct i2c_adapter corresponding to the @fwnode, + * and increment the adapter module's use count. If no adapter can be found, + * or @fwnode is NULL, this returns NULL. + * + * The user must call i2c_put_adapter(adapter) once done with the i2c adapter. + * Note that this is different from i2c_find_adapter_by_node(). + */ +struct i2c_adapter *i2c_get_adapter_by_fwnode(struct fwnode_handle *fwnode) +{ +	struct i2c_adapter *adapter; + +	adapter = i2c_find_adapter_by_fwnode(fwnode); +	if (!adapter) +		return NULL; + +	if (!try_module_get(adapter->owner)) { +		put_device(&adapter->dev); +		adapter = NULL; +	} + +	return adapter; +} +EXPORT_SYMBOL(i2c_get_adapter_by_fwnode); +  static void i2c_parse_timing(struct device *dev, char *prop_name, u32 *cur_val_p,  			    u32 def_val, bool use_def)  { diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 3ed74aa4b44b..bce6b796e04c 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -113,72 +113,6 @@ void of_i2c_register_devices(struct i2c_adapter *adap)  	of_node_put(bus);  } -static int of_dev_or_parent_node_match(struct device *dev, const void *data) -{ -	if (dev->of_node == data) -		return 1; - -	if (dev->parent) -		return dev->parent->of_node == data; - -	return 0; -} - -/* must call put_device() when done with returned i2c_client device */ -struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) -{ -	struct device *dev; -	struct i2c_client *client; - -	dev = bus_find_device_by_of_node(&i2c_bus_type, node); -	if (!dev) -		return NULL; - -	client = i2c_verify_client(dev); -	if (!client) -		put_device(dev); - -	return client; -} -EXPORT_SYMBOL(of_find_i2c_device_by_node); - -/* must call put_device() when done with returned i2c_adapter device */ -struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) -{ -	struct device *dev; -	struct i2c_adapter *adapter; - -	dev = bus_find_device(&i2c_bus_type, NULL, node, -			      of_dev_or_parent_node_match); -	if (!dev) -		return NULL; - -	adapter = i2c_verify_adapter(dev); -	if (!adapter) -		put_device(dev); - -	return adapter; -} -EXPORT_SYMBOL(of_find_i2c_adapter_by_node); - -/* must call i2c_put_adapter() when done with returned i2c_adapter device */ -struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node) -{ -	struct i2c_adapter *adapter; - -	adapter = of_find_i2c_adapter_by_node(node); -	if (!adapter) -		return NULL; - -	if (!try_module_get(adapter->owner)) { -		put_device(&adapter->dev); -		adapter = NULL; -	} - -	return adapter; -} -EXPORT_SYMBOL(of_get_i2c_adapter_by_node); -  static const struct of_device_id*  i2c_of_match_device_sysfs(const struct of_device_id *matches,  				  struct i2c_client *client) diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index ab0adaa130da..95a0b63ac560 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -646,19 +646,19 @@ static void i2cdev_dev_release(struct device *dev)  	kfree(i2c_dev);  } -static int i2cdev_attach_adapter(struct device *dev, void *dummy) +static int i2cdev_attach_adapter(struct device *dev)  {  	struct i2c_adapter *adap;  	struct i2c_dev *i2c_dev;  	int res;  	if (dev->type != &i2c_adapter_type) -		return 0; +		return NOTIFY_DONE;  	adap = to_i2c_adapter(dev);  	i2c_dev = get_free_i2c_dev(adap);  	if (IS_ERR(i2c_dev)) -		return PTR_ERR(i2c_dev); +		return NOTIFY_DONE;  	cdev_init(&i2c_dev->cdev, &i2cdev_fops);  	i2c_dev->cdev.owner = THIS_MODULE; @@ -678,30 +678,30 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)  		goto err_put_i2c_dev;  	pr_debug("adapter [%s] registered as minor %d\n", adap->name, adap->nr); -	return 0; +	return NOTIFY_OK;  err_put_i2c_dev:  	put_i2c_dev(i2c_dev, false); -	return res; +	return NOTIFY_DONE;  } -static int i2cdev_detach_adapter(struct device *dev, void *dummy) +static int i2cdev_detach_adapter(struct device *dev)  {  	struct i2c_adapter *adap;  	struct i2c_dev *i2c_dev;  	if (dev->type != &i2c_adapter_type) -		return 0; +		return NOTIFY_DONE;  	adap = to_i2c_adapter(dev);  	i2c_dev = i2c_dev_get_by_minor(adap->nr);  	if (!i2c_dev) /* attach_adapter must have failed */ -		return 0; +		return NOTIFY_DONE;  	put_i2c_dev(i2c_dev, true);  	pr_debug("adapter [%s] unregistered\n", adap->name); -	return 0; +	return NOTIFY_OK;  }  static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, @@ -711,12 +711,12 @@ static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,  	switch (action) {  	case BUS_NOTIFY_ADD_DEVICE: -		return i2cdev_attach_adapter(dev, NULL); +		return i2cdev_attach_adapter(dev);  	case BUS_NOTIFY_DEL_DEVICE: -		return i2cdev_detach_adapter(dev, NULL); +		return i2cdev_detach_adapter(dev);  	} -	return 0; +	return NOTIFY_DONE;  }  static struct notifier_block i2cdev_notifier = { @@ -725,6 +725,18 @@ static struct notifier_block i2cdev_notifier = {  /* ------------------------------------------------------------------------- */ +static int __init i2c_dev_attach_adapter(struct device *dev, void *dummy) +{ +	i2cdev_attach_adapter(dev); +	return 0; +} + +static int __exit i2c_dev_detach_adapter(struct device *dev, void *dummy) +{ +	i2cdev_detach_adapter(dev); +	return 0; +} +  /*   * module load/unload record keeping   */ @@ -752,7 +764,7 @@ static int __init i2c_dev_init(void)  		goto out_unreg_class;  	/* Bind to already existing adapters right away */ -	i2c_for_each_dev(NULL, i2cdev_attach_adapter); +	i2c_for_each_dev(NULL, i2c_dev_attach_adapter);  	return 0; @@ -768,7 +780,7 @@ out:  static void __exit i2c_dev_exit(void)  {  	bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier); -	i2c_for_each_dev(NULL, i2cdev_detach_adapter); +	i2c_for_each_dev(NULL, i2c_dev_detach_adapter);  	class_destroy(i2c_dev_class);  	unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);  } diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index 5f25f23c4ff8..5946c0d0aef9 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -207,7 +207,7 @@ static struct i2c_driver i2c_slave_eeprom_driver = {  	.driver = {  		.name = "i2c-slave-eeprom",  	}, -	.probe_new = i2c_slave_eeprom_probe, +	.probe = i2c_slave_eeprom_probe,  	.remove = i2c_slave_eeprom_remove,  	.id_table = i2c_slave_eeprom_id,  }; diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c index 75ee7ebdb614..a49642bbae4b 100644 --- a/drivers/i2c/i2c-slave-testunit.c +++ b/drivers/i2c/i2c-slave-testunit.c @@ -171,7 +171,7 @@ static struct i2c_driver i2c_slave_testunit_driver = {  	.driver = {  		.name = "i2c-slave-testunit",  	}, -	.probe_new = i2c_slave_testunit_probe, +	.probe = i2c_slave_testunit_probe,  	.remove = i2c_slave_testunit_remove,  	.id_table = i2c_slave_testunit_id,  }; diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index cd19546d31fc..138c3f5e0093 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -169,7 +169,7 @@ static struct i2c_driver smbalert_driver = {  	.driver = {  		.name	= "smbus_alert",  	}, -	.probe_new	= smbalert_probe, +	.probe		= smbalert_probe,  	.remove		= smbalert_remove,  	.id_table	= smbalert_ids,  }; diff --git a/drivers/i2c/muxes/i2c-mux-ltc4306.c b/drivers/i2c/muxes/i2c-mux-ltc4306.c index 70835825083f..5a03031519be 100644 --- a/drivers/i2c/muxes/i2c-mux-ltc4306.c +++ b/drivers/i2c/muxes/i2c-mux-ltc4306.c @@ -306,7 +306,7 @@ static struct i2c_driver ltc4306_driver = {  		.name	= "ltc4306",  		.of_match_table = of_match_ptr(ltc4306_of_match),  	}, -	.probe_new	= ltc4306_probe, +	.probe		= ltc4306_probe,  	.remove		= ltc4306_remove,  	.id_table	= ltc4306_id,  }; diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index 09d1d9e67e31..ce0fb69249a8 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -336,7 +336,7 @@ static struct i2c_driver pca9541_driver = {  		   .name = "pca9541",  		   .of_match_table = of_match_ptr(pca9541_of_match),  		   }, -	.probe_new = pca9541_probe, +	.probe = pca9541_probe,  	.remove = pca9541_remove,  	.id_table = pca9541_id,  }; diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 3639e6d7304c..0ccee2ae5720 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -554,7 +554,7 @@ static struct i2c_driver pca954x_driver = {  		.pm	= &pca954x_pm,  		.of_match_table = pca954x_of_match,  	}, -	.probe_new	= pca954x_probe, +	.probe		= pca954x_probe,  	.remove		= pca954x_remove,  	.id_table	= pca954x_id,  };  |