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