linux/arch/arm/mach-omap2/i2c.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Helper module for board specific I2C bus registration
   4 *
   5 * Copyright (C) 2009 Nokia Corporation.
   6 */
   7
   8#include "soc.h"
   9#include "omap_hwmod.h"
  10#include "omap_device.h"
  11
  12#include "prm.h"
  13#include "common.h"
  14#include "i2c.h"
  15
  16/* In register I2C_CON, Bit 15 is the I2C enable bit */
  17#define I2C_EN                                  BIT(15)
  18#define OMAP2_I2C_CON_OFFSET                    0x24
  19#define OMAP4_I2C_CON_OFFSET                    0xA4
  20
  21#define MAX_OMAP_I2C_HWMOD_NAME_LEN     16
  22
  23/**
  24 * omap_i2c_reset - reset the omap i2c module.
  25 * @oh: struct omap_hwmod *
  26 *
  27 * The i2c moudle in omap2, omap3 had a special sequence to reset. The
  28 * sequence is:
  29 * - Disable the I2C.
  30 * - Write to SOFTRESET bit.
  31 * - Enable the I2C.
  32 * - Poll on the RESETDONE bit.
  33 * The sequence is implemented in below function. This is called for 2420,
  34 * 2430 and omap3.
  35 */
  36int omap_i2c_reset(struct omap_hwmod *oh)
  37{
  38        u32 v;
  39        u16 i2c_con;
  40        int c = 0;
  41
  42        if (soc_is_omap24xx() || soc_is_omap34xx() || soc_is_am35xx())
  43                i2c_con = OMAP2_I2C_CON_OFFSET;
  44        else
  45                i2c_con = OMAP4_I2C_CON_OFFSET;
  46
  47        /* Disable I2C */
  48        v = omap_hwmod_read(oh, i2c_con);
  49        v &= ~I2C_EN;
  50        omap_hwmod_write(v, oh, i2c_con);
  51
  52        /* Write to the SOFTRESET bit */
  53        omap_hwmod_softreset(oh);
  54
  55        /* Enable I2C */
  56        v = omap_hwmod_read(oh, i2c_con);
  57        v |= I2C_EN;
  58        omap_hwmod_write(v, oh, i2c_con);
  59
  60        /* Poll on RESETDONE bit */
  61        omap_test_timeout((omap_hwmod_read(oh,
  62                                oh->class->sysc->syss_offs)
  63                                & SYSS_RESETDONE_MASK),
  64                                MAX_MODULE_SOFTRESET_WAIT, c);
  65
  66        if (c == MAX_MODULE_SOFTRESET_WAIT)
  67                pr_warn("%s: %s: softreset failed (waited %d usec)\n",
  68                        __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
  69        else
  70                pr_debug("%s: %s: softreset in %d usec\n", __func__,
  71                        oh->name, c);
  72
  73        return 0;
  74}
  75