root/drivers/w1/slaves/w1_ds250x.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. w1_ds2502_read_page
  2. w1_ds2505_read_page
  3. w1_nvmem_read
  4. w1_eprom_add_slave
  5. w1_ds250x_init
  6. w1_ds250x_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * w1_ds250x.c - w1 family 09/0b/89/91 (DS250x) driver
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/module.h>
   8 #include <linux/moduleparam.h>
   9 #include <linux/device.h>
  10 #include <linux/types.h>
  11 #include <linux/delay.h>
  12 #include <linux/slab.h>
  13 #include <linux/crc16.h>
  14 
  15 #include <linux/w1.h>
  16 #include <linux/nvmem-provider.h>
  17 
  18 #define W1_DS2501_UNW_FAMILY    0x91
  19 #define W1_DS2501_SIZE          64
  20 
  21 #define W1_DS2502_FAMILY        0x09
  22 #define W1_DS2502_UNW_FAMILY    0x89
  23 #define W1_DS2502_SIZE          128
  24 
  25 #define W1_DS2505_FAMILY        0x0b
  26 #define W1_DS2505_SIZE          2048
  27 
  28 #define W1_PAGE_SIZE            32
  29 
  30 #define W1_EXT_READ_MEMORY      0xA5
  31 #define W1_READ_DATA_CRC        0xC3
  32 
  33 #define OFF2PG(off)     ((off) / W1_PAGE_SIZE)
  34 
  35 #define CRC16_INIT              0
  36 #define CRC16_VALID             0xb001
  37 
  38 struct w1_eprom_data {
  39         size_t size;
  40         int (*read)(struct w1_slave *sl, int pageno);
  41         u8 eprom[W1_DS2505_SIZE];
  42         DECLARE_BITMAP(page_present, W1_DS2505_SIZE / W1_PAGE_SIZE);
  43         char nvmem_name[64];
  44 };
  45 
  46 static int w1_ds2502_read_page(struct w1_slave *sl, int pageno)
  47 {
  48         struct w1_eprom_data *data = sl->family_data;
  49         int pgoff = pageno * W1_PAGE_SIZE;
  50         int ret = -EIO;
  51         u8 buf[3];
  52         u8 crc8;
  53 
  54         if (test_bit(pageno, data->page_present))
  55                 return 0; /* page already present */
  56 
  57         mutex_lock(&sl->master->bus_mutex);
  58 
  59         if (w1_reset_select_slave(sl))
  60                 goto err;
  61 
  62         buf[0] = W1_READ_DATA_CRC;
  63         buf[1] = pgoff & 0xff;
  64         buf[2] = pgoff >> 8;
  65         w1_write_block(sl->master, buf, 3);
  66 
  67         crc8 = w1_read_8(sl->master);
  68         if (w1_calc_crc8(buf, 3) != crc8)
  69                 goto err;
  70 
  71         w1_read_block(sl->master, &data->eprom[pgoff], W1_PAGE_SIZE);
  72 
  73         crc8 = w1_read_8(sl->master);
  74         if (w1_calc_crc8(&data->eprom[pgoff], W1_PAGE_SIZE) != crc8)
  75                 goto err;
  76 
  77         set_bit(pageno, data->page_present); /* mark page present */
  78         ret = 0;
  79 err:
  80         mutex_unlock(&sl->master->bus_mutex);
  81         return ret;
  82 }
  83 
  84 static int w1_ds2505_read_page(struct w1_slave *sl, int pageno)
  85 {
  86         struct w1_eprom_data *data = sl->family_data;
  87         int redir_retries = 16;
  88         int pgoff, epoff;
  89         int ret = -EIO;
  90         u8 buf[6];
  91         u8 redir;
  92         u16 crc;
  93 
  94         if (test_bit(pageno, data->page_present))
  95                 return 0; /* page already present */
  96 
  97         epoff = pgoff = pageno * W1_PAGE_SIZE;
  98         mutex_lock(&sl->master->bus_mutex);
  99 
 100 retry:
 101         if (w1_reset_select_slave(sl))
 102                 goto err;
 103 
 104         buf[0] = W1_EXT_READ_MEMORY;
 105         buf[1] = pgoff & 0xff;
 106         buf[2] = pgoff >> 8;
 107         w1_write_block(sl->master, buf, 3);
 108         w1_read_block(sl->master, buf + 3, 3); /* redir, crc16 */
 109         redir = buf[3];
 110         crc = crc16(CRC16_INIT, buf, 6);
 111 
 112         if (crc != CRC16_VALID)
 113                 goto err;
 114 
 115 
 116         if (redir != 0xff) {
 117                 redir_retries--;
 118                 if (redir_retries < 0)
 119                         goto err;
 120 
 121                 pgoff = (redir ^ 0xff) * W1_PAGE_SIZE;
 122                 goto retry;
 123         }
 124 
 125         w1_read_block(sl->master, &data->eprom[epoff], W1_PAGE_SIZE);
 126         w1_read_block(sl->master, buf, 2); /* crc16 */
 127         crc = crc16(CRC16_INIT, &data->eprom[epoff], W1_PAGE_SIZE);
 128         crc = crc16(crc, buf, 2);
 129 
 130         if (crc != CRC16_VALID)
 131                 goto err;
 132 
 133         set_bit(pageno, data->page_present);
 134         ret = 0;
 135 err:
 136         mutex_unlock(&sl->master->bus_mutex);
 137         return ret;
 138 }
 139 
 140 static int w1_nvmem_read(void *priv, unsigned int off, void *buf, size_t count)
 141 {
 142         struct w1_slave *sl = priv;
 143         struct w1_eprom_data *data = sl->family_data;
 144         size_t eprom_size = data->size;
 145         int ret;
 146         int i;
 147 
 148         if (off > eprom_size)
 149                 return -EINVAL;
 150 
 151         if ((off + count) > eprom_size)
 152                 count = eprom_size - off;
 153 
 154         i = OFF2PG(off);
 155         do {
 156                 ret = data->read(sl, i++);
 157                 if (ret < 0)
 158                         return ret;
 159         } while (i < OFF2PG(off + count));
 160 
 161         memcpy(buf, &data->eprom[off], count);
 162         return 0;
 163 }
 164 
 165 static int w1_eprom_add_slave(struct w1_slave *sl)
 166 {
 167         struct w1_eprom_data *data;
 168         struct nvmem_device *nvmem;
 169         struct nvmem_config nvmem_cfg = {
 170                 .dev = &sl->dev,
 171                 .reg_read = w1_nvmem_read,
 172                 .type = NVMEM_TYPE_OTP,
 173                 .read_only = true,
 174                 .word_size = 1,
 175                 .priv = sl,
 176                 .id = -1
 177         };
 178 
 179         data = devm_kzalloc(&sl->dev, sizeof(struct w1_eprom_data), GFP_KERNEL);
 180         if (!data)
 181                 return -ENOMEM;
 182 
 183         sl->family_data = data;
 184         switch (sl->family->fid) {
 185         case W1_DS2501_UNW_FAMILY:
 186                 data->size = W1_DS2501_SIZE;
 187                 data->read = w1_ds2502_read_page;
 188                 break;
 189         case W1_DS2502_FAMILY:
 190         case W1_DS2502_UNW_FAMILY:
 191                 data->size = W1_DS2502_SIZE;
 192                 data->read = w1_ds2502_read_page;
 193                 break;
 194         case W1_DS2505_FAMILY:
 195                 data->size = W1_DS2505_SIZE;
 196                 data->read = w1_ds2505_read_page;
 197                 break;
 198         }
 199 
 200         if (sl->master->bus_master->dev_id)
 201                 snprintf(data->nvmem_name, sizeof(data->nvmem_name),
 202                          "%s-%02x-%012llx",
 203                          sl->master->bus_master->dev_id, sl->reg_num.family,
 204                          (unsigned long long)sl->reg_num.id);
 205         else
 206                 snprintf(data->nvmem_name, sizeof(data->nvmem_name),
 207                          "%02x-%012llx",
 208                          sl->reg_num.family,
 209                          (unsigned long long)sl->reg_num.id);
 210 
 211         nvmem_cfg.name = data->nvmem_name;
 212         nvmem_cfg.size = data->size;
 213 
 214         nvmem = devm_nvmem_register(&sl->dev, &nvmem_cfg);
 215         return PTR_ERR_OR_ZERO(nvmem);
 216 }
 217 
 218 static struct w1_family_ops w1_eprom_fops = {
 219         .add_slave      = w1_eprom_add_slave,
 220 };
 221 
 222 static struct w1_family w1_family_09 = {
 223         .fid = W1_DS2502_FAMILY,
 224         .fops = &w1_eprom_fops,
 225 };
 226 
 227 static struct w1_family w1_family_0b = {
 228         .fid = W1_DS2505_FAMILY,
 229         .fops = &w1_eprom_fops,
 230 };
 231 
 232 static struct w1_family w1_family_89 = {
 233         .fid = W1_DS2502_UNW_FAMILY,
 234         .fops = &w1_eprom_fops,
 235 };
 236 
 237 static struct w1_family w1_family_91 = {
 238         .fid = W1_DS2501_UNW_FAMILY,
 239         .fops = &w1_eprom_fops,
 240 };
 241 
 242 static int __init w1_ds250x_init(void)
 243 {
 244         int err;
 245 
 246         err = w1_register_family(&w1_family_09);
 247         if (err)
 248                 return err;
 249 
 250         err = w1_register_family(&w1_family_0b);
 251         if (err)
 252                 goto err_0b;
 253 
 254         err = w1_register_family(&w1_family_89);
 255         if (err)
 256                 goto err_89;
 257 
 258         err = w1_register_family(&w1_family_91);
 259         if (err)
 260                 goto err_91;
 261 
 262         return 0;
 263 
 264 err_91:
 265         w1_unregister_family(&w1_family_89);
 266 err_89:
 267         w1_unregister_family(&w1_family_0b);
 268 err_0b:
 269         w1_unregister_family(&w1_family_09);
 270         return err;
 271 }
 272 
 273 static void __exit w1_ds250x_exit(void)
 274 {
 275         w1_unregister_family(&w1_family_09);
 276         w1_unregister_family(&w1_family_0b);
 277         w1_unregister_family(&w1_family_89);
 278         w1_unregister_family(&w1_family_91);
 279 }
 280 
 281 module_init(w1_ds250x_init);
 282 module_exit(w1_ds250x_exit);
 283 
 284 MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfe@suse.de>");
 285 MODULE_DESCRIPTION("w1 family driver for DS250x Add Only Memory");
 286 MODULE_LICENSE("GPL");
 287 MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_FAMILY));
 288 MODULE_ALIAS("w1-family-" __stringify(W1_DS2505_FAMILY));
 289 MODULE_ALIAS("w1-family-" __stringify(W1_DS2501_UNW_FAMILY));
 290 MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_UNW_FAMILY));

/* [<][>][^][v][top][bottom][index][help] */