i2c-acorn.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * ARM IOC/IOMD i2c driver.
  3. *
  4. * Copyright (C) 2000 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * On Acorn machines, the following i2c devices are on the bus:
  11. * - PCF8583 real time clock & static RAM
  12. */
  13. #include <linux/module.h>
  14. #include <linux/i2c.h>
  15. #include <linux/i2c-algo-bit.h>
  16. #include <linux/io.h>
  17. #include <mach/hardware.h>
  18. #include <asm/hardware/ioc.h>
  19. #define FORCE_ONES 0xdc
  20. #define SCL 0x02
  21. #define SDA 0x01
  22. /*
  23. * We must preserve all non-i2c output bits in IOC_CONTROL.
  24. * Note also that we need to preserve the value of SCL and
  25. * SDA outputs as well (which may be different from the
  26. * values read back from IOC_CONTROL).
  27. */
  28. static u_int force_ones;
  29. static void ioc_setscl(void *data, int state)
  30. {
  31. u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
  32. u_int ones = force_ones;
  33. if (state)
  34. ones |= SCL;
  35. else
  36. ones &= ~SCL;
  37. force_ones = ones;
  38. ioc_writeb(ioc_control | ones, IOC_CONTROL);
  39. }
  40. static void ioc_setsda(void *data, int state)
  41. {
  42. u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
  43. u_int ones = force_ones;
  44. if (state)
  45. ones |= SDA;
  46. else
  47. ones &= ~SDA;
  48. force_ones = ones;
  49. ioc_writeb(ioc_control | ones, IOC_CONTROL);
  50. }
  51. static int ioc_getscl(void *data)
  52. {
  53. return (ioc_readb(IOC_CONTROL) & SCL) != 0;
  54. }
  55. static int ioc_getsda(void *data)
  56. {
  57. return (ioc_readb(IOC_CONTROL) & SDA) != 0;
  58. }
  59. static struct i2c_algo_bit_data ioc_data = {
  60. .setsda = ioc_setsda,
  61. .setscl = ioc_setscl,
  62. .getsda = ioc_getsda,
  63. .getscl = ioc_getscl,
  64. .udelay = 80,
  65. .timeout = HZ,
  66. };
  67. static struct i2c_adapter ioc_ops = {
  68. .nr = 0,
  69. .algo_data = &ioc_data,
  70. };
  71. static int __init i2c_ioc_init(void)
  72. {
  73. force_ones = FORCE_ONES | SCL | SDA;
  74. return i2c_bit_add_numbered_bus(&ioc_ops);
  75. }
  76. module_init(i2c_ioc_init);
  77. MODULE_AUTHOR("Russell King <linux@armlinux.org.uk>");
  78. MODULE_DESCRIPTION("ARM IOC/IOMD i2c driver");
  79. MODULE_LICENSE("GPL v2");