source: trunk/target/linux/sibyte/patches-3.3/103-m41t80_smbus.patch @ 31680

Last change on this file since 31680 was 31680, checked in by juhosg, 4 years ago

sibyte: add 3.3 support

File size: 9.7 KB
  • drivers/rtc/rtc-m41t80.c

    a b  
    66 * Based on m41t00.c by Mark A. Greer <mgreer@mvista.com> 
    77 * 
    88 * 2006 (c) mycable GmbH 
     9 * Copyright (c) 2008  Maciej W. Rozycki 
    910 * 
    1011 * This program is free software; you can redistribute it and/or modify 
    1112 * it under the terms of the GNU General Public License version 2 as 
     
    3839#define M41T80_REG_DAY  5 
    3940#define M41T80_REG_MON  6 
    4041#define M41T80_REG_YEAR 7 
     42#define M41T80_REG_CONTROL      8 
     43#define M41T80_REG_WATCHDOG     9 
    4144#define M41T80_REG_ALARM_MON    0xa 
    4245#define M41T80_REG_ALARM_DAY    0xb 
    4346#define M41T80_REG_ALARM_HOUR   0xc 
     
    6669#define M41T80_FEATURE_WD       (1 << 3)        /* Extra watchdog resolution */ 
    6770#define M41T80_FEATURE_SQ_ALT   (1 << 4)        /* RSx bits are in reg 4 */ 
    6871 
    69 #define DRV_VERSION "0.05" 
     72#define DRV_VERSION "0.06" 
    7073 
    7174static DEFINE_MUTEX(m41t80_rtc_mutex); 
    7275static const struct i2c_device_id m41t80_id[] = { 
    struct m41t80_data { 
    8992        struct rtc_device *rtc; 
    9093}; 
    9194 
    92 static int m41t80_get_datetime(struct i2c_client *client, 
    93                                struct rtc_time *tm) 
     95 
     96static int m41t80_write_block_data(struct i2c_client *client, 
     97                                   u8 reg, u8 num, u8 *buf) 
    9498{ 
    95         u8 buf[M41T80_DATETIME_REG_SIZE], dt_addr[1] = { M41T80_REG_SEC }; 
    96         struct i2c_msg msgs[] = { 
    97                 { 
    98                         .addr   = client->addr, 
    99                         .flags  = 0, 
    100                         .len    = 1, 
    101                         .buf    = dt_addr, 
    102                 }, 
    103                 { 
    104                         .addr   = client->addr, 
    105                         .flags  = I2C_M_RD, 
    106                         .len    = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, 
    107                         .buf    = buf + M41T80_REG_SEC, 
    108                 }, 
    109         }; 
     99        int i, rc; 
    110100 
    111         if (i2c_transfer(client->adapter, msgs, 2) < 0) { 
    112                 dev_err(&client->dev, "read error\n"); 
    113                 return -EIO; 
     101        if (i2c_check_functionality(client->adapter, 
     102                                    I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { 
     103                i = i2c_smbus_write_i2c_block_data(client, reg, num, buf); 
     104        } else { 
     105                for (i = 0; i < num; i++) { 
     106                        rc = i2c_smbus_write_byte_data(client, reg + i, 
     107                                                       buf[i]); 
     108                        if (rc < 0) { 
     109                                i = rc; 
     110                                goto out; 
     111                        } 
     112                } 
    114113        } 
     114out: 
     115        return i; 
     116} 
     117 
     118static int m41t80_read_block_data(struct i2c_client *client, 
     119                                  u8 reg, u8 num, u8 *buf) 
     120{ 
     121        int i, rc; 
     122 
     123        if (i2c_check_functionality(client->adapter, 
     124                                    I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { 
     125                i = i2c_smbus_read_i2c_block_data(client, reg, num, buf); 
     126        } else { 
     127                for (i = 0; i < num; i++) { 
     128                        rc = i2c_smbus_read_byte_data(client, reg + i); 
     129                        if (rc < 0) { 
     130                                i = rc; 
     131                                goto out; 
     132                        } 
     133                        buf[i] = rc; 
     134                } 
     135        } 
     136out: 
     137        return i; 
     138} 
     139 
     140static int m41t80_get_datetime(struct i2c_client *client, struct rtc_time *tm) 
     141{ 
     142        u8 buf[M41T80_DATETIME_REG_SIZE]; 
     143        int loops = 2; 
     144        int sec0, sec1; 
     145 
     146        /* 
     147         * Time registers are latched by this chip if an I2C block 
     148         * transfer is used, but with SMBus-style byte accesses 
     149         * this is not the case, so check seconds for a wraparound. 
     150         */ 
     151        do { 
     152                if (m41t80_read_block_data(client, M41T80_REG_SEC, 
     153                                           M41T80_DATETIME_REG_SIZE - 
     154                                           M41T80_REG_SEC, 
     155                                           buf + M41T80_REG_SEC) < 0) { 
     156                        dev_err(&client->dev, "read error\n"); 
     157                        return -EIO; 
     158                } 
     159                if (i2c_check_functionality(client->adapter, 
     160                                            I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { 
     161                        sec1 = buf[M41T80_REG_SEC]; 
     162                        break; 
     163                } 
     164 
     165                sec0 = buf[M41T80_REG_SEC]; 
     166                sec1 = i2c_smbus_read_byte_data(client, M41T80_REG_SEC); 
     167                if (sec1 < 0) { 
     168                        dev_err(&client->dev, "read error\n"); 
     169                        return -EIO; 
     170                } 
     171 
     172                sec0 = bcd2bin(sec0 & 0x7f); 
     173                sec1 = bcd2bin(sec1 & 0x7f); 
     174        } while (sec1 < sec0 && --loops); 
    115175 
    116         tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f); 
     176        tm->tm_sec = sec1; 
    117177        tm->tm_min = bcd2bin(buf[M41T80_REG_MIN] & 0x7f); 
    118178        tm->tm_hour = bcd2bin(buf[M41T80_REG_HOUR] & 0x3f); 
    119179        tm->tm_mday = bcd2bin(buf[M41T80_REG_DAY] & 0x3f); 
    static int m41t80_get_datetime(struct i2 
    128188/* Sets the given date and time to the real time clock. */ 
    129189static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) 
    130190{ 
    131         u8 wbuf[1 + M41T80_DATETIME_REG_SIZE]; 
    132         u8 *buf = &wbuf[1]; 
    133         u8 dt_addr[1] = { M41T80_REG_SEC }; 
    134         struct i2c_msg msgs_in[] = { 
    135                 { 
    136                         .addr   = client->addr, 
    137                         .flags  = 0, 
    138                         .len    = 1, 
    139                         .buf    = dt_addr, 
    140                 }, 
    141                 { 
    142                         .addr   = client->addr, 
    143                         .flags  = I2C_M_RD, 
    144                         .len    = M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, 
    145                         .buf    = buf + M41T80_REG_SEC, 
    146                 }, 
    147         }; 
    148         struct i2c_msg msgs[] = { 
    149                 { 
    150                         .addr   = client->addr, 
    151                         .flags  = 0, 
    152                         .len    = 1 + M41T80_DATETIME_REG_SIZE, 
    153                         .buf    = wbuf, 
    154                  }, 
    155         }; 
     191        u8 buf[M41T80_DATETIME_REG_SIZE]; 
    156192 
    157193        /* Read current reg values into buf[1..7] */ 
    158         if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { 
     194        if (m41t80_read_block_data(client, M41T80_REG_SEC, 
     195                                   M41T80_DATETIME_REG_SIZE - M41T80_REG_SEC, 
     196                                   buf + M41T80_REG_SEC) < 0) { 
    159197                dev_err(&client->dev, "read error\n"); 
    160198                return -EIO; 
    161199        } 
    162200 
    163         wbuf[0] = 0; /* offset into rtc's regs */ 
    164201        /* Merge time-data and register flags into buf[0..7] */ 
    165202        buf[M41T80_REG_SSEC] = 0; 
    166203        buf[M41T80_REG_SEC] = 
    static int m41t80_set_datetime(struct i2 
    178215        /* assume 20YY not 19YY */ 
    179216        buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100); 
    180217 
    181         if (i2c_transfer(client->adapter, msgs, 1) != 1) { 
     218        if (m41t80_write_block_data(client, M41T80_REG_SSEC, 
     219                                    M41T80_DATETIME_REG_SIZE, buf) < 0) { 
    182220                dev_err(&client->dev, "write error\n"); 
    183221                return -EIO; 
    184222        } 
    err: 
    238276static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) 
    239277{ 
    240278        struct i2c_client *client = to_i2c_client(dev); 
    241         u8 wbuf[1 + M41T80_ALARM_REG_SIZE]; 
    242         u8 *buf = &wbuf[1]; 
     279        u8 buf[M41T80_ALARM_REG_SIZE]; 
    243280        u8 *reg = buf - M41T80_REG_ALARM_MON; 
    244         u8 dt_addr[1] = { M41T80_REG_ALARM_MON }; 
    245         struct i2c_msg msgs_in[] = { 
    246                 { 
    247                         .addr   = client->addr, 
    248                         .flags  = 0, 
    249                         .len    = 1, 
    250                         .buf    = dt_addr, 
    251                 }, 
    252                 { 
    253                         .addr   = client->addr, 
    254                         .flags  = I2C_M_RD, 
    255                         .len    = M41T80_ALARM_REG_SIZE, 
    256                         .buf    = buf, 
    257                 }, 
    258         }; 
    259         struct i2c_msg msgs[] = { 
    260                 { 
    261                         .addr   = client->addr, 
    262                         .flags  = 0, 
    263                         .len    = 1 + M41T80_ALARM_REG_SIZE, 
    264                         .buf    = wbuf, 
    265                  }, 
    266         }; 
    267281 
    268         if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { 
     282        if (m41t80_read_block_data(client, M41T80_REG_ALARM_MON, 
     283                                   M41T80_ALARM_REG_SIZE, buf) < 0) { 
    269284                dev_err(&client->dev, "read error\n"); 
    270285                return -EIO; 
    271286        } 
    static int m41t80_rtc_set_alarm(struct d 
    275290        reg[M41T80_REG_ALARM_MIN] = 0; 
    276291        reg[M41T80_REG_ALARM_SEC] = 0; 
    277292 
    278         wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */ 
    279293        reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ? 
    280294                bin2bcd(t->time.tm_sec) : 0x80; 
    281295        reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ? 
    static int m41t80_rtc_set_alarm(struct d 
    289303        else 
    290304                reg[M41T80_REG_ALARM_DAY] |= 0x40; 
    291305 
    292         if (i2c_transfer(client->adapter, msgs, 1) != 1) { 
     306        if (m41t80_write_block_data(client, M41T80_REG_ALARM_MON, 
     307                                    M41T80_ALARM_REG_SIZE, buf) < 0) { 
    293308                dev_err(&client->dev, "write error\n"); 
    294309                return -EIO; 
    295310        } 
    static int m41t80_rtc_read_alarm(struct 
    309324{ 
    310325        struct i2c_client *client = to_i2c_client(dev); 
    311326        u8 buf[M41T80_ALARM_REG_SIZE + 1]; /* all alarm regs and flags */ 
    312         u8 dt_addr[1] = { M41T80_REG_ALARM_MON }; 
    313327        u8 *reg = buf - M41T80_REG_ALARM_MON; 
    314         struct i2c_msg msgs[] = { 
    315                 { 
    316                         .addr   = client->addr, 
    317                         .flags  = 0, 
    318                         .len    = 1, 
    319                         .buf    = dt_addr, 
    320                 }, 
    321                 { 
    322                         .addr   = client->addr, 
    323                         .flags  = I2C_M_RD, 
    324                         .len    = M41T80_ALARM_REG_SIZE + 1, 
    325                         .buf    = buf, 
    326                 }, 
    327         }; 
    328328 
    329         if (i2c_transfer(client->adapter, msgs, 2) < 0) { 
     329        if (m41t80_read_block_data(client, M41T80_REG_ALARM_MON, 
     330                                   M41T80_ALARM_REG_SIZE + 1, buf) < 0) { 
    330331                dev_err(&client->dev, "read error\n"); 
    331332                return -EIO; 
    332333        } 
    static int boot_flag; 
    508509 */ 
    509510static void wdt_ping(void) 
    510511{ 
    511         unsigned char i2c_data[2]; 
    512         struct i2c_msg msgs1[1] = { 
    513                 { 
    514                         .addr   = save_client->addr, 
    515                         .flags  = 0, 
    516                         .len    = 2, 
    517                         .buf    = i2c_data, 
    518                 }, 
    519         }; 
    520         struct m41t80_data *clientdata = i2c_get_clientdata(save_client); 
     512        u8 wdt = 0x80;                          /* WDS = 1 (0x80)  */ 
    521513 
    522         i2c_data[0] = 0x09;             /* watchdog register */ 
     514        struct m41t80_data *clientdata = i2c_get_clientdata(save_client); 
    523515 
    524516        if (wdt_margin > 31) 
    525                 i2c_data[1] = (wdt_margin & 0xFC) | 0x83; /* resolution = 4s */ 
     517                /* mulitplier = WD_TIMO / 4, resolution = 4s (0x3)  */ 
     518                wdt |= (wdt_margin & 0xfc) | 0x3; 
    526519        else 
    527                 /* 
    528                  * WDS = 1 (0x80), mulitplier = WD_TIMO, resolution = 1s (0x02) 
    529                  */ 
    530                 i2c_data[1] = wdt_margin<<2 | 0x82; 
     520                /* mulitplier = WD_TIMO, resolution = 1s (0x2)  */ 
     521                wdt |= wdt_margin << 2 | 0x2; 
    531522 
    532523        /* 
    533524         * M41T65 has three bits for watchdog resolution.  Don't set bit 7, as 
    static void wdt_ping(void) 
    536527        if (clientdata->features & M41T80_FEATURE_WD) 
    537528                i2c_data[1] &= ~M41T80_WATCHDOG_RB2; 
    538529 
    539         i2c_transfer(save_client->adapter, msgs1, 1); 
     530        i2c_smbus_write_byte_data(save_client, M41T80_REG_WATCHDOG, wdt); 
    540531} 
    541532 
    542533/** 
    static void wdt_ping(void) 
    546537 */ 
    547538static void wdt_disable(void) 
    548539{ 
    549         unsigned char i2c_data[2], i2c_buf[0x10]; 
    550         struct i2c_msg msgs0[2] = { 
    551                 { 
    552                         .addr   = save_client->addr, 
    553                         .flags  = 0, 
    554                         .len    = 1, 
    555                         .buf    = i2c_data, 
    556                 }, 
    557                 { 
    558                         .addr   = save_client->addr, 
    559                         .flags  = I2C_M_RD, 
    560                         .len    = 1, 
    561                         .buf    = i2c_buf, 
    562                 }, 
    563         }; 
    564         struct i2c_msg msgs1[1] = { 
    565                 { 
    566                         .addr   = save_client->addr, 
    567                         .flags  = 0, 
    568                         .len    = 2, 
    569                         .buf    = i2c_data, 
    570                 }, 
    571         }; 
    572  
    573         i2c_data[0] = 0x09; 
    574         i2c_transfer(save_client->adapter, msgs0, 2); 
    575  
    576         i2c_data[0] = 0x09; 
    577         i2c_data[1] = 0x00; 
    578         i2c_transfer(save_client->adapter, msgs1, 1); 
     540        i2c_smbus_read_byte_data(save_client, M41T80_REG_WATCHDOG); 
     541        i2c_smbus_write_byte_data(save_client, M41T80_REG_WATCHDOG, 0); 
    579542} 
    580543 
    581544/** 
    static int m41t80_probe(struct i2c_clien 
    777740        struct rtc_time tm; 
    778741        struct m41t80_data *clientdata = NULL; 
    779742 
    780         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C 
    781                                      | I2C_FUNC_SMBUS_BYTE_DATA)) { 
     743        if (!i2c_check_functionality(client->adapter, 
     744                                     I2C_FUNC_SMBUS_BYTE_DATA)) { 
    782745                rc = -ENODEV; 
    783746                goto exit; 
    784747        } 
Note: See TracBrowser for help on using the repository browser.