Ignore:
Timestamp:
Apr 21, 2017, 4:28:29 AM (2 months ago)
Author:
brainslayer
Message:

update

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/linux/universal/linux-3.18/drivers/rtc/rtc-s35390a.c

    r25370 r31885  
    1616#include <linux/bcd.h>
    1717#include <linux/slab.h>
     18#include <linux/delay.h>
    1819
    1920#define S35390A_CMD_STATUS1     0
     
    3536#define S35390A_ALRM_BYTE_MINS  2
    3637
     38/* flags for STATUS1 */
    3739#define S35390A_FLAG_POC        0x01
    3840#define S35390A_FLAG_BLD        0x02
     41#define S35390A_FLAG_INT2       0x04
    3942#define S35390A_FLAG_24H        0x40
    4043#define S35390A_FLAG_RESET      0x80
     44
     45/* flag for STATUS2 */
    4146#define S35390A_FLAG_TEST       0x01
    4247
     
    95100}
    96101
    97 static int s35390a_reset(struct s35390a *s35390a)
    98 {
    99         char buf[1];
    100 
    101         if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0)
    102                 return -EIO;
    103 
    104         if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD)))
     102/*
     103 * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.
     104 * To keep the information if an irq is pending, pass the value read from
     105 * STATUS1 to the caller.
     106 */
     107static int s35390a_reset(struct s35390a *s35390a, char *status1)
     108{
     109        char buf;
     110        int ret;
     111        unsigned initcount = 0;
     112
     113        ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
     114        if (ret < 0)
     115                return ret;
     116
     117        if (*status1 & S35390A_FLAG_POC)
     118                /*
     119                 * Do not communicate for 0.5 seconds since the power-on
     120                 * detection circuit is in operation.
     121                 */
     122                msleep(500);
     123        else if (!(*status1 & S35390A_FLAG_BLD))
     124                /*
     125                 * If both POC and BLD are unset everything is fine.
     126                 */
    105127                return 0;
    106128
    107         buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H);
    108         buf[0] &= 0xf0;
    109         return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
     129        /*
     130         * At least one of POC and BLD are set, so reinitialise chip. Keeping
     131         * this information in the hardware to know later that the time isn't
     132         * valid is unfortunately not possible because POC and BLD are cleared
     133         * on read. So the reset is best done now.
     134         *
     135         * The 24H bit is kept over reset, so set it already here.
     136         */
     137initialize:
     138        *status1 = S35390A_FLAG_24H;
     139        buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;
     140        ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
     141
     142        if (ret < 0)
     143                return ret;
     144
     145        ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
     146        if (ret < 0)
     147                return ret;
     148
     149        if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {
     150                /* Try up to five times to reset the chip */
     151                if (initcount < 5) {
     152                        ++initcount;
     153                        goto initialize;
     154                } else
     155                        return -EIO;
     156        }
     157
     158        return 1;
    110159}
    111160
     
    243292        if (alm->time.tm_wday != -1)
    244293                buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
     294        else
     295                buf[S35390A_ALRM_BYTE_WDAY] = 0;
    245296
    246297        buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
     
    266317        int i, err;
    267318
     319        /*
     320         * initialize all members to -1 to signal the core that they are not
     321         * defined by the hardware.
     322         */
     323        alm->time.tm_sec = -1;
     324        alm->time.tm_min = -1;
     325        alm->time.tm_hour = -1;
     326        alm->time.tm_mday = -1;
     327        alm->time.tm_mon = -1;
     328        alm->time.tm_year = -1;
     329        alm->time.tm_wday = -1;
     330        alm->time.tm_yday = -1;
     331        alm->time.tm_isdst = -1;
     332
    268333        err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
    269334        if (err < 0)
    270335                return err;
    271336
    272         if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
    273                 return -EINVAL;
     337        if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
     338                /*
     339                 * When the alarm isn't enabled, the register to configure
     340                 * the alarm time isn't accessible.
     341                 */
     342                alm->enabled = 0;
     343                return 0;
     344        } else {
     345                alm->enabled = 1;
     346        }
    274347
    275348        err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
     
    278351
    279352        /* This chip returns the bits of each byte in reverse order */
    280         for (i = 0; i < 3; ++i) {
     353        for (i = 0; i < 3; ++i)
    281354                buf[i] = bitrev8(buf[i]);
    282                 buf[i] &= ~0x80;
    283         }
    284 
    285         alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
    286         alm->time.tm_hour = s35390a_reg2hr(s35390a,
    287                                                 buf[S35390A_ALRM_BYTE_HOURS]);
    288         alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
     355
     356        /*
     357         * B0 of the three matching registers is an enable flag. Iff it is set
     358         * the configured value is used for matching.
     359         */
     360        if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
     361                alm->time.tm_wday =
     362                        bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
     363
     364        if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
     365                alm->time.tm_hour =
     366                        s35390a_reg2hr(s35390a,
     367                                       buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
     368
     369        if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
     370                alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
     371
     372        /* alarm triggers always at s=0 */
     373        alm->time.tm_sec = 0;
    289374
    290375        dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
     
    328413                         const struct i2c_device_id *id)
    329414{
    330         int err;
     415        int err, err_reset;
    331416        unsigned int i;
    332417        struct s35390a *s35390a;
    333418        struct rtc_time tm;
    334         char buf[1];
     419        char buf, status1;
    335420
    336421        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
     
    361446        }
    362447
    363         err = s35390a_reset(s35390a);
    364         if (err < 0) {
     448        err_reset = s35390a_reset(s35390a, &status1);
     449        if (err_reset < 0) {
     450                err = err_reset;
    365451                dev_err(&client->dev, "error resetting chip\n");
    366452                goto exit_dummy;
    367453        }
    368454
    369         err = s35390a_disable_test_mode(s35390a);
    370         if (err < 0) {
    371                 dev_err(&client->dev, "error disabling test mode\n");
    372                 goto exit_dummy;
    373         }
    374 
    375         err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
    376         if (err < 0) {
    377                 dev_err(&client->dev, "error checking 12/24 hour mode\n");
    378                 goto exit_dummy;
    379         }
    380         if (buf[0] & S35390A_FLAG_24H)
     455        if (status1 & S35390A_FLAG_24H)
    381456                s35390a->twentyfourhour = 1;
    382457        else
    383458                s35390a->twentyfourhour = 0;
    384459
    385         if (s35390a_get_datetime(client, &tm) < 0)
     460        if (status1 & S35390A_FLAG_INT2) {
     461                /* disable alarm (and maybe test mode) */
     462                buf = 0;
     463                err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
     464                if (err < 0) {
     465                        dev_err(&client->dev, "error disabling alarm");
     466                        goto exit_dummy;
     467                }
     468        } else {
     469                err = s35390a_disable_test_mode(s35390a);
     470                if (err < 0) {
     471                        dev_err(&client->dev, "error disabling test mode\n");
     472                        goto exit_dummy;
     473                }
     474        }
     475
     476        if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
    386477                dev_warn(&client->dev, "clock needs to be set\n");
    387478
     
    396487                goto exit_dummy;
    397488        }
     489
     490        if (status1 & S35390A_FLAG_INT2)
     491                rtc_update_irq(s35390a->rtc, 1, RTC_AF);
     492
    398493        return 0;
    399494
Note: See TracChangeset for help on using the changeset viewer.