162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Helper module for board specific I2C bus registration
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2009 Nokia Corporation.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "soc.h"
962306a36Sopenharmony_ci#include "omap_hwmod.h"
1062306a36Sopenharmony_ci#include "omap_device.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "prm.h"
1362306a36Sopenharmony_ci#include "common.h"
1462306a36Sopenharmony_ci#include "i2c.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* In register I2C_CON, Bit 15 is the I2C enable bit */
1762306a36Sopenharmony_ci#define I2C_EN					BIT(15)
1862306a36Sopenharmony_ci#define OMAP2_I2C_CON_OFFSET			0x24
1962306a36Sopenharmony_ci#define OMAP4_I2C_CON_OFFSET			0xA4
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define MAX_OMAP_I2C_HWMOD_NAME_LEN	16
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/**
2462306a36Sopenharmony_ci * omap_i2c_reset - reset the omap i2c module.
2562306a36Sopenharmony_ci * @oh: struct omap_hwmod *
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * The i2c moudle in omap2, omap3 had a special sequence to reset. The
2862306a36Sopenharmony_ci * sequence is:
2962306a36Sopenharmony_ci * - Disable the I2C.
3062306a36Sopenharmony_ci * - Write to SOFTRESET bit.
3162306a36Sopenharmony_ci * - Enable the I2C.
3262306a36Sopenharmony_ci * - Poll on the RESETDONE bit.
3362306a36Sopenharmony_ci * The sequence is implemented in below function. This is called for 2420,
3462306a36Sopenharmony_ci * 2430 and omap3.
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ciint omap_i2c_reset(struct omap_hwmod *oh)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	u32 v;
3962306a36Sopenharmony_ci	u16 i2c_con;
4062306a36Sopenharmony_ci	int c = 0;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (soc_is_omap24xx() || soc_is_omap34xx() || soc_is_am35xx())
4362306a36Sopenharmony_ci		i2c_con = OMAP2_I2C_CON_OFFSET;
4462306a36Sopenharmony_ci	else
4562306a36Sopenharmony_ci		i2c_con = OMAP4_I2C_CON_OFFSET;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* Disable I2C */
4862306a36Sopenharmony_ci	v = omap_hwmod_read(oh, i2c_con);
4962306a36Sopenharmony_ci	v &= ~I2C_EN;
5062306a36Sopenharmony_ci	omap_hwmod_write(v, oh, i2c_con);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/* Write to the SOFTRESET bit */
5362306a36Sopenharmony_ci	omap_hwmod_softreset(oh);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	/* Enable I2C */
5662306a36Sopenharmony_ci	v = omap_hwmod_read(oh, i2c_con);
5762306a36Sopenharmony_ci	v |= I2C_EN;
5862306a36Sopenharmony_ci	omap_hwmod_write(v, oh, i2c_con);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/* Poll on RESETDONE bit */
6162306a36Sopenharmony_ci	omap_test_timeout((omap_hwmod_read(oh,
6262306a36Sopenharmony_ci				oh->class->sysc->syss_offs)
6362306a36Sopenharmony_ci				& SYSS_RESETDONE_MASK),
6462306a36Sopenharmony_ci				MAX_MODULE_SOFTRESET_WAIT, c);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	if (c == MAX_MODULE_SOFTRESET_WAIT)
6762306a36Sopenharmony_ci		pr_warn("%s: %s: softreset failed (waited %d usec)\n",
6862306a36Sopenharmony_ci			__func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
6962306a36Sopenharmony_ci	else
7062306a36Sopenharmony_ci		pr_debug("%s: %s: softreset in %d usec\n", __func__,
7162306a36Sopenharmony_ci			oh->name, c);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	return 0;
7462306a36Sopenharmony_ci}
75