Skip to content

Commit

Permalink
i2c: davinci: Add helper functions for power management
Browse files Browse the repository at this point in the history
Add i2c reset control and clock divider calculation functions
which will be useful for power management features.

Signed-off-by: Chaithrika U S <chaithrika@ti.com>
Acked-by: Kevin Hilman <khilman@deeprootsystems.com>
  • Loading branch information
Chaithrika U S authored and Kevin Hilman committed Aug 5, 2010
1 parent c062a25 commit 5ae5b11
Showing 1 changed file with 37 additions and 19 deletions.
56 changes: 37 additions & 19 deletions drivers/i2c/busses/i2c-davinci.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,21 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
return __raw_readw(i2c_dev->base + reg);
}

/*
* This functions configures I2C and brings I2C out of reset.
* This function is called during I2C init function. This function
* also gets called if I2C encounters any errors.
*/
static int i2c_davinci_init(struct davinci_i2c_dev *dev)
static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
int val)
{
u16 w;

w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG);
if (!val) /* put I2C into reset */
w &= ~DAVINCI_I2C_MDR_IRS;
else /* take I2C out of reset */
w |= DAVINCI_I2C_MDR_IRS;

davinci_i2c_write_reg(i2c_dev, DAVINCI_I2C_MDR_REG, w);
}

static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
{
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
u16 psc;
Expand All @@ -140,15 +149,6 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
u32 clkh;
u32 clkl;
u32 input_clock = clk_get_rate(dev->clk);
u16 w;

if (!pdata)
pdata = &davinci_i2c_platform_data_default;

/* put I2C into reset */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w &= ~DAVINCI_I2C_MDR_IRS;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);

/* NOTE: I2C Clock divider programming info
* As per I2C specs the following formulas provide prescaler
Expand Down Expand Up @@ -180,12 +180,32 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);

dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
}

/*
* This function configures I2C and brings I2C out of reset.
* This function is called during I2C init function. This function
* also gets called if I2C encounters any errors.
*/
static int i2c_davinci_init(struct davinci_i2c_dev *dev)
{
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;

if (!pdata)
pdata = &davinci_i2c_platform_data_default;

/* put I2C into reset */
davinci_i2c_reset_ctrl(dev, 0);

/* compute clock dividers */
i2c_davinci_calc_clk_dividers(dev);

/* Respond at reserved "SMBus Host" slave address" (and zero);
* we seem to have no option to not respond...
*/
davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08);

dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
dev_dbg(dev->dev, "PSC = %d\n",
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
dev_dbg(dev->dev, "CLKL = %d\n",
Expand All @@ -196,9 +216,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
pdata->bus_freq, pdata->bus_delay);

/* Take the I2C module out of reset: */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
w |= DAVINCI_I2C_MDR_IRS;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
davinci_i2c_reset_ctrl(dev, 1);

/* Enable interrupts */
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL);
Expand Down

0 comments on commit 5ae5b11

Please sign in to comment.