xref: /openbmc/linux/arch/arm/mach-omap2/i2c.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*2b27bdccSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b63128e8STony Lindgren /*
3b63128e8STony Lindgren  * Helper module for board specific I2C bus registration
4b63128e8STony Lindgren  *
5b63128e8STony Lindgren  * Copyright (C) 2009 Nokia Corporation.
6b63128e8STony Lindgren  */
7b63128e8STony Lindgren 
8e4c060dbSTony Lindgren #include "soc.h"
92a296c8fSTony Lindgren #include "omap_hwmod.h"
1025c7d49eSTony Lindgren #include "omap_device.h"
11b63128e8STony Lindgren 
12b13159afSPaul Walmsley #include "prm.h"
13b13159afSPaul Walmsley #include "common.h"
143a8761c0STony Lindgren #include "i2c.h"
15b63128e8STony Lindgren 
166d3c55fdSAvinash.H.M /* In register I2C_CON, Bit 15 is the I2C enable bit */
176d3c55fdSAvinash.H.M #define I2C_EN					BIT(15)
186d3c55fdSAvinash.H.M #define OMAP2_I2C_CON_OFFSET			0x24
196d3c55fdSAvinash.H.M #define OMAP4_I2C_CON_OFFSET			0xA4
206d3c55fdSAvinash.H.M 
213a8761c0STony Lindgren #define MAX_OMAP_I2C_HWMOD_NAME_LEN	16
223a8761c0STony Lindgren 
236d3c55fdSAvinash.H.M /**
246d3c55fdSAvinash.H.M  * omap_i2c_reset - reset the omap i2c module.
256d3c55fdSAvinash.H.M  * @oh: struct omap_hwmod *
266d3c55fdSAvinash.H.M  *
276d3c55fdSAvinash.H.M  * The i2c moudle in omap2, omap3 had a special sequence to reset. The
286d3c55fdSAvinash.H.M  * sequence is:
296d3c55fdSAvinash.H.M  * - Disable the I2C.
306d3c55fdSAvinash.H.M  * - Write to SOFTRESET bit.
316d3c55fdSAvinash.H.M  * - Enable the I2C.
326d3c55fdSAvinash.H.M  * - Poll on the RESETDONE bit.
336d3c55fdSAvinash.H.M  * The sequence is implemented in below function. This is called for 2420,
346d3c55fdSAvinash.H.M  * 2430 and omap3.
356d3c55fdSAvinash.H.M  */
omap_i2c_reset(struct omap_hwmod * oh)366d3c55fdSAvinash.H.M int omap_i2c_reset(struct omap_hwmod *oh)
376d3c55fdSAvinash.H.M {
386d3c55fdSAvinash.H.M 	u32 v;
396d3c55fdSAvinash.H.M 	u16 i2c_con;
406d3c55fdSAvinash.H.M 	int c = 0;
416d3c55fdSAvinash.H.M 
4270451127STony Lindgren 	if (soc_is_omap24xx() || soc_is_omap34xx() || soc_is_am35xx())
436d3c55fdSAvinash.H.M 		i2c_con = OMAP2_I2C_CON_OFFSET;
4470451127STony Lindgren 	else
4570451127STony Lindgren 		i2c_con = OMAP4_I2C_CON_OFFSET;
466d3c55fdSAvinash.H.M 
476d3c55fdSAvinash.H.M 	/* Disable I2C */
486d3c55fdSAvinash.H.M 	v = omap_hwmod_read(oh, i2c_con);
496d3c55fdSAvinash.H.M 	v &= ~I2C_EN;
506d3c55fdSAvinash.H.M 	omap_hwmod_write(v, oh, i2c_con);
516d3c55fdSAvinash.H.M 
526d3c55fdSAvinash.H.M 	/* Write to the SOFTRESET bit */
536d3c55fdSAvinash.H.M 	omap_hwmod_softreset(oh);
546d3c55fdSAvinash.H.M 
556d3c55fdSAvinash.H.M 	/* Enable I2C */
566d3c55fdSAvinash.H.M 	v = omap_hwmod_read(oh, i2c_con);
576d3c55fdSAvinash.H.M 	v |= I2C_EN;
586d3c55fdSAvinash.H.M 	omap_hwmod_write(v, oh, i2c_con);
596d3c55fdSAvinash.H.M 
606d3c55fdSAvinash.H.M 	/* Poll on RESETDONE bit */
616d3c55fdSAvinash.H.M 	omap_test_timeout((omap_hwmod_read(oh,
626d3c55fdSAvinash.H.M 				oh->class->sysc->syss_offs)
636d3c55fdSAvinash.H.M 				& SYSS_RESETDONE_MASK),
646d3c55fdSAvinash.H.M 				MAX_MODULE_SOFTRESET_WAIT, c);
656d3c55fdSAvinash.H.M 
666d3c55fdSAvinash.H.M 	if (c == MAX_MODULE_SOFTRESET_WAIT)
673d0cb73eSJoe Perches 		pr_warn("%s: %s: softreset failed (waited %d usec)\n",
686d3c55fdSAvinash.H.M 			__func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
696d3c55fdSAvinash.H.M 	else
706d3c55fdSAvinash.H.M 		pr_debug("%s: %s: softreset in %d usec\n", __func__,
716d3c55fdSAvinash.H.M 			oh->name, c);
726d3c55fdSAvinash.H.M 
736d3c55fdSAvinash.H.M 	return 0;
746d3c55fdSAvinash.H.M }
75