i2c: davinci: Add helper functions for power management
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>
This commit is contained in:
parent
c062a2518d
commit
5ae5b1136e
|
@ -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);
|
return __raw_readw(i2c_dev->base + reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
|
||||||
* This functions configures I2C and brings I2C out of reset.
|
int val)
|
||||||
* This function is called during I2C init function. This function
|
{
|
||||||
* also gets called if I2C encounters any errors.
|
u16 w;
|
||||||
*/
|
|
||||||
static int i2c_davinci_init(struct davinci_i2c_dev *dev)
|
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;
|
struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
|
||||||
u16 psc;
|
u16 psc;
|
||||||
|
@ -140,15 +149,6 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
|
||||||
u32 clkh;
|
u32 clkh;
|
||||||
u32 clkl;
|
u32 clkl;
|
||||||
u32 input_clock = clk_get_rate(dev->clk);
|
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
|
/* NOTE: I2C Clock divider programming info
|
||||||
* As per I2C specs the following formulas provide prescaler
|
* As per I2C specs the following formulas provide prescaler
|
||||||
|
@ -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_CLKH_REG, clkh);
|
||||||
davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
|
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);
|
/* Respond at reserved "SMBus Host" slave address" (and zero);
|
||||||
* we seem to have no option to not respond...
|
* we seem to have no option to not respond...
|
||||||
*/
|
*/
|
||||||
davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08);
|
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",
|
dev_dbg(dev->dev, "PSC = %d\n",
|
||||||
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
|
davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
|
||||||
dev_dbg(dev->dev, "CLKL = %d\n",
|
dev_dbg(dev->dev, "CLKL = %d\n",
|
||||||
|
@ -196,9 +216,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
|
||||||
pdata->bus_freq, pdata->bus_delay);
|
pdata->bus_freq, pdata->bus_delay);
|
||||||
|
|
||||||
/* Take the I2C module out of reset: */
|
/* Take the I2C module out of reset: */
|
||||||
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
|
davinci_i2c_reset_ctrl(dev, 1);
|
||||||
w |= DAVINCI_I2C_MDR_IRS;
|
|
||||||
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
|
|
||||||
|
|
||||||
/* Enable interrupts */
|
/* Enable interrupts */
|
||||||
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL);
|
davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL);
|
||||||
|
|
Loading…
Reference in New Issue