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