diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-au1550.c | 130 |
1 files changed, 75 insertions, 55 deletions
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index cae9dc89d88c..66a04c2c660f 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c | |||
| @@ -269,9 +269,13 @@ static int | |||
| 269 | au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | 269 | au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) |
| 270 | { | 270 | { |
| 271 | struct i2c_au1550_data *adap = i2c_adap->algo_data; | 271 | struct i2c_au1550_data *adap = i2c_adap->algo_data; |
| 272 | volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base; | ||
| 272 | struct i2c_msg *p; | 273 | struct i2c_msg *p; |
| 273 | int i, err = 0; | 274 | int i, err = 0; |
| 274 | 275 | ||
| 276 | sp->psc_ctrl = PSC_CTRL_ENABLE; | ||
| 277 | au_sync(); | ||
| 278 | |||
| 275 | for (i = 0; !err && i < num; i++) { | 279 | for (i = 0; !err && i < num; i++) { |
| 276 | p = &msgs[i]; | 280 | p = &msgs[i]; |
| 277 | err = do_address(adap, p->addr, p->flags & I2C_M_RD, | 281 | err = do_address(adap, p->addr, p->flags & I2C_M_RD, |
| @@ -288,6 +292,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | |||
| 288 | */ | 292 | */ |
| 289 | if (err == 0) | 293 | if (err == 0) |
| 290 | err = num; | 294 | err = num; |
| 295 | |||
| 296 | sp->psc_ctrl = PSC_CTRL_SUSPEND; | ||
| 297 | au_sync(); | ||
| 298 | |||
| 291 | return err; | 299 | return err; |
| 292 | } | 300 | } |
| 293 | 301 | ||
| @@ -302,6 +310,61 @@ static const struct i2c_algorithm au1550_algo = { | |||
| 302 | .functionality = au1550_func, | 310 | .functionality = au1550_func, |
| 303 | }; | 311 | }; |
| 304 | 312 | ||
| 313 | static void i2c_au1550_setup(struct i2c_au1550_data *priv) | ||
| 314 | { | ||
| 315 | volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; | ||
| 316 | u32 stat; | ||
| 317 | |||
| 318 | sp->psc_ctrl = PSC_CTRL_DISABLE; | ||
| 319 | au_sync(); | ||
| 320 | sp->psc_sel = PSC_SEL_PS_SMBUSMODE; | ||
| 321 | sp->psc_smbcfg = 0; | ||
| 322 | au_sync(); | ||
| 323 | sp->psc_ctrl = PSC_CTRL_ENABLE; | ||
| 324 | au_sync(); | ||
| 325 | do { | ||
| 326 | stat = sp->psc_smbstat; | ||
| 327 | au_sync(); | ||
| 328 | } while ((stat & PSC_SMBSTAT_SR) == 0); | ||
| 329 | |||
| 330 | sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | | ||
| 331 | PSC_SMBCFG_DD_DISABLE); | ||
| 332 | |||
| 333 | /* Divide by 8 to get a 6.25 MHz clock. The later protocol | ||
| 334 | * timings are based on this clock. | ||
| 335 | */ | ||
| 336 | sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8); | ||
| 337 | sp->psc_smbmsk = PSC_SMBMSK_ALLMASK; | ||
| 338 | au_sync(); | ||
| 339 | |||
| 340 | /* Set the protocol timer values. See Table 71 in the | ||
| 341 | * Au1550 Data Book for standard timing values. | ||
| 342 | */ | ||
| 343 | sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \ | ||
| 344 | PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \ | ||
| 345 | PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \ | ||
| 346 | PSC_SMBTMR_SET_CH(15); | ||
| 347 | au_sync(); | ||
| 348 | |||
| 349 | sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE; | ||
| 350 | do { | ||
| 351 | stat = sp->psc_smbstat; | ||
| 352 | au_sync(); | ||
| 353 | } while ((stat & PSC_SMBSTAT_SR) == 0); | ||
| 354 | |||
| 355 | sp->psc_ctrl = PSC_CTRL_SUSPEND; | ||
| 356 | au_sync(); | ||
| 357 | } | ||
| 358 | |||
| 359 | static void i2c_au1550_disable(struct i2c_au1550_data *priv) | ||
| 360 | { | ||
| 361 | volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; | ||
| 362 | |||
| 363 | sp->psc_smbcfg = 0; | ||
| 364 | sp->psc_ctrl = PSC_CTRL_DISABLE; | ||
| 365 | au_sync(); | ||
| 366 | } | ||
| 367 | |||
| 305 | /* | 368 | /* |
| 306 | * registering functions to load algorithms at runtime | 369 | * registering functions to load algorithms at runtime |
| 307 | * Prior to calling us, the 50MHz clock frequency and routing | 370 | * Prior to calling us, the 50MHz clock frequency and routing |
| @@ -311,9 +374,7 @@ static int __devinit | |||
| 311 | i2c_au1550_probe(struct platform_device *pdev) | 374 | i2c_au1550_probe(struct platform_device *pdev) |
| 312 | { | 375 | { |
| 313 | struct i2c_au1550_data *priv; | 376 | struct i2c_au1550_data *priv; |
| 314 | volatile psc_smb_t *sp; | ||
| 315 | struct resource *r; | 377 | struct resource *r; |
| 316 | u32 stat; | ||
| 317 | int ret; | 378 | int ret; |
| 318 | 379 | ||
| 319 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 380 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -348,43 +409,7 @@ i2c_au1550_probe(struct platform_device *pdev) | |||
| 348 | 409 | ||
| 349 | /* Now, set up the PSC for SMBus PIO mode. | 410 | /* Now, set up the PSC for SMBus PIO mode. |
| 350 | */ | 411 | */ |
| 351 | sp = (volatile psc_smb_t *)priv->psc_base; | 412 | i2c_au1550_setup(priv); |
| 352 | sp->psc_ctrl = PSC_CTRL_DISABLE; | ||
| 353 | au_sync(); | ||
| 354 | sp->psc_sel = PSC_SEL_PS_SMBUSMODE; | ||
| 355 | sp->psc_smbcfg = 0; | ||
| 356 | au_sync(); | ||
| 357 | sp->psc_ctrl = PSC_CTRL_ENABLE; | ||
| 358 | au_sync(); | ||
| 359 | do { | ||
| 360 | stat = sp->psc_smbstat; | ||
| 361 | au_sync(); | ||
| 362 | } while ((stat & PSC_SMBSTAT_SR) == 0); | ||
| 363 | |||
| 364 | sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | | ||
| 365 | PSC_SMBCFG_DD_DISABLE); | ||
| 366 | |||
| 367 | /* Divide by 8 to get a 6.25 MHz clock. The later protocol | ||
| 368 | * timings are based on this clock. | ||
| 369 | */ | ||
| 370 | sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8); | ||
| 371 | sp->psc_smbmsk = PSC_SMBMSK_ALLMASK; | ||
| 372 | au_sync(); | ||
| 373 | |||
| 374 | /* Set the protocol timer values. See Table 71 in the | ||
| 375 | * Au1550 Data Book for standard timing values. | ||
| 376 | */ | ||
| 377 | sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \ | ||
| 378 | PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \ | ||
| 379 | PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \ | ||
| 380 | PSC_SMBTMR_SET_CH(15); | ||
| 381 | au_sync(); | ||
| 382 | |||
| 383 | sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE; | ||
| 384 | do { | ||
| 385 | stat = sp->psc_smbstat; | ||
| 386 | au_sync(); | ||
| 387 | } while ((stat & PSC_SMBSTAT_DR) == 0); | ||
| 388 | 413 | ||
| 389 | ret = i2c_add_numbered_adapter(&priv->adap); | 414 | ret = i2c_add_numbered_adapter(&priv->adap); |
| 390 | if (ret == 0) { | 415 | if (ret == 0) { |
| @@ -392,10 +417,7 @@ i2c_au1550_probe(struct platform_device *pdev) | |||
| 392 | return 0; | 417 | return 0; |
| 393 | } | 418 | } |
| 394 | 419 | ||
| 395 | /* disable the PSC */ | 420 | i2c_au1550_disable(priv); |
| 396 | sp->psc_smbcfg = 0; | ||
| 397 | sp->psc_ctrl = PSC_CTRL_DISABLE; | ||
| 398 | au_sync(); | ||
| 399 | 421 | ||
| 400 | release_resource(priv->ioarea); | 422 | release_resource(priv->ioarea); |
| 401 | kfree(priv->ioarea); | 423 | kfree(priv->ioarea); |
| @@ -409,27 +431,24 @@ static int __devexit | |||
| 409 | i2c_au1550_remove(struct platform_device *pdev) | 431 | i2c_au1550_remove(struct platform_device *pdev) |
| 410 | { | 432 | { |
| 411 | struct i2c_au1550_data *priv = platform_get_drvdata(pdev); | 433 | struct i2c_au1550_data *priv = platform_get_drvdata(pdev); |
| 412 | volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; | ||
| 413 | 434 | ||
| 414 | platform_set_drvdata(pdev, NULL); | 435 | platform_set_drvdata(pdev, NULL); |
| 415 | i2c_del_adapter(&priv->adap); | 436 | i2c_del_adapter(&priv->adap); |
| 416 | sp->psc_smbcfg = 0; | 437 | i2c_au1550_disable(priv); |
| 417 | sp->psc_ctrl = PSC_CTRL_DISABLE; | ||
| 418 | au_sync(); | ||
| 419 | release_resource(priv->ioarea); | 438 | release_resource(priv->ioarea); |
| 420 | kfree(priv->ioarea); | 439 | kfree(priv->ioarea); |
| 421 | kfree(priv); | 440 | kfree(priv); |
| 422 | return 0; | 441 | return 0; |
| 423 | } | 442 | } |
| 424 | 443 | ||
| 444 | #ifdef CONFIG_PM | ||
| 425 | static int | 445 | static int |
| 426 | i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state) | 446 | i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state) |
| 427 | { | 447 | { |
| 428 | struct i2c_au1550_data *priv = platform_get_drvdata(pdev); | 448 | struct i2c_au1550_data *priv = platform_get_drvdata(pdev); |
| 429 | volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; | ||
| 430 | 449 | ||
| 431 | sp->psc_ctrl = PSC_CTRL_SUSPEND; | 450 | i2c_au1550_disable(priv); |
| 432 | au_sync(); | 451 | |
| 433 | return 0; | 452 | return 0; |
| 434 | } | 453 | } |
| 435 | 454 | ||
| @@ -437,14 +456,15 @@ static int | |||
| 437 | i2c_au1550_resume(struct platform_device *pdev) | 456 | i2c_au1550_resume(struct platform_device *pdev) |
| 438 | { | 457 | { |
| 439 | struct i2c_au1550_data *priv = platform_get_drvdata(pdev); | 458 | struct i2c_au1550_data *priv = platform_get_drvdata(pdev); |
| 440 | volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base; | ||
| 441 | 459 | ||
| 442 | sp->psc_ctrl = PSC_CTRL_ENABLE; | 460 | i2c_au1550_setup(priv); |
| 443 | au_sync(); | 461 | |
| 444 | while (!(sp->psc_smbstat & PSC_SMBSTAT_SR)) | ||
| 445 | au_sync(); | ||
| 446 | return 0; | 462 | return 0; |
| 447 | } | 463 | } |
| 464 | #else | ||
| 465 | #define i2c_au1550_suspend NULL | ||
| 466 | #define i2c_au1550_resume NULL | ||
| 467 | #endif | ||
| 448 | 468 | ||
| 449 | static struct platform_driver au1xpsc_smbus_driver = { | 469 | static struct platform_driver au1xpsc_smbus_driver = { |
| 450 | .driver = { | 470 | .driver = { |
