diff options
author | Chaithrika U S <chaithrika@ti.com> | 2010-01-06 04:24:58 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-08-05 12:38:32 -0400 |
commit | 5ae5b1136e0c434b076ab1f9cb39deebf6187f55 (patch) | |
tree | c9d9f9b0f7f6ef6528e537c20d963738dd712775 /drivers/i2c/busses | |
parent | c062a2518d35a76e7db8519b2292191a47e3ab79 (diff) |
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>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/i2c-davinci.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 4e33909dd3f0..9afd9af4f550 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c | |||
@@ -126,12 +126,21 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg) | |||
126 | return __raw_readw(i2c_dev->base + reg); | 126 | return __raw_readw(i2c_dev->base + reg); |
127 | } | 127 | } |
128 | 128 | ||
129 | /* | 129 | static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, |
130 | * This functions configures I2C and brings I2C out of reset. | 130 | int val) |
131 | * This function is called during I2C init function. This function | 131 | { |
132 | * also gets called if I2C encounters any errors. | 132 | u16 w; |
133 | */ | 133 | |
134 | static int i2c_davinci_init(struct davinci_i2c_dev *dev) | 134 | w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG); |
135 | if (!val) /* put I2C into reset */ | ||
136 | w &= ~DAVINCI_I2C_MDR_IRS; | ||
137 | else /* take I2C out of reset */ | ||
138 | w |= DAVINCI_I2C_MDR_IRS; | ||
139 | |||
140 | davinci_i2c_write_reg(i2c_dev, DAVINCI_I2C_MDR_REG, w); | ||
141 | } | ||
142 | |||
143 | static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) | ||
135 | { | 144 | { |
136 | struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; | 145 | struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; |
137 | u16 psc; | 146 | u16 psc; |
@@ -140,15 +149,6 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) | |||
140 | u32 clkh; | 149 | u32 clkh; |
141 | u32 clkl; | 150 | u32 clkl; |
142 | u32 input_clock = clk_get_rate(dev->clk); | 151 | u32 input_clock = clk_get_rate(dev->clk); |
143 | u16 w; | ||
144 | |||
145 | if (!pdata) | ||
146 | pdata = &davinci_i2c_platform_data_default; | ||
147 | |||
148 | /* put I2C into reset */ | ||
149 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); | ||
150 | w &= ~DAVINCI_I2C_MDR_IRS; | ||
151 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); | ||
152 | 152 | ||
153 | /* NOTE: I2C Clock divider programming info | 153 | /* NOTE: I2C Clock divider programming info |
154 | * As per I2C specs the following formulas provide prescaler | 154 | * As per I2C specs the following formulas provide prescaler |
@@ -180,12 +180,32 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) | |||
180 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); | 180 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); |
181 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); | 181 | davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); |
182 | 182 | ||
183 | dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * This function configures I2C and brings I2C out of reset. | ||
188 | * This function is called during I2C init function. This function | ||
189 | * also gets called if I2C encounters any errors. | ||
190 | */ | ||
191 | static int i2c_davinci_init(struct davinci_i2c_dev *dev) | ||
192 | { | ||
193 | struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; | ||
194 | |||
195 | if (!pdata) | ||
196 | pdata = &davinci_i2c_platform_data_default; | ||
197 | |||
198 | /* put I2C into reset */ | ||
199 | davinci_i2c_reset_ctrl(dev, 0); | ||
200 | |||
201 | /* compute clock dividers */ | ||
202 | i2c_davinci_calc_clk_dividers(dev); | ||
203 | |||
183 | /* Respond at reserved "SMBus Host" slave address" (and zero); | 204 | /* Respond at reserved "SMBus Host" slave address" (and zero); |
184 | * we seem to have no option to not respond... | 205 | * we seem to have no option to not respond... |
185 | */ | 206 | */ |
186 | davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); | 207 | davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); |
187 | 208 | ||
188 | dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); | ||
189 | dev_dbg(dev->dev, "PSC = %d\n", | 209 | dev_dbg(dev->dev, "PSC = %d\n", |
190 | davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); | 210 | davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); |
191 | dev_dbg(dev->dev, "CLKL = %d\n", | 211 | dev_dbg(dev->dev, "CLKL = %d\n", |
@@ -196,9 +216,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) | |||
196 | pdata->bus_freq, pdata->bus_delay); | 216 | pdata->bus_freq, pdata->bus_delay); |
197 | 217 | ||
198 | /* Take the I2C module out of reset: */ | 218 | /* Take the I2C module out of reset: */ |
199 | w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); | 219 | davinci_i2c_reset_ctrl(dev, 1); |
200 | w |= DAVINCI_I2C_MDR_IRS; | ||
201 | davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); | ||
202 | 220 | ||
203 | /* Enable interrupts */ | 221 | /* Enable interrupts */ |
204 | davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); | 222 | davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); |