diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-28 11:28:50 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-28 11:28:50 -0400 |
| commit | 9ffc1699e36abd5baee188c8e36b1bb27d0d4278 (patch) | |
| tree | ce07bb773305b38ec672e1e37f48bd6ecfdc8dc4 | |
| parent | a01386924874c4d6d67f8a34e66f04452c2abb69 (diff) | |
| parent | 958585f58f675a3c2855c7d91b6fdd2875552d0b (diff) | |
Merge branch 'i2c-for-linus' of git://aeryn.fluff.org.uk/bjdooks/linux
* 'i2c-for-linus' of git://aeryn.fluff.org.uk/bjdooks/linux:
i2c: Blackfin I2C Driver: Functional power management support
i2c: Documentation: upgrading clients HOWTO
i2c: S3C24XX I2C frequency scaling support.
i2c: i2c_gpio: keep probe resident for hotplugged devices.
i2c: S3C2410: Pass the I2C bus number via drivers platform data
| -rw-r--r-- | Documentation/i2c/upgrading-clients | 281 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-bfin-twi.c | 35 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-gpio.c | 9 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 129 | ||||
| -rw-r--r-- | include/asm-arm/plat-s3c/iic.h | 1 |
5 files changed, 426 insertions, 29 deletions
diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients new file mode 100644 index 000000000000..9a45f9bb6a25 --- /dev/null +++ b/Documentation/i2c/upgrading-clients | |||
| @@ -0,0 +1,281 @@ | |||
| 1 | Upgrading I2C Drivers to the new 2.6 Driver Model | ||
| 2 | ================================================= | ||
| 3 | |||
| 4 | Ben Dooks <ben-linux@fluff.org> | ||
| 5 | |||
| 6 | Introduction | ||
| 7 | ------------ | ||
| 8 | |||
| 9 | This guide outlines how to alter existing Linux 2.6 client drivers from | ||
| 10 | the old to the new new binding methods. | ||
| 11 | |||
| 12 | |||
| 13 | Example old-style driver | ||
| 14 | ------------------------ | ||
| 15 | |||
| 16 | |||
| 17 | struct example_state { | ||
| 18 | struct i2c_client client; | ||
| 19 | .... | ||
| 20 | }; | ||
| 21 | |||
| 22 | static struct i2c_driver example_driver; | ||
| 23 | |||
| 24 | static unsigned short ignore[] = { I2C_CLIENT_END }; | ||
| 25 | static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; | ||
| 26 | |||
| 27 | I2C_CLIENT_INSMOD; | ||
| 28 | |||
| 29 | static int example_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 30 | { | ||
| 31 | struct example_state *state; | ||
| 32 | struct device *dev = &adap->dev; /* to use for dev_ reports */ | ||
| 33 | int ret; | ||
| 34 | |||
| 35 | state = kzalloc(sizeof(struct example_state), GFP_KERNEL); | ||
| 36 | if (state == NULL) { | ||
| 37 | dev_err(dev, "failed to create our state\n"); | ||
| 38 | return -ENOMEM; | ||
| 39 | } | ||
| 40 | |||
| 41 | example->client.addr = addr; | ||
| 42 | example->client.flags = 0; | ||
| 43 | example->client.adapter = adap; | ||
| 44 | |||
| 45 | i2c_set_clientdata(&state->i2c_client, state); | ||
| 46 | strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE); | ||
| 47 | |||
| 48 | ret = i2c_attach_client(&state->i2c_client); | ||
| 49 | if (ret < 0) { | ||
| 50 | dev_err(dev, "failed to attach client\n"); | ||
| 51 | kfree(state); | ||
| 52 | return ret; | ||
| 53 | } | ||
| 54 | |||
| 55 | dev = &state->i2c_client.dev; | ||
| 56 | |||
| 57 | /* rest of the initialisation goes here. */ | ||
| 58 | |||
| 59 | dev_info(dev, "example client created\n"); | ||
| 60 | |||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int __devexit example_detach(struct i2c_client *client) | ||
| 65 | { | ||
| 66 | struct example_state *state = i2c_get_clientdata(client); | ||
| 67 | |||
| 68 | i2c_detach_client(client); | ||
| 69 | kfree(state); | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int example_attach_adapter(struct i2c_adapter *adap) | ||
| 74 | { | ||
| 75 | return i2c_probe(adap, &addr_data, example_attach); | ||
| 76 | } | ||
| 77 | |||
| 78 | static struct i2c_driver example_driver = { | ||
| 79 | .driver = { | ||
| 80 | .owner = THIS_MODULE, | ||
| 81 | .name = "example", | ||
| 82 | }, | ||
| 83 | .attach_adapter = example_attach_adapter, | ||
| 84 | .detach_client = __devexit_p(example_detach), | ||
| 85 | .suspend = example_suspend, | ||
| 86 | .resume = example_resume, | ||
| 87 | }; | ||
| 88 | |||
| 89 | |||
| 90 | Updating the client | ||
| 91 | ------------------- | ||
| 92 | |||
| 93 | The new style binding model will check against a list of supported | ||
| 94 | devices and their associated address supplied by the code registering | ||
| 95 | the busses. This means that the driver .attach_adapter and | ||
| 96 | .detach_adapter methods can be removed, along with the addr_data, | ||
| 97 | as follows: | ||
| 98 | |||
| 99 | - static struct i2c_driver example_driver; | ||
| 100 | |||
| 101 | - static unsigned short ignore[] = { I2C_CLIENT_END }; | ||
| 102 | - static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END }; | ||
| 103 | |||
| 104 | - I2C_CLIENT_INSMOD; | ||
| 105 | |||
| 106 | - static int example_attach_adapter(struct i2c_adapter *adap) | ||
| 107 | - { | ||
| 108 | - return i2c_probe(adap, &addr_data, example_attach); | ||
| 109 | - } | ||
| 110 | |||
| 111 | static struct i2c_driver example_driver = { | ||
| 112 | - .attach_adapter = example_attach_adapter, | ||
| 113 | - .detach_client = __devexit_p(example_detach), | ||
| 114 | } | ||
| 115 | |||
| 116 | Add the probe and remove methods to the i2c_driver, as so: | ||
| 117 | |||
| 118 | static struct i2c_driver example_driver = { | ||
| 119 | + .probe = example_probe, | ||
| 120 | + .remove = __devexit_p(example_remove), | ||
| 121 | } | ||
| 122 | |||
| 123 | Change the example_attach method to accept the new parameters | ||
| 124 | which include the i2c_client that it will be working with: | ||
| 125 | |||
| 126 | - static int example_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 127 | + static int example_probe(struct i2c_client *client, | ||
| 128 | + const struct i2c_device_id *id) | ||
| 129 | |||
| 130 | Change the name of example_attach to example_probe to align it with the | ||
| 131 | i2c_driver entry names. The rest of the probe routine will now need to be | ||
| 132 | changed as the i2c_client has already been setup for use. | ||
| 133 | |||
| 134 | The necessary client fields have already been setup before | ||
| 135 | the probe function is called, so the following client setup | ||
| 136 | can be removed: | ||
| 137 | |||
| 138 | - example->client.addr = addr; | ||
| 139 | - example->client.flags = 0; | ||
| 140 | - example->client.adapter = adap; | ||
| 141 | - | ||
| 142 | - strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE); | ||
| 143 | |||
| 144 | The i2c_set_clientdata is now: | ||
| 145 | |||
| 146 | - i2c_set_clientdata(&state->client, state); | ||
| 147 | + i2c_set_clientdata(client, state); | ||
| 148 | |||
| 149 | The call to i2c_attach_client is no longer needed, if the probe | ||
| 150 | routine exits successfully, then the driver will be automatically | ||
| 151 | attached by the core. Change the probe routine as so: | ||
| 152 | |||
| 153 | - ret = i2c_attach_client(&state->i2c_client); | ||
| 154 | - if (ret < 0) { | ||
| 155 | - dev_err(dev, "failed to attach client\n"); | ||
| 156 | - kfree(state); | ||
| 157 | - return ret; | ||
| 158 | - } | ||
| 159 | |||
| 160 | |||
| 161 | Remove the storage of 'struct i2c_client' from the 'struct example_state' | ||
| 162 | as we are provided with the i2c_client in our example_probe. Instead we | ||
| 163 | store a pointer to it for when it is needed. | ||
| 164 | |||
| 165 | struct example_state { | ||
| 166 | - struct i2c_client client; | ||
| 167 | + struct i2c_client *client; | ||
| 168 | |||
| 169 | the new i2c client as so: | ||
| 170 | |||
| 171 | - struct device *dev = &adap->dev; /* to use for dev_ reports */ | ||
| 172 | + struct device *dev = &i2c_client->dev; /* to use for dev_ reports */ | ||
| 173 | |||
| 174 | And remove the change after our client is attached, as the driver no | ||
| 175 | longer needs to register a new client structure with the core: | ||
| 176 | |||
| 177 | - dev = &state->i2c_client.dev; | ||
| 178 | |||
| 179 | In the probe routine, ensure that the new state has the client stored | ||
| 180 | in it: | ||
| 181 | |||
| 182 | static int example_probe(struct i2c_client *i2c_client, | ||
| 183 | const struct i2c_device_id *id) | ||
| 184 | { | ||
| 185 | struct example_state *state; | ||
| 186 | struct device *dev = &i2c_client->dev; | ||
| 187 | int ret; | ||
| 188 | |||
| 189 | state = kzalloc(sizeof(struct example_state), GFP_KERNEL); | ||
| 190 | if (state == NULL) { | ||
| 191 | dev_err(dev, "failed to create our state\n"); | ||
| 192 | return -ENOMEM; | ||
| 193 | } | ||
| 194 | |||
| 195 | + state->client = i2c_client; | ||
| 196 | |||
| 197 | Update the detach method, by changing the name to _remove and | ||
| 198 | to delete the i2c_detach_client call. It is possible that you | ||
| 199 | can also remove the ret variable as it is not not needed for | ||
| 200 | any of the core functions. | ||
| 201 | |||
| 202 | - static int __devexit example_detach(struct i2c_client *client) | ||
| 203 | + static int __devexit example_remove(struct i2c_client *client) | ||
| 204 | { | ||
| 205 | struct example_state *state = i2c_get_clientdata(client); | ||
| 206 | |||
| 207 | - i2c_detach_client(client); | ||
| 208 | |||
| 209 | And finally ensure that we have the correct ID table for the i2c-core | ||
| 210 | and other utilities: | ||
| 211 | |||
| 212 | + struct i2c_device_id example_idtable[] = { | ||
| 213 | + { "example", 0 }, | ||
| 214 | + { } | ||
| 215 | +}; | ||
| 216 | + | ||
| 217 | +MODULE_DEVICE_TABLE(i2c, example_idtable); | ||
| 218 | |||
| 219 | static struct i2c_driver example_driver = { | ||
| 220 | .driver = { | ||
| 221 | .owner = THIS_MODULE, | ||
| 222 | .name = "example", | ||
| 223 | }, | ||
| 224 | + .id_table = example_ids, | ||
| 225 | |||
| 226 | |||
| 227 | Our driver should now look like this: | ||
| 228 | |||
| 229 | struct example_state { | ||
| 230 | struct i2c_client *client; | ||
| 231 | .... | ||
| 232 | }; | ||
| 233 | |||
| 234 | static int example_probe(struct i2c_client *client, | ||
| 235 | const struct i2c_device_id *id) | ||
| 236 | { | ||
| 237 | struct example_state *state; | ||
| 238 | struct device *dev = &client->dev; | ||
| 239 | |||
| 240 | state = kzalloc(sizeof(struct example_state), GFP_KERNEL); | ||
| 241 | if (state == NULL) { | ||
| 242 | dev_err(dev, "failed to create our state\n"); | ||
| 243 | return -ENOMEM; | ||
| 244 | } | ||
| 245 | |||
| 246 | state->client = client; | ||
| 247 | i2c_set_clientdata(client, state); | ||
| 248 | |||
| 249 | /* rest of the initialisation goes here. */ | ||
| 250 | |||
| 251 | dev_info(dev, "example client created\n"); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static int __devexit example_remove(struct i2c_client *client) | ||
| 257 | { | ||
| 258 | struct example_state *state = i2c_get_clientdata(client); | ||
| 259 | |||
| 260 | kfree(state); | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static struct i2c_device_id example_idtable[] = { | ||
| 265 | { "example", 0 }, | ||
| 266 | { } | ||
| 267 | }; | ||
| 268 | |||
| 269 | MODULE_DEVICE_TABLE(i2c, example_idtable); | ||
| 270 | |||
| 271 | static struct i2c_driver example_driver = { | ||
| 272 | .driver = { | ||
| 273 | .owner = THIS_MODULE, | ||
| 274 | .name = "example", | ||
| 275 | }, | ||
| 276 | .id_table = example_idtable, | ||
| 277 | .probe = example_probe, | ||
| 278 | .remove = __devexit_p(example_remove), | ||
| 279 | .suspend = example_suspend, | ||
| 280 | .resume = example_resume, | ||
| 281 | }; | ||
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 48d084bdf7c8..3c855ff2992f 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c | |||
| @@ -49,6 +49,8 @@ struct bfin_twi_iface { | |||
| 49 | struct i2c_msg *pmsg; | 49 | struct i2c_msg *pmsg; |
| 50 | int msg_num; | 50 | int msg_num; |
| 51 | int cur_msg; | 51 | int cur_msg; |
| 52 | u16 saved_clkdiv; | ||
| 53 | u16 saved_control; | ||
| 52 | void __iomem *regs_base; | 54 | void __iomem *regs_base; |
| 53 | }; | 55 | }; |
| 54 | 56 | ||
| @@ -565,32 +567,43 @@ static u32 bfin_twi_functionality(struct i2c_adapter *adap) | |||
| 565 | I2C_FUNC_I2C; | 567 | I2C_FUNC_I2C; |
| 566 | } | 568 | } |
| 567 | 569 | ||
| 568 | |||
| 569 | static struct i2c_algorithm bfin_twi_algorithm = { | 570 | static struct i2c_algorithm bfin_twi_algorithm = { |
| 570 | .master_xfer = bfin_twi_master_xfer, | 571 | .master_xfer = bfin_twi_master_xfer, |
| 571 | .smbus_xfer = bfin_twi_smbus_xfer, | 572 | .smbus_xfer = bfin_twi_smbus_xfer, |
| 572 | .functionality = bfin_twi_functionality, | 573 | .functionality = bfin_twi_functionality, |
| 573 | }; | 574 | }; |
| 574 | 575 | ||
| 575 | 576 | static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state) | |
| 576 | static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state) | ||
| 577 | { | 577 | { |
| 578 | struct bfin_twi_iface *iface = platform_get_drvdata(dev); | 578 | struct bfin_twi_iface *iface = platform_get_drvdata(pdev); |
| 579 | |||
| 580 | iface->saved_clkdiv = read_CLKDIV(iface); | ||
| 581 | iface->saved_control = read_CONTROL(iface); | ||
| 582 | |||
| 583 | free_irq(iface->irq, iface); | ||
| 579 | 584 | ||
| 580 | /* Disable TWI */ | 585 | /* Disable TWI */ |
| 581 | write_CONTROL(iface, read_CONTROL(iface) & ~TWI_ENA); | 586 | write_CONTROL(iface, iface->saved_control & ~TWI_ENA); |
| 582 | SSYNC(); | ||
| 583 | 587 | ||
| 584 | return 0; | 588 | return 0; |
| 585 | } | 589 | } |
| 586 | 590 | ||
| 587 | static int i2c_bfin_twi_resume(struct platform_device *dev) | 591 | static int i2c_bfin_twi_resume(struct platform_device *pdev) |
| 588 | { | 592 | { |
| 589 | struct bfin_twi_iface *iface = platform_get_drvdata(dev); | 593 | struct bfin_twi_iface *iface = platform_get_drvdata(pdev); |
| 590 | 594 | ||
| 591 | /* Enable TWI */ | 595 | int rc = request_irq(iface->irq, bfin_twi_interrupt_entry, |
| 592 | write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); | 596 | IRQF_DISABLED, pdev->name, iface); |
| 593 | SSYNC(); | 597 | if (rc) { |
| 598 | dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); | ||
| 599 | return -ENODEV; | ||
| 600 | } | ||
| 601 | |||
| 602 | /* Resume TWI interface clock as specified */ | ||
| 603 | write_CLKDIV(iface, iface->saved_clkdiv); | ||
| 604 | |||
| 605 | /* Resume TWI */ | ||
| 606 | write_CONTROL(iface, iface->saved_control); | ||
| 594 | 607 | ||
| 595 | return 0; | 608 | return 0; |
| 596 | } | 609 | } |
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 79b455a1f090..32104eac8d3d 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c | |||
| @@ -77,7 +77,7 @@ static int i2c_gpio_getscl(void *data) | |||
| 77 | return gpio_get_value(pdata->scl_pin); | 77 | return gpio_get_value(pdata->scl_pin); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static int __init i2c_gpio_probe(struct platform_device *pdev) | 80 | static int __devinit i2c_gpio_probe(struct platform_device *pdev) |
| 81 | { | 81 | { |
| 82 | struct i2c_gpio_platform_data *pdata; | 82 | struct i2c_gpio_platform_data *pdata; |
| 83 | struct i2c_algo_bit_data *bit_data; | 83 | struct i2c_algo_bit_data *bit_data; |
| @@ -174,7 +174,7 @@ err_alloc_adap: | |||
| 174 | return ret; | 174 | return ret; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static int __exit i2c_gpio_remove(struct platform_device *pdev) | 177 | static int __devexit i2c_gpio_remove(struct platform_device *pdev) |
| 178 | { | 178 | { |
| 179 | struct i2c_gpio_platform_data *pdata; | 179 | struct i2c_gpio_platform_data *pdata; |
| 180 | struct i2c_adapter *adap; | 180 | struct i2c_adapter *adap; |
| @@ -196,14 +196,15 @@ static struct platform_driver i2c_gpio_driver = { | |||
| 196 | .name = "i2c-gpio", | 196 | .name = "i2c-gpio", |
| 197 | .owner = THIS_MODULE, | 197 | .owner = THIS_MODULE, |
| 198 | }, | 198 | }, |
| 199 | .remove = __exit_p(i2c_gpio_remove), | 199 | .probe = i2c_gpio_probe, |
| 200 | .remove = __devexit_p(i2c_gpio_remove), | ||
| 200 | }; | 201 | }; |
| 201 | 202 | ||
| 202 | static int __init i2c_gpio_init(void) | 203 | static int __init i2c_gpio_init(void) |
| 203 | { | 204 | { |
| 204 | int ret; | 205 | int ret; |
| 205 | 206 | ||
| 206 | ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe); | 207 | ret = platform_driver_register(&i2c_gpio_driver); |
| 207 | if (ret) | 208 | if (ret) |
| 208 | printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); | 209 | printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); |
| 209 | 210 | ||
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 007390ad9810..4864723c7425 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/err.h> | 33 | #include <linux/err.h> |
| 34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 35 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
| 36 | #include <linux/cpufreq.h> | ||
| 36 | 37 | ||
| 37 | #include <asm/hardware.h> | 38 | #include <asm/hardware.h> |
| 38 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
| @@ -64,6 +65,7 @@ struct s3c24xx_i2c { | |||
| 64 | unsigned int tx_setup; | 65 | unsigned int tx_setup; |
| 65 | 66 | ||
| 66 | enum s3c24xx_i2c_state state; | 67 | enum s3c24xx_i2c_state state; |
| 68 | unsigned long clkrate; | ||
| 67 | 69 | ||
| 68 | void __iomem *regs; | 70 | void __iomem *regs; |
| 69 | struct clk *clk; | 71 | struct clk *clk; |
| @@ -71,6 +73,10 @@ struct s3c24xx_i2c { | |||
| 71 | struct resource *irq; | 73 | struct resource *irq; |
| 72 | struct resource *ioarea; | 74 | struct resource *ioarea; |
| 73 | struct i2c_adapter adap; | 75 | struct i2c_adapter adap; |
| 76 | |||
| 77 | #ifdef CONFIG_CPU_FREQ | ||
| 78 | struct notifier_block freq_transition; | ||
| 79 | #endif | ||
| 74 | }; | 80 | }; |
| 75 | 81 | ||
| 76 | /* default platform data to use if not supplied in the platform_device | 82 | /* default platform data to use if not supplied in the platform_device |
| @@ -501,6 +507,9 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int | |||
| 501 | unsigned long timeout; | 507 | unsigned long timeout; |
| 502 | int ret; | 508 | int ret; |
| 503 | 509 | ||
| 510 | if (!readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN) | ||
| 511 | return -EIO; | ||
| 512 | |||
| 504 | ret = s3c24xx_i2c_set_master(i2c); | 513 | ret = s3c24xx_i2c_set_master(i2c); |
| 505 | if (ret != 0) { | 514 | if (ret != 0) { |
| 506 | dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); | 515 | dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); |
| @@ -636,27 +645,28 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted) | |||
| 636 | return (diff >= -2 && diff <= 2); | 645 | return (diff >= -2 && diff <= 2); |
| 637 | } | 646 | } |
| 638 | 647 | ||
| 639 | /* s3c24xx_i2c_getdivisor | 648 | /* s3c24xx_i2c_clockrate |
| 640 | * | 649 | * |
| 641 | * work out a divisor for the user requested frequency setting, | 650 | * work out a divisor for the user requested frequency setting, |
| 642 | * either by the requested frequency, or scanning the acceptable | 651 | * either by the requested frequency, or scanning the acceptable |
| 643 | * range of frequencies until something is found | 652 | * range of frequencies until something is found |
| 644 | */ | 653 | */ |
| 645 | 654 | ||
| 646 | static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c, | 655 | static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) |
| 647 | struct s3c2410_platform_i2c *pdata, | ||
| 648 | unsigned long *iicon, | ||
| 649 | unsigned int *got) | ||
| 650 | { | 656 | { |
| 657 | struct s3c2410_platform_i2c *pdata; | ||
| 651 | unsigned long clkin = clk_get_rate(i2c->clk); | 658 | unsigned long clkin = clk_get_rate(i2c->clk); |
| 652 | |||
| 653 | unsigned int divs, div1; | 659 | unsigned int divs, div1; |
| 660 | u32 iiccon; | ||
| 654 | int freq; | 661 | int freq; |
| 655 | int start, end; | 662 | int start, end; |
| 656 | 663 | ||
| 664 | i2c->clkrate = clkin; | ||
| 665 | |||
| 666 | pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent); | ||
| 657 | clkin /= 1000; /* clkin now in KHz */ | 667 | clkin /= 1000; /* clkin now in KHz */ |
| 658 | 668 | ||
| 659 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", | 669 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", |
| 660 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); | 670 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); |
| 661 | 671 | ||
| 662 | if (pdata->bus_freq != 0) { | 672 | if (pdata->bus_freq != 0) { |
| @@ -688,11 +698,79 @@ static int s3c24xx_i2c_getdivisor(struct s3c24xx_i2c *i2c, | |||
| 688 | 698 | ||
| 689 | found: | 699 | found: |
| 690 | *got = freq; | 700 | *got = freq; |
| 691 | *iicon |= (divs-1); | 701 | |
| 692 | *iicon |= (div1 == 512) ? S3C2410_IICCON_TXDIV_512 : 0; | 702 | iiccon = readl(i2c->regs + S3C2410_IICCON); |
| 703 | iiccon &= ~(S3C2410_IICCON_SCALEMASK | S3C2410_IICCON_TXDIV_512); | ||
| 704 | iiccon |= (divs-1); | ||
| 705 | |||
| 706 | if (div1 == 512) | ||
| 707 | iiccon |= S3C2410_IICCON_TXDIV_512; | ||
| 708 | |||
| 709 | writel(iiccon, i2c->regs + S3C2410_IICCON); | ||
| 710 | |||
| 711 | return 0; | ||
| 712 | } | ||
| 713 | |||
| 714 | #ifdef CONFIG_CPU_FREQ | ||
| 715 | |||
| 716 | #define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition) | ||
| 717 | |||
| 718 | static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, | ||
| 719 | unsigned long val, void *data) | ||
| 720 | { | ||
| 721 | struct s3c24xx_i2c *i2c = freq_to_i2c(nb); | ||
| 722 | unsigned long flags; | ||
| 723 | unsigned int got; | ||
| 724 | int delta_f; | ||
| 725 | int ret; | ||
| 726 | |||
| 727 | delta_f = clk_get_rate(i2c->clk) - i2c->clkrate; | ||
| 728 | |||
| 729 | /* if we're post-change and the input clock has slowed down | ||
| 730 | * or at pre-change and the clock is about to speed up, then | ||
| 731 | * adjust our clock rate. <0 is slow, >0 speedup. | ||
| 732 | */ | ||
| 733 | |||
| 734 | if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || | ||
| 735 | (val == CPUFREQ_PRECHANGE && delta_f > 0)) { | ||
| 736 | spin_lock_irqsave(&i2c->lock, flags); | ||
| 737 | ret = s3c24xx_i2c_clockrate(i2c, &got); | ||
| 738 | spin_unlock_irqrestore(&i2c->lock, flags); | ||
| 739 | |||
| 740 | if (ret < 0) | ||
| 741 | dev_err(i2c->dev, "cannot find frequency\n"); | ||
| 742 | else | ||
| 743 | dev_info(i2c->dev, "setting freq %d\n", got); | ||
| 744 | } | ||
| 745 | |||
| 746 | return 0; | ||
| 747 | } | ||
| 748 | |||
| 749 | static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 750 | { | ||
| 751 | i2c->freq_transition.notifier_call = s3c24xx_i2c_cpufreq_transition; | ||
| 752 | |||
| 753 | return cpufreq_register_notifier(&i2c->freq_transition, | ||
| 754 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 755 | } | ||
| 756 | |||
| 757 | static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 758 | { | ||
| 759 | cpufreq_unregister_notifier(&i2c->freq_transition, | ||
| 760 | CPUFREQ_TRANSITION_NOTIFIER); | ||
| 761 | } | ||
| 762 | |||
| 763 | #else | ||
| 764 | static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 765 | { | ||
| 693 | return 0; | 766 | return 0; |
| 694 | } | 767 | } |
| 695 | 768 | ||
| 769 | static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) | ||
| 770 | { | ||
| 771 | } | ||
| 772 | #endif | ||
| 773 | |||
| 696 | /* s3c24xx_i2c_init | 774 | /* s3c24xx_i2c_init |
| 697 | * | 775 | * |
| 698 | * initialise the controller, set the IO lines and frequency | 776 | * initialise the controller, set the IO lines and frequency |
| @@ -719,9 +797,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
| 719 | 797 | ||
| 720 | dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); | 798 | dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); |
| 721 | 799 | ||
| 800 | writel(iicon, i2c->regs + S3C2410_IICCON); | ||
| 801 | |||
| 722 | /* we need to work out the divisors for the clock... */ | 802 | /* we need to work out the divisors for the clock... */ |
| 723 | 803 | ||
| 724 | if (s3c24xx_i2c_getdivisor(i2c, pdata, &iicon, &freq) != 0) { | 804 | if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) { |
| 805 | writel(0, i2c->regs + S3C2410_IICCON); | ||
| 725 | dev_err(i2c->dev, "cannot meet bus frequency required\n"); | 806 | dev_err(i2c->dev, "cannot meet bus frequency required\n"); |
| 726 | return -EINVAL; | 807 | return -EINVAL; |
| 727 | } | 808 | } |
| @@ -730,8 +811,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
| 730 | 811 | ||
| 731 | dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); | 812 | dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); |
| 732 | dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); | 813 | dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); |
| 733 | |||
| 734 | writel(iicon, i2c->regs + S3C2410_IICCON); | ||
| 735 | 814 | ||
| 736 | /* check for s3c2440 i2c controller */ | 815 | /* check for s3c2440 i2c controller */ |
| 737 | 816 | ||
| @@ -752,9 +831,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
| 752 | static int s3c24xx_i2c_probe(struct platform_device *pdev) | 831 | static int s3c24xx_i2c_probe(struct platform_device *pdev) |
| 753 | { | 832 | { |
| 754 | struct s3c24xx_i2c *i2c = &s3c24xx_i2c; | 833 | struct s3c24xx_i2c *i2c = &s3c24xx_i2c; |
| 834 | struct s3c2410_platform_i2c *pdata; | ||
| 755 | struct resource *res; | 835 | struct resource *res; |
| 756 | int ret; | 836 | int ret; |
| 757 | 837 | ||
| 838 | pdata = s3c24xx_i2c_get_platformdata(&pdev->dev); | ||
| 839 | |||
| 758 | /* find the clock and enable it */ | 840 | /* find the clock and enable it */ |
| 759 | 841 | ||
| 760 | i2c->dev = &pdev->dev; | 842 | i2c->dev = &pdev->dev; |
| @@ -832,17 +914,34 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
| 832 | dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res, | 914 | dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res, |
| 833 | (unsigned long)res->start); | 915 | (unsigned long)res->start); |
| 834 | 916 | ||
| 835 | ret = i2c_add_adapter(&i2c->adap); | 917 | ret = s3c24xx_i2c_register_cpufreq(i2c); |
| 836 | if (ret < 0) { | 918 | if (ret < 0) { |
| 837 | dev_err(&pdev->dev, "failed to add bus to i2c core\n"); | 919 | dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); |
| 838 | goto err_irq; | 920 | goto err_irq; |
| 839 | } | 921 | } |
| 840 | 922 | ||
| 923 | /* Note, previous versions of the driver used i2c_add_adapter() | ||
| 924 | * to add the bus at any number. We now pass the bus number via | ||
| 925 | * the platform data, so if unset it will now default to always | ||
| 926 | * being bus 0. | ||
| 927 | */ | ||
| 928 | |||
| 929 | i2c->adap.nr = pdata->bus_num; | ||
| 930 | |||
| 931 | ret = i2c_add_numbered_adapter(&i2c->adap); | ||
| 932 | if (ret < 0) { | ||
| 933 | dev_err(&pdev->dev, "failed to add bus to i2c core\n"); | ||
| 934 | goto err_cpufreq; | ||
| 935 | } | ||
| 936 | |||
| 841 | platform_set_drvdata(pdev, i2c); | 937 | platform_set_drvdata(pdev, i2c); |
| 842 | 938 | ||
| 843 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); | 939 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); |
| 844 | return 0; | 940 | return 0; |
| 845 | 941 | ||
| 942 | err_cpufreq: | ||
| 943 | s3c24xx_i2c_deregister_cpufreq(i2c); | ||
| 944 | |||
| 846 | err_irq: | 945 | err_irq: |
| 847 | free_irq(i2c->irq->start, i2c); | 946 | free_irq(i2c->irq->start, i2c); |
| 848 | 947 | ||
| @@ -870,6 +969,8 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) | |||
| 870 | { | 969 | { |
| 871 | struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); | 970 | struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); |
| 872 | 971 | ||
| 972 | s3c24xx_i2c_deregister_cpufreq(i2c); | ||
| 973 | |||
| 873 | i2c_del_adapter(&i2c->adap); | 974 | i2c_del_adapter(&i2c->adap); |
| 874 | free_irq(i2c->irq->start, i2c); | 975 | free_irq(i2c->irq->start, i2c); |
| 875 | 976 | ||
diff --git a/include/asm-arm/plat-s3c/iic.h b/include/asm-arm/plat-s3c/iic.h index 71211c8b5384..d08a1f2863e4 100644 --- a/include/asm-arm/plat-s3c/iic.h +++ b/include/asm-arm/plat-s3c/iic.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | struct s3c2410_platform_i2c { | 23 | struct s3c2410_platform_i2c { |
| 24 | int bus_num; /* bus number to use */ | ||
| 24 | unsigned int flags; | 25 | unsigned int flags; |
| 25 | unsigned int slave_addr; /* slave address for controller */ | 26 | unsigned int slave_addr; /* slave address for controller */ |
| 26 | unsigned long bus_freq; /* standard bus frequency */ | 27 | unsigned long bus_freq; /* standard bus frequency */ |
