Commit | Line | Data |
---|---|---|
8d91cbad RK |
1 | /* |
2 | * linux/drivers/acorn/char/i2c.c | |
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 | * ARM IOC/IOMD i2c driver. | |
11 | * | |
12 | * On Acorn machines, the following i2c devices are on the bus: | |
13 | * - PCF8583 real time clock & static RAM | |
14 | */ | |
15 | #include <linux/init.h> | |
16 | #include <linux/i2c.h> | |
17 | #include <linux/i2c-algo-bit.h> | |
99730225 | 18 | #include <linux/io.h> |
8d91cbad | 19 | |
a09e64fb | 20 | #include <mach/hardware.h> |
8d91cbad | 21 | #include <asm/hardware/ioc.h> |
8d91cbad RK |
22 | |
23 | #define FORCE_ONES 0xdc | |
24 | #define SCL 0x02 | |
25 | #define SDA 0x01 | |
26 | ||
27 | /* | |
28 | * We must preserve all non-i2c output bits in IOC_CONTROL. | |
29 | * Note also that we need to preserve the value of SCL and | |
30 | * SDA outputs as well (which may be different from the | |
31 | * values read back from IOC_CONTROL). | |
32 | */ | |
33 | static u_int force_ones; | |
34 | ||
35 | static void ioc_setscl(void *data, int state) | |
36 | { | |
37 | u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); | |
38 | u_int ones = force_ones; | |
39 | ||
40 | if (state) | |
41 | ones |= SCL; | |
42 | else | |
43 | ones &= ~SCL; | |
44 | ||
45 | force_ones = ones; | |
46 | ||
47 | ioc_writeb(ioc_control | ones, IOC_CONTROL); | |
48 | } | |
49 | ||
50 | static void ioc_setsda(void *data, int state) | |
51 | { | |
52 | u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); | |
53 | u_int ones = force_ones; | |
54 | ||
55 | if (state) | |
56 | ones |= SDA; | |
57 | else | |
58 | ones &= ~SDA; | |
59 | ||
60 | force_ones = ones; | |
61 | ||
62 | ioc_writeb(ioc_control | ones, IOC_CONTROL); | |
63 | } | |
64 | ||
65 | static int ioc_getscl(void *data) | |
66 | { | |
67 | return (ioc_readb(IOC_CONTROL) & SCL) != 0; | |
68 | } | |
69 | ||
70 | static int ioc_getsda(void *data) | |
71 | { | |
72 | return (ioc_readb(IOC_CONTROL) & SDA) != 0; | |
73 | } | |
74 | ||
75 | static struct i2c_algo_bit_data ioc_data = { | |
76 | .setsda = ioc_setsda, | |
77 | .setscl = ioc_setscl, | |
78 | .getsda = ioc_getsda, | |
79 | .getscl = ioc_getscl, | |
80 | .udelay = 80, | |
082a4cf8 | 81 | .timeout = HZ, |
8d91cbad RK |
82 | }; |
83 | ||
84 | static struct i2c_adapter ioc_ops = { | |
531660ef | 85 | .nr = 0, |
8d91cbad RK |
86 | .algo_data = &ioc_data, |
87 | }; | |
88 | ||
89 | static int __init i2c_ioc_init(void) | |
90 | { | |
91 | force_ones = FORCE_ONES | SCL | SDA; | |
92 | ||
531660ef | 93 | return i2c_bit_add_numbered_bus(&ioc_ops); |
8d91cbad RK |
94 | } |
95 | ||
2a9915c8 | 96 | module_init(i2c_ioc_init); |