Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * w1_ds2430.c - w1 family 14 (DS2430) driver
0004  **
0005  * Copyright (c) 2019 Angelo Dureghello <angelo.dureghello@timesys.com>
0006  *
0007  * Cloned and modified from ds2431
0008  * Copyright (c) 2008 Bernhard Weirich <bernhard.weirich@riedel.net>
0009  *
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/moduleparam.h>
0015 #include <linux/device.h>
0016 #include <linux/types.h>
0017 #include <linux/delay.h>
0018 
0019 #include <linux/w1.h>
0020 
0021 #define W1_EEPROM_DS2430    0x14
0022 
0023 #define W1_F14_EEPROM_SIZE  32
0024 #define W1_F14_PAGE_COUNT   1
0025 #define W1_F14_PAGE_BITS    5
0026 #define W1_F14_PAGE_SIZE    (1 << W1_F14_PAGE_BITS)
0027 #define W1_F14_PAGE_MASK    0x1F
0028 
0029 #define W1_F14_SCRATCH_BITS 5
0030 #define W1_F14_SCRATCH_SIZE (1 << W1_F14_SCRATCH_BITS)
0031 #define W1_F14_SCRATCH_MASK (W1_F14_SCRATCH_SIZE-1)
0032 
0033 #define W1_F14_READ_EEPROM  0xF0
0034 #define W1_F14_WRITE_SCRATCH    0x0F
0035 #define W1_F14_READ_SCRATCH 0xAA
0036 #define W1_F14_COPY_SCRATCH 0x55
0037 #define W1_F14_VALIDATION_KEY   0xa5
0038 
0039 #define W1_F14_TPROG_MS     11
0040 #define W1_F14_READ_RETRIES 10
0041 #define W1_F14_READ_MAXLEN  W1_F14_SCRATCH_SIZE
0042 
0043 /*
0044  * Check the file size bounds and adjusts count as needed.
0045  * This would not be needed if the file size didn't reset to 0 after a write.
0046  */
0047 static inline size_t w1_f14_fix_count(loff_t off, size_t count, size_t size)
0048 {
0049     if (off > size)
0050         return 0;
0051 
0052     if ((off + count) > size)
0053         return size - off;
0054 
0055     return count;
0056 }
0057 
0058 /*
0059  * Read a block from W1 ROM two times and compares the results.
0060  * If they are equal they are returned, otherwise the read
0061  * is repeated W1_F14_READ_RETRIES times.
0062  *
0063  * count must not exceed W1_F14_READ_MAXLEN.
0064  */
0065 static int w1_f14_readblock(struct w1_slave *sl, int off, int count, char *buf)
0066 {
0067     u8 wrbuf[2];
0068     u8 cmp[W1_F14_READ_MAXLEN];
0069     int tries = W1_F14_READ_RETRIES;
0070 
0071     do {
0072         wrbuf[0] = W1_F14_READ_EEPROM;
0073         wrbuf[1] = off & 0xff;
0074 
0075         if (w1_reset_select_slave(sl))
0076             return -1;
0077 
0078         w1_write_block(sl->master, wrbuf, 2);
0079         w1_read_block(sl->master, buf, count);
0080 
0081         if (w1_reset_select_slave(sl))
0082             return -1;
0083 
0084         w1_write_block(sl->master, wrbuf, 2);
0085         w1_read_block(sl->master, cmp, count);
0086 
0087         if (!memcmp(cmp, buf, count))
0088             return 0;
0089     } while (--tries);
0090 
0091     dev_err(&sl->dev, "proof reading failed %d times\n",
0092             W1_F14_READ_RETRIES);
0093 
0094     return -1;
0095 }
0096 
0097 static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
0098                struct bin_attribute *bin_attr, char *buf,
0099                loff_t off, size_t count)
0100 {
0101     struct w1_slave *sl = kobj_to_w1_slave(kobj);
0102     int todo = count;
0103 
0104     count = w1_f14_fix_count(off, count, W1_F14_EEPROM_SIZE);
0105     if (count == 0)
0106         return 0;
0107 
0108     mutex_lock(&sl->master->bus_mutex);
0109 
0110     /* read directly from the EEPROM in chunks of W1_F14_READ_MAXLEN */
0111     while (todo > 0) {
0112         int block_read;
0113 
0114         if (todo >= W1_F14_READ_MAXLEN)
0115             block_read = W1_F14_READ_MAXLEN;
0116         else
0117             block_read = todo;
0118 
0119         if (w1_f14_readblock(sl, off, block_read, buf) < 0)
0120             count = -EIO;
0121 
0122         todo -= W1_F14_READ_MAXLEN;
0123         buf += W1_F14_READ_MAXLEN;
0124         off += W1_F14_READ_MAXLEN;
0125     }
0126 
0127     mutex_unlock(&sl->master->bus_mutex);
0128 
0129     return count;
0130 }
0131 
0132 /*
0133  * Writes to the scratchpad and reads it back for verification.
0134  * Then copies the scratchpad to EEPROM.
0135  * The data must be aligned at W1_F14_SCRATCH_SIZE bytes and
0136  * must be W1_F14_SCRATCH_SIZE bytes long.
0137  * The master must be locked.
0138  *
0139  * @param sl    The slave structure
0140  * @param addr  Address for the write
0141  * @param len   length must be <= (W1_F14_PAGE_SIZE - (addr & W1_F14_PAGE_MASK))
0142  * @param data  The data to write
0143  * @return  0=Success -1=failure
0144  */
0145 static int w1_f14_write(struct w1_slave *sl, int addr, int len, const u8 *data)
0146 {
0147     int tries = W1_F14_READ_RETRIES;
0148     u8 wrbuf[2];
0149     u8 rdbuf[W1_F14_SCRATCH_SIZE + 3];
0150 
0151 retry:
0152 
0153     /* Write the data to the scratchpad */
0154     if (w1_reset_select_slave(sl))
0155         return -1;
0156 
0157     wrbuf[0] = W1_F14_WRITE_SCRATCH;
0158     wrbuf[1] = addr & 0xff;
0159 
0160     w1_write_block(sl->master, wrbuf, 2);
0161     w1_write_block(sl->master, data, len);
0162 
0163     /* Read the scratchpad and verify */
0164     if (w1_reset_select_slave(sl))
0165         return -1;
0166 
0167     w1_write_8(sl->master, W1_F14_READ_SCRATCH);
0168     w1_read_block(sl->master, rdbuf, len + 2);
0169 
0170     /*
0171      * Compare what was read against the data written
0172      * Note: on read scratchpad, device returns 2 bulk 0xff bytes,
0173      * to be discarded.
0174      */
0175     if ((memcmp(data, &rdbuf[2], len) != 0)) {
0176 
0177         if (--tries)
0178             goto retry;
0179 
0180         dev_err(&sl->dev,
0181             "could not write to eeprom, scratchpad compare failed %d times\n",
0182             W1_F14_READ_RETRIES);
0183 
0184         return -1;
0185     }
0186 
0187     /* Copy the scratchpad to EEPROM */
0188     if (w1_reset_select_slave(sl))
0189         return -1;
0190 
0191     wrbuf[0] = W1_F14_COPY_SCRATCH;
0192     wrbuf[1] = W1_F14_VALIDATION_KEY;
0193     w1_write_block(sl->master, wrbuf, 2);
0194 
0195     /* Sleep for tprog ms to wait for the write to complete */
0196     msleep(W1_F14_TPROG_MS);
0197 
0198     /* Reset the bus to wake up the EEPROM  */
0199     w1_reset_bus(sl->master);
0200 
0201     return 0;
0202 }
0203 
0204 static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
0205                 struct bin_attribute *bin_attr, char *buf,
0206                 loff_t off, size_t count)
0207 {
0208     struct w1_slave *sl = kobj_to_w1_slave(kobj);
0209     int addr, len;
0210     int copy;
0211 
0212     count = w1_f14_fix_count(off, count, W1_F14_EEPROM_SIZE);
0213     if (count == 0)
0214         return 0;
0215 
0216     mutex_lock(&sl->master->bus_mutex);
0217 
0218     /* Can only write data in blocks of the size of the scratchpad */
0219     addr = off;
0220     len = count;
0221     while (len > 0) {
0222 
0223         /* if len too short or addr not aligned */
0224         if (len < W1_F14_SCRATCH_SIZE || addr & W1_F14_SCRATCH_MASK) {
0225             char tmp[W1_F14_SCRATCH_SIZE];
0226 
0227             /* read the block and update the parts to be written */
0228             if (w1_f14_readblock(sl, addr & ~W1_F14_SCRATCH_MASK,
0229                     W1_F14_SCRATCH_SIZE, tmp)) {
0230                 count = -EIO;
0231                 goto out_up;
0232             }
0233 
0234             /* copy at most to the boundary of the PAGE or len */
0235             copy = W1_F14_SCRATCH_SIZE -
0236                 (addr & W1_F14_SCRATCH_MASK);
0237 
0238             if (copy > len)
0239                 copy = len;
0240 
0241             memcpy(&tmp[addr & W1_F14_SCRATCH_MASK], buf, copy);
0242             if (w1_f14_write(sl, addr & ~W1_F14_SCRATCH_MASK,
0243                     W1_F14_SCRATCH_SIZE, tmp) < 0) {
0244                 count = -EIO;
0245                 goto out_up;
0246             }
0247         } else {
0248 
0249             copy = W1_F14_SCRATCH_SIZE;
0250             if (w1_f14_write(sl, addr, copy, buf) < 0) {
0251                 count = -EIO;
0252                 goto out_up;
0253             }
0254         }
0255         buf += copy;
0256         addr += copy;
0257         len -= copy;
0258     }
0259 
0260 out_up:
0261     mutex_unlock(&sl->master->bus_mutex);
0262 
0263     return count;
0264 }
0265 
0266 static BIN_ATTR_RW(eeprom, W1_F14_EEPROM_SIZE);
0267 
0268 static struct bin_attribute *w1_f14_bin_attrs[] = {
0269     &bin_attr_eeprom,
0270     NULL,
0271 };
0272 
0273 static const struct attribute_group w1_f14_group = {
0274     .bin_attrs = w1_f14_bin_attrs,
0275 };
0276 
0277 static const struct attribute_group *w1_f14_groups[] = {
0278     &w1_f14_group,
0279     NULL,
0280 };
0281 
0282 static const struct w1_family_ops w1_f14_fops = {
0283     .groups = w1_f14_groups,
0284 };
0285 
0286 static struct w1_family w1_family_14 = {
0287     .fid = W1_EEPROM_DS2430,
0288     .fops = &w1_f14_fops,
0289 };
0290 module_w1_family(w1_family_14);
0291 
0292 MODULE_AUTHOR("Angelo Dureghello <angelo.dureghello@timesys.com>");
0293 MODULE_DESCRIPTION("w1 family 14 driver for DS2430, 256b EEPROM");
0294 MODULE_LICENSE("GPL");
0295 MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS2430));