linux/arch/arm/mach-omap2/i2c.c
<<
>>
Prefs
   1/*
   2 * Helper module for board specific I2C bus registration
   3 *
   4 * Copyright (C) 2009 Nokia Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * version 2 as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  18 * 02110-1301 USA
  19 *
  20 */
  21
  22#include <plat/cpu.h>
  23#include <plat/i2c.h>
  24#include "common.h"
  25#include <plat/omap_hwmod.h>
  26
  27#include "mux.h"
  28
  29/* In register I2C_CON, Bit 15 is the I2C enable bit */
  30#define I2C_EN                                  BIT(15)
  31#define OMAP2_I2C_CON_OFFSET                    0x24
  32#define OMAP4_I2C_CON_OFFSET                    0xA4
  33
  34/* Maximum microseconds to wait for OMAP module to softreset */
  35#define MAX_MODULE_SOFTRESET_WAIT       10000
  36
  37void __init omap2_i2c_mux_pins(int bus_id)
  38{
  39        char mux_name[sizeof("i2c2_scl.i2c2_scl")];
  40
  41        /* First I2C bus is not muxable */
  42        if (bus_id == 1)
  43                return;
  44
  45        sprintf(mux_name, "i2c%i_scl.i2c%i_scl", bus_id, bus_id);
  46        omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
  47        sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id);
  48        omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
  49}
  50
  51/**
  52 * omap_i2c_reset - reset the omap i2c module.
  53 * @oh: struct omap_hwmod *
  54 *
  55 * The i2c moudle in omap2, omap3 had a special sequence to reset. The
  56 * sequence is:
  57 * - Disable the I2C.
  58 * - Write to SOFTRESET bit.
  59 * - Enable the I2C.
  60 * - Poll on the RESETDONE bit.
  61 * The sequence is implemented in below function. This is called for 2420,
  62 * 2430 and omap3.
  63 */
  64int omap_i2c_reset(struct omap_hwmod *oh)
  65{
  66        u32 v;
  67        u16 i2c_con;
  68        int c = 0;
  69
  70        if (oh->class->rev == OMAP_I2C_IP_VERSION_2) {
  71                i2c_con = OMAP4_I2C_CON_OFFSET;
  72        } else if (oh->class->rev == OMAP_I2C_IP_VERSION_1) {
  73                i2c_con = OMAP2_I2C_CON_OFFSET;
  74        } else {
  75                WARN(1, "Cannot reset I2C block %s: unsupported revision\n",
  76                     oh->name);
  77                return -EINVAL;
  78        }
  79
  80        /* Disable I2C */
  81        v = omap_hwmod_read(oh, i2c_con);
  82        v &= ~I2C_EN;
  83        omap_hwmod_write(v, oh, i2c_con);
  84
  85        /* Write to the SOFTRESET bit */
  86        omap_hwmod_softreset(oh);
  87
  88        /* Enable I2C */
  89        v = omap_hwmod_read(oh, i2c_con);
  90        v |= I2C_EN;
  91        omap_hwmod_write(v, oh, i2c_con);
  92
  93        /* Poll on RESETDONE bit */
  94        omap_test_timeout((omap_hwmod_read(oh,
  95                                oh->class->sysc->syss_offs)
  96                                & SYSS_RESETDONE_MASK),
  97                                MAX_MODULE_SOFTRESET_WAIT, c);
  98
  99        if (c == MAX_MODULE_SOFTRESET_WAIT)
 100                pr_warning("%s: %s: softreset failed (waited %d usec)\n",
 101                        __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT);
 102        else
 103                pr_debug("%s: %s: softreset in %d usec\n", __func__,
 104                        oh->name, c);
 105
 106        return 0;
 107}
 108