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/sched.h>
17#include <linux/i2c.h>
18#include <linux/i2c-algo-bit.h>
19
20#include <asm/hardware.h>
21#include <asm/io.h>
22#include <asm/hardware/ioc.h>
23#include <asm/system.h>
24
25#include "pcf8583.h"
26
27extern unsigned long
28mktime(unsigned int year, unsigned int mon, unsigned int day,
29       unsigned int hour, unsigned int min, unsigned int sec);
30extern int (*set_rtc)(void);
31
32static struct i2c_client *rtc_client;
33
34static inline int rtc_command(int cmd, void *data)
35{
36	int ret = -EIO;
37
38	if (rtc_client)
39		ret = rtc_client->driver->command(rtc_client, cmd, data);
40
41	return ret;
42}
43
44/*
45 * Read the current RTC time and date, and update xtime.
46 */
47static void get_rtc_time(void)
48{
49	unsigned char ctrl;
50	unsigned char year;
51	struct rtc_tm rtctm;
52	struct mem rtcmem = { 0xc0, 1, &year };
53
54	/*
55	 * Ensure that the RTC is running.
56	 */
57	rtc_command(RTC_GETCTRL, &ctrl);
58	if (ctrl & 0xc0) {
59		unsigned char new_ctrl;
60
61		new_ctrl = ctrl & ~0xc0;
62
63		printk("RTC: resetting control %02X -> %02X\n",
64		       ctrl, new_ctrl);
65
66		rtc_command(RTC_SETCTRL, &new_ctrl);
67	}
68
69	/*
70	 * Acorn machines store the year in
71	 * the static RAM at location 192.
72	 */
73	if (rtc_command(MEM_READ, &rtcmem))
74		return;
75
76	if (rtc_command(RTC_GETDATETIME, &rtctm))
77		return;
78
79	if (year < 70)
80		year += 100;
81
82	xtime.tv_usec = rtctm.cs * 10000;
83	xtime.tv_sec  = mktime(1900 + year, rtctm.mon, rtctm.mday,
84			       rtctm.hours, rtctm.mins, rtctm.secs);
85}
86
87/*
88 * Set the RTC time only.  Note that
89 * we do not touch the date.
90 */
91static int set_rtc_time(void)
92{
93	struct rtc_tm new_rtctm, old_rtctm;
94	unsigned long nowtime = xtime.tv_sec;
95
96	if (rtc_command(RTC_GETDATETIME, &old_rtctm))
97		return 0;
98
99	new_rtctm.cs    = xtime.tv_usec / 10000;
100	new_rtctm.secs  = nowtime % 60;	nowtime /= 60;
101	new_rtctm.mins  = nowtime % 60;	nowtime /= 60;
102	new_rtctm.hours = nowtime % 24;
103
104	/*
105	 * avoid writing when we're going to change the day
106	 * of the month.  We will retry in the next minute.
107	 * This basically means that if the RTC must not drift
108	 * by more than 1 minute in 11 minutes.
109	 *
110	 * [ rtc: 1/1/2000 23:58:00, real 2/1/2000 00:01:00,
111	 *   rtc gets set to 1/1/2000 00:01:00 ]
112	 */
113	if ((old_rtctm.hours == 23 && old_rtctm.mins  == 59) ||
114	    (new_rtctm.hours == 23 && new_rtctm.mins  == 59))
115		return 1;
116
117	return rtc_command(RTC_SETTIME, &new_rtctm);
118}
119
120
121#define FORCE_ONES	0xdc
122#define SCL		0x02
123#define SDA		0x01
124
125/*
126 * We must preserve all non-i2c output bits in IOC_CONTROL.
127 * Note also that we need to preserve the value of SCL and
128 * SDA outputs as well (which may be different from the
129 * values read back from IOC_CONTROL).
130 */
131static u_int force_ones;
132
133static void ioc_setscl(void *data, int state)
134{
135	u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
136	u_int ones = force_ones;
137
138	if (state)
139		ones |= SCL;
140	else
141		ones &= ~SCL;
142
143	force_ones = ones;
144
145 	ioc_writeb(ioc_control | ones, IOC_CONTROL);
146}
147
148static void ioc_setsda(void *data, int state)
149{
150	u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
151	u_int ones = force_ones;
152
153	if (state)
154		ones |= SDA;
155	else
156		ones &= ~SDA;
157
158	force_ones = ones;
159
160 	ioc_writeb(ioc_control | ones, IOC_CONTROL);
161}
162
163static int ioc_getscl(void *data)
164{
165	return (ioc_readb(IOC_CONTROL) & SCL) != 0;
166}
167
168static int ioc_getsda(void *data)
169{
170	return (ioc_readb(IOC_CONTROL) & SDA) != 0;
171}
172
173static struct i2c_algo_bit_data ioc_data = {
174	setsda:		ioc_setsda,
175	setscl:		ioc_setscl,
176	getsda:		ioc_getsda,
177	getscl:		ioc_getscl,
178	udelay:		 80,
179	mdelay:		 80,
180	timeout:	100
181};
182
183static int ioc_client_reg(struct i2c_client *client)
184{
185	if (client->id == I2C_DRIVERID_PCF8583 &&
186	    client->addr == 0x50) {
187		rtc_client = client;
188		get_rtc_time();
189		set_rtc = set_rtc_time;
190	}
191
192	return 0;
193}
194
195static int ioc_client_unreg(struct i2c_client *client)
196{
197	if (client == rtc_client) {
198		set_rtc = NULL;
199		rtc_client = NULL;
200	}
201
202	return 0;
203}
204
205static struct i2c_adapter ioc_ops = {
206	name:			"IOC/IOMD",
207	id:			I2C_HW_B_IOC,
208	algo_data:		&ioc_data,
209	client_register:	ioc_client_reg,
210	client_unregister:	ioc_client_unreg
211};
212
213static int __init i2c_ioc_init(void)
214{
215	force_ones = FORCE_ONES | SCL | SDA;
216
217	return i2c_bit_add_bus(&ioc_ops);
218}
219
220__initcall(i2c_ioc_init);
221