mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
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
1 changed files with 37 additions and 19 deletions
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue