0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/device.h>
0012 #include <linux/types.h>
0013 #include <linux/delay.h>
0014
0015 #include <linux/w1.h>
0016
0017 #define W1_EEPROM_DS2805 0x0D
0018
0019 #define W1_F0D_EEPROM_SIZE 128
0020 #define W1_F0D_PAGE_BITS 3
0021 #define W1_F0D_PAGE_SIZE (1<<W1_F0D_PAGE_BITS)
0022 #define W1_F0D_PAGE_MASK 0x0F
0023
0024 #define W1_F0D_SCRATCH_BITS 1
0025 #define W1_F0D_SCRATCH_SIZE (1<<W1_F0D_SCRATCH_BITS)
0026 #define W1_F0D_SCRATCH_MASK (W1_F0D_SCRATCH_SIZE-1)
0027
0028 #define W1_F0D_READ_EEPROM 0xF0
0029 #define W1_F0D_WRITE_EEPROM 0x55
0030 #define W1_F0D_RELEASE 0xFF
0031
0032 #define W1_F0D_CS_OK 0xAA
0033
0034 #define W1_F0D_TPROG_MS 16
0035
0036 #define W1_F0D_READ_RETRIES 10
0037 #define W1_F0D_READ_MAXLEN W1_F0D_EEPROM_SIZE
0038
0039
0040
0041
0042
0043 static inline size_t w1_f0d_fix_count(loff_t off, size_t count, size_t size)
0044 {
0045 if (off > size)
0046 return 0;
0047
0048 if ((off + count) > size)
0049 return size - off;
0050
0051 return count;
0052 }
0053
0054
0055
0056
0057
0058
0059
0060
0061 static int w1_f0d_readblock(struct w1_slave *sl, int off, int count, char *buf)
0062 {
0063 u8 wrbuf[3];
0064 u8 cmp[W1_F0D_READ_MAXLEN];
0065 int tries = W1_F0D_READ_RETRIES;
0066
0067 do {
0068 wrbuf[0] = W1_F0D_READ_EEPROM;
0069 wrbuf[1] = off & 0x7f;
0070 wrbuf[2] = 0;
0071
0072 if (w1_reset_select_slave(sl))
0073 return -1;
0074
0075 w1_write_block(sl->master, wrbuf, sizeof(wrbuf));
0076 w1_read_block(sl->master, buf, count);
0077
0078 if (w1_reset_select_slave(sl))
0079 return -1;
0080
0081 w1_write_block(sl->master, wrbuf, sizeof(wrbuf));
0082 w1_read_block(sl->master, cmp, count);
0083
0084 if (!memcmp(cmp, buf, count))
0085 return 0;
0086 } while (--tries);
0087
0088 dev_err(&sl->dev, "proof reading failed %d times\n",
0089 W1_F0D_READ_RETRIES);
0090
0091 return -1;
0092 }
0093
0094 static ssize_t w1_f0d_read_bin(struct file *filp, struct kobject *kobj,
0095 struct bin_attribute *bin_attr,
0096 char *buf, loff_t off, size_t count)
0097 {
0098 struct w1_slave *sl = kobj_to_w1_slave(kobj);
0099 int todo = count;
0100
0101 count = w1_f0d_fix_count(off, count, W1_F0D_EEPROM_SIZE);
0102 if (count == 0)
0103 return 0;
0104
0105 mutex_lock(&sl->master->mutex);
0106
0107
0108 while (todo > 0) {
0109 int block_read;
0110
0111 if (todo >= W1_F0D_READ_MAXLEN)
0112 block_read = W1_F0D_READ_MAXLEN;
0113 else
0114 block_read = todo;
0115
0116 if (w1_f0d_readblock(sl, off, block_read, buf) < 0) {
0117 count = -EIO;
0118 break;
0119 }
0120
0121 todo -= W1_F0D_READ_MAXLEN;
0122 buf += W1_F0D_READ_MAXLEN;
0123 off += W1_F0D_READ_MAXLEN;
0124 }
0125
0126 mutex_unlock(&sl->master->mutex);
0127
0128 return count;
0129 }
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 static int w1_f0d_write(struct w1_slave *sl, int addr, int len, const u8 *data)
0145 {
0146 int tries = W1_F0D_READ_RETRIES;
0147 u8 wrbuf[3];
0148 u8 rdbuf[W1_F0D_SCRATCH_SIZE];
0149 u8 cs;
0150
0151 if ((addr & 1) || (len != 2)) {
0152 dev_err(&sl->dev, "%s: bad addr/len - addr=%#x len=%d\n",
0153 __func__, addr, len);
0154 return -1;
0155 }
0156
0157 retry:
0158
0159
0160 if (w1_reset_select_slave(sl))
0161 return -1;
0162
0163 wrbuf[0] = W1_F0D_WRITE_EEPROM;
0164 wrbuf[1] = addr & 0xff;
0165 wrbuf[2] = 0xff;
0166
0167 w1_write_block(sl->master, wrbuf, sizeof(wrbuf));
0168 w1_write_block(sl->master, data, len);
0169
0170 w1_read_block(sl->master, rdbuf, sizeof(rdbuf));
0171
0172 if ((rdbuf[0] != data[0]) || (rdbuf[1] != data[1])) {
0173
0174 if (--tries)
0175 goto retry;
0176
0177 dev_err(&sl->dev,
0178 "could not write to eeprom, scratchpad compare failed %d times\n",
0179 W1_F0D_READ_RETRIES);
0180 pr_info("%s: rdbuf = %#x %#x data = %#x %#x\n",
0181 __func__, rdbuf[0], rdbuf[1], data[0], data[1]);
0182
0183 return -1;
0184 }
0185
0186
0187 w1_write_8(sl->master, W1_F0D_RELEASE);
0188
0189
0190 msleep(W1_F0D_TPROG_MS);
0191
0192
0193 cs = w1_read_8(sl->master);
0194 if (cs != W1_F0D_CS_OK) {
0195 dev_err(&sl->dev, "save to eeprom failed = CS=%#x\n", cs);
0196 return -1;
0197 }
0198
0199 return 0;
0200 }
0201
0202 static ssize_t w1_f0d_write_bin(struct file *filp, struct kobject *kobj,
0203 struct bin_attribute *bin_attr,
0204 char *buf, loff_t off, size_t count)
0205 {
0206 struct w1_slave *sl = kobj_to_w1_slave(kobj);
0207 int addr, len;
0208 int copy;
0209
0210 count = w1_f0d_fix_count(off, count, W1_F0D_EEPROM_SIZE);
0211 if (count == 0)
0212 return 0;
0213
0214 mutex_lock(&sl->master->mutex);
0215
0216
0217 addr = off;
0218 len = count;
0219 while (len > 0) {
0220
0221
0222 if (len < W1_F0D_SCRATCH_SIZE || addr & W1_F0D_SCRATCH_MASK) {
0223 char tmp[W1_F0D_SCRATCH_SIZE];
0224
0225
0226 if (w1_f0d_readblock(sl, addr & ~W1_F0D_SCRATCH_MASK,
0227 W1_F0D_SCRATCH_SIZE, tmp)) {
0228 count = -EIO;
0229 goto out_up;
0230 }
0231
0232
0233 copy = W1_F0D_SCRATCH_SIZE -
0234 (addr & W1_F0D_SCRATCH_MASK);
0235
0236 if (copy > len)
0237 copy = len;
0238
0239 memcpy(&tmp[addr & W1_F0D_SCRATCH_MASK], buf, copy);
0240 if (w1_f0d_write(sl, addr & ~W1_F0D_SCRATCH_MASK,
0241 W1_F0D_SCRATCH_SIZE, tmp) < 0) {
0242 count = -EIO;
0243 goto out_up;
0244 }
0245 } else {
0246
0247 copy = W1_F0D_SCRATCH_SIZE;
0248 if (w1_f0d_write(sl, addr, copy, buf) < 0) {
0249 count = -EIO;
0250 goto out_up;
0251 }
0252 }
0253 buf += copy;
0254 addr += copy;
0255 len -= copy;
0256 }
0257
0258 out_up:
0259 mutex_unlock(&sl->master->mutex);
0260
0261 return count;
0262 }
0263
0264 static struct bin_attribute w1_f0d_bin_attr = {
0265 .attr = {
0266 .name = "eeprom",
0267 .mode = S_IRUGO | S_IWUSR,
0268 },
0269 .size = W1_F0D_EEPROM_SIZE,
0270 .read = w1_f0d_read_bin,
0271 .write = w1_f0d_write_bin,
0272 };
0273
0274 static int w1_f0d_add_slave(struct w1_slave *sl)
0275 {
0276 return sysfs_create_bin_file(&sl->dev.kobj, &w1_f0d_bin_attr);
0277 }
0278
0279 static void w1_f0d_remove_slave(struct w1_slave *sl)
0280 {
0281 sysfs_remove_bin_file(&sl->dev.kobj, &w1_f0d_bin_attr);
0282 }
0283
0284 static const struct w1_family_ops w1_f0d_fops = {
0285 .add_slave = w1_f0d_add_slave,
0286 .remove_slave = w1_f0d_remove_slave,
0287 };
0288
0289 static struct w1_family w1_family_0d = {
0290 .fid = W1_EEPROM_DS2805,
0291 .fops = &w1_f0d_fops,
0292 };
0293
0294 module_w1_family(w1_family_0d);
0295
0296 MODULE_LICENSE("GPL");
0297 MODULE_AUTHOR("Andrew Worsley amworsley@gmail.com");
0298 MODULE_DESCRIPTION("w1 family 0d driver for DS2805, 1kb EEPROM");