linux/drivers/misc/c2port/core.c
<<
>>
Prefs
   1/*
   2 *  Silicon Labs C2 port core Linux support
   3 *
   4 *  Copyright (c) 2007 Rodolfo Giometti <giometti@linux.it>
   5 *  Copyright (c) 2007 Eurotech S.p.A. <info@eurotech.it>
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License version 2 as published by
   9 * the Free Software Foundation
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/init.h>
  14#include <linux/device.h>
  15#include <linux/errno.h>
  16#include <linux/err.h>
  17#include <linux/kernel.h>
  18#include <linux/kmemcheck.h>
  19#include <linux/ctype.h>
  20#include <linux/delay.h>
  21#include <linux/idr.h>
  22#include <linux/sched.h>
  23
  24#include <linux/c2port.h>
  25
  26#define DRIVER_NAME             "c2port"
  27#define DRIVER_VERSION          "0.51.0"
  28
  29static DEFINE_SPINLOCK(c2port_idr_lock);
  30static DEFINE_IDR(c2port_idr);
  31
  32/*
  33 * Local variables
  34 */
  35
  36static struct class *c2port_class;
  37
  38/*
  39 * C2 registers & commands defines
  40 */
  41
  42/* C2 registers */
  43#define C2PORT_DEVICEID         0x00
  44#define C2PORT_REVID            0x01
  45#define C2PORT_FPCTL            0x02
  46#define C2PORT_FPDAT            0xB4
  47
  48/* C2 interface commands */
  49#define C2PORT_GET_VERSION      0x01
  50#define C2PORT_DEVICE_ERASE     0x03
  51#define C2PORT_BLOCK_READ       0x06
  52#define C2PORT_BLOCK_WRITE      0x07
  53#define C2PORT_PAGE_ERASE       0x08
  54
  55/* C2 status return codes */
  56#define C2PORT_INVALID_COMMAND  0x00
  57#define C2PORT_COMMAND_FAILED   0x02
  58#define C2PORT_COMMAND_OK       0x0d
  59
  60/*
  61 * C2 port low level signal managements
  62 */
  63
  64static void c2port_reset(struct c2port_device *dev)
  65{
  66        struct c2port_ops *ops = dev->ops;
  67
  68        /* To reset the device we have to keep clock line low for at least
  69         * 20us.
  70         */
  71        local_irq_disable();
  72        ops->c2ck_set(dev, 0);
  73        udelay(25);
  74        ops->c2ck_set(dev, 1);
  75        local_irq_enable();
  76
  77        udelay(1);
  78}
  79
  80static void c2port_strobe_ck(struct c2port_device *dev)
  81{
  82        struct c2port_ops *ops = dev->ops;
  83
  84        /* During hi-low-hi transition we disable local IRQs to avoid
  85         * interructions since C2 port specification says that it must be
  86         * shorter than 5us, otherwise the microcontroller may consider
  87         * it as a reset signal!
  88         */
  89        local_irq_disable();
  90        ops->c2ck_set(dev, 0);
  91        udelay(1);
  92        ops->c2ck_set(dev, 1);
  93        local_irq_enable();
  94
  95        udelay(1);
  96}
  97
  98/*
  99 * C2 port basic functions
 100 */
 101
 102static void c2port_write_ar(struct c2port_device *dev, u8 addr)
 103{
 104        struct c2port_ops *ops = dev->ops;
 105        int i;
 106
 107        /* START field */
 108        c2port_strobe_ck(dev);
 109
 110        /* INS field (11b, LSB first) */
 111        ops->c2d_dir(dev, 0);
 112        ops->c2d_set(dev, 1);
 113        c2port_strobe_ck(dev);
 114        ops->c2d_set(dev, 1);
 115        c2port_strobe_ck(dev);
 116
 117        /* ADDRESS field */
 118        for (i = 0; i < 8; i++) {
 119                ops->c2d_set(dev, addr & 0x01);
 120                c2port_strobe_ck(dev);
 121
 122                addr >>= 1;
 123        }
 124
 125        /* STOP field */
 126        ops->c2d_dir(dev, 1);
 127        c2port_strobe_ck(dev);
 128}
 129
 130static int c2port_read_ar(struct c2port_device *dev, u8 *addr)
 131{
 132        struct c2port_ops *ops = dev->ops;
 133        int i;
 134
 135        /* START field */
 136        c2port_strobe_ck(dev);
 137
 138        /* INS field (10b, LSB first) */
 139        ops->c2d_dir(dev, 0);
 140        ops->c2d_set(dev, 0);
 141        c2port_strobe_ck(dev);
 142        ops->c2d_set(dev, 1);
 143        c2port_strobe_ck(dev);
 144
 145        /* ADDRESS field */
 146        ops->c2d_dir(dev, 1);
 147        *addr = 0;
 148        for (i = 0; i < 8; i++) {
 149                *addr >>= 1;    /* shift in 8-bit ADDRESS field LSB first */
 150
 151                c2port_strobe_ck(dev);
 152                if (ops->c2d_get(dev))
 153                        *addr |= 0x80;
 154        }
 155
 156        /* STOP field */
 157        c2port_strobe_ck(dev);
 158
 159        return 0;
 160}
 161
 162static int c2port_write_dr(struct c2port_device *dev, u8 data)
 163{
 164        struct c2port_ops *ops = dev->ops;
 165        int timeout, i;
 166
 167        /* START field */
 168        c2port_strobe_ck(dev);
 169
 170        /* INS field (01b, LSB first) */
 171        ops->c2d_dir(dev, 0);
 172        ops->c2d_set(dev, 1);
 173        c2port_strobe_ck(dev);
 174        ops->c2d_set(dev, 0);
 175        c2port_strobe_ck(dev);
 176
 177        /* LENGTH field (00b, LSB first -> 1 byte) */
 178        ops->c2d_set(dev, 0);
 179        c2port_strobe_ck(dev);
 180        ops->c2d_set(dev, 0);
 181        c2port_strobe_ck(dev);
 182
 183        /* DATA field */
 184        for (i = 0; i < 8; i++) {
 185                ops->c2d_set(dev, data & 0x01);
 186                c2port_strobe_ck(dev);
 187
 188                data >>= 1;
 189        }
 190
 191        /* WAIT field */
 192        ops->c2d_dir(dev, 1);
 193        timeout = 20;
 194        do {
 195                c2port_strobe_ck(dev);
 196                if (ops->c2d_get(dev))
 197                        break;
 198
 199                udelay(1);
 200        } while (--timeout > 0);
 201        if (timeout == 0)
 202                return -EIO;
 203
 204        /* STOP field */
 205        c2port_strobe_ck(dev);
 206
 207        return 0;
 208}
 209
 210static int c2port_read_dr(struct c2port_device *dev, u8 *data)
 211{
 212        struct c2port_ops *ops = dev->ops;
 213        int timeout, i;
 214
 215        /* START field */
 216        c2port_strobe_ck(dev);
 217
 218        /* INS field (00b, LSB first) */
 219        ops->c2d_dir(dev, 0);
 220        ops->c2d_set(dev, 0);
 221        c2port_strobe_ck(dev);
 222        ops->c2d_set(dev, 0);
 223        c2port_strobe_ck(dev);
 224
 225        /* LENGTH field (00b, LSB first -> 1 byte) */
 226        ops->c2d_set(dev, 0);
 227        c2port_strobe_ck(dev);
 228        ops->c2d_set(dev, 0);
 229        c2port_strobe_ck(dev);
 230
 231        /* WAIT field */
 232        ops->c2d_dir(dev, 1);
 233        timeout = 20;
 234        do {
 235                c2port_strobe_ck(dev);
 236                if (ops->c2d_get(dev))
 237                        break;
 238
 239                udelay(1);
 240        } while (--timeout > 0);
 241        if (timeout == 0)
 242                return -EIO;
 243
 244        /* DATA field */
 245        *data = 0;
 246        for (i = 0; i < 8; i++) {
 247                *data >>= 1;    /* shift in 8-bit DATA field LSB first */
 248
 249                c2port_strobe_ck(dev);
 250                if (ops->c2d_get(dev))
 251                        *data |= 0x80;
 252        }
 253
 254        /* STOP field */
 255        c2port_strobe_ck(dev);
 256
 257        return 0;
 258}
 259
 260static int c2port_poll_in_busy(struct c2port_device *dev)
 261{
 262        u8 addr;
 263        int ret, timeout = 20;
 264
 265        do {
 266                ret = (c2port_read_ar(dev, &addr));
 267                if (ret < 0)
 268                        return -EIO;
 269
 270                if (!(addr & 0x02))
 271                        break;
 272
 273                udelay(1);
 274        } while (--timeout > 0);
 275        if (timeout == 0)
 276                return -EIO;
 277
 278        return 0;
 279}
 280
 281static int c2port_poll_out_ready(struct c2port_device *dev)
 282{
 283        u8 addr;
 284        int ret, timeout = 10000; /* erase flash needs long time... */
 285
 286        do {
 287                ret = (c2port_read_ar(dev, &addr));
 288                if (ret < 0)
 289                        return -EIO;
 290
 291                if (addr & 0x01)
 292                        break;
 293
 294                udelay(1);
 295        } while (--timeout > 0);
 296        if (timeout == 0)
 297                return -EIO;
 298
 299        return 0;
 300}
 301
 302/*
 303 * sysfs methods
 304 */
 305
 306static ssize_t c2port_show_name(struct device *dev,
 307                                struct device_attribute *attr, char *buf)
 308{
 309        struct c2port_device *c2dev = dev_get_drvdata(dev);
 310
 311        return sprintf(buf, "%s\n", c2dev->name);
 312}
 313
 314static ssize_t c2port_show_flash_blocks_num(struct device *dev,
 315                                struct device_attribute *attr, char *buf)
 316{
 317        struct c2port_device *c2dev = dev_get_drvdata(dev);
 318        struct c2port_ops *ops = c2dev->ops;
 319
 320        return sprintf(buf, "%d\n", ops->blocks_num);
 321}
 322
 323static ssize_t c2port_show_flash_block_size(struct device *dev,
 324                                struct device_attribute *attr, char *buf)
 325{
 326        struct c2port_device *c2dev = dev_get_drvdata(dev);
 327        struct c2port_ops *ops = c2dev->ops;
 328
 329        return sprintf(buf, "%d\n", ops->block_size);
 330}
 331
 332static ssize_t c2port_show_flash_size(struct device *dev,
 333                                struct device_attribute *attr, char *buf)
 334{
 335        struct c2port_device *c2dev = dev_get_drvdata(dev);
 336        struct c2port_ops *ops = c2dev->ops;
 337
 338        return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size);
 339}
 340
 341static ssize_t c2port_show_access(struct device *dev,
 342                                struct device_attribute *attr, char *buf)
 343{
 344        struct c2port_device *c2dev = dev_get_drvdata(dev);
 345
 346        return sprintf(buf, "%d\n", c2dev->access);
 347}
 348
 349static ssize_t c2port_store_access(struct device *dev,
 350                                struct device_attribute *attr,
 351                                const char *buf, size_t count)
 352{
 353        struct c2port_device *c2dev = dev_get_drvdata(dev);
 354        struct c2port_ops *ops = c2dev->ops;
 355        int status, ret;
 356
 357        ret = sscanf(buf, "%d", &status);
 358        if (ret != 1)
 359                return -EINVAL;
 360
 361        mutex_lock(&c2dev->mutex);
 362
 363        c2dev->access = !!status;
 364
 365        /* If access is "on" clock should be HIGH _before_ setting the line
 366         * as output and data line should be set as INPUT anyway */
 367        if (c2dev->access)
 368                ops->c2ck_set(c2dev, 1);
 369        ops->access(c2dev, c2dev->access);
 370        if (c2dev->access)
 371                ops->c2d_dir(c2dev, 1);
 372
 373        mutex_unlock(&c2dev->mutex);
 374
 375        return count;
 376}
 377
 378static ssize_t c2port_store_reset(struct device *dev,
 379                                struct device_attribute *attr,
 380                                const char *buf, size_t count)
 381{
 382        struct c2port_device *c2dev = dev_get_drvdata(dev);
 383
 384        /* Check the device access status */
 385        if (!c2dev->access)
 386                return -EBUSY;
 387
 388        mutex_lock(&c2dev->mutex);
 389
 390        c2port_reset(c2dev);
 391        c2dev->flash_access = 0;
 392
 393        mutex_unlock(&c2dev->mutex);
 394
 395        return count;
 396}
 397
 398static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf)
 399{
 400        u8 data;
 401        int ret;
 402
 403        /* Select DEVICEID register for C2 data register accesses */
 404        c2port_write_ar(dev, C2PORT_DEVICEID);
 405
 406        /* Read and return the device ID register */
 407        ret = c2port_read_dr(dev, &data);
 408        if (ret < 0)
 409                return ret;
 410
 411        return sprintf(buf, "%d\n", data);
 412}
 413
 414static ssize_t c2port_show_dev_id(struct device *dev,
 415                                struct device_attribute *attr, char *buf)
 416{
 417        struct c2port_device *c2dev = dev_get_drvdata(dev);
 418        ssize_t ret;
 419
 420        /* Check the device access status */
 421        if (!c2dev->access)
 422                return -EBUSY;
 423
 424        mutex_lock(&c2dev->mutex);
 425        ret = __c2port_show_dev_id(c2dev, buf);
 426        mutex_unlock(&c2dev->mutex);
 427
 428        if (ret < 0)
 429                dev_err(dev, "cannot read from %s\n", c2dev->name);
 430
 431        return ret;
 432}
 433
 434static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf)
 435{
 436        u8 data;
 437        int ret;
 438
 439        /* Select REVID register for C2 data register accesses */
 440        c2port_write_ar(dev, C2PORT_REVID);
 441
 442        /* Read and return the revision ID register */
 443        ret = c2port_read_dr(dev, &data);
 444        if (ret < 0)
 445                return ret;
 446
 447        return sprintf(buf, "%d\n", data);
 448}
 449
 450static ssize_t c2port_show_rev_id(struct device *dev,
 451                                struct device_attribute *attr, char *buf)
 452{
 453        struct c2port_device *c2dev = dev_get_drvdata(dev);
 454        ssize_t ret;
 455
 456        /* Check the device access status */
 457        if (!c2dev->access)
 458                return -EBUSY;
 459
 460        mutex_lock(&c2dev->mutex);
 461        ret = __c2port_show_rev_id(c2dev, buf);
 462        mutex_unlock(&c2dev->mutex);
 463
 464        if (ret < 0)
 465                dev_err(c2dev->dev, "cannot read from %s\n", c2dev->name);
 466
 467        return ret;
 468}
 469
 470static ssize_t c2port_show_flash_access(struct device *dev,
 471                                struct device_attribute *attr, char *buf)
 472{
 473        struct c2port_device *c2dev = dev_get_drvdata(dev);
 474
 475        return sprintf(buf, "%d\n", c2dev->flash_access);
 476}
 477
 478static ssize_t __c2port_store_flash_access(struct c2port_device *dev,
 479                                                int status)
 480{
 481        int ret;
 482
 483        /* Check the device access status */
 484        if (!dev->access)
 485                return -EBUSY;
 486
 487        dev->flash_access = !!status;
 488
 489        /* If flash_access is off we have nothing to do... */
 490        if (dev->flash_access == 0)
 491                return 0;
 492
 493        /* Target the C2 flash programming control register for C2 data
 494         * register access */
 495        c2port_write_ar(dev, C2PORT_FPCTL);
 496
 497        /* Write the first keycode to enable C2 Flash programming */
 498        ret = c2port_write_dr(dev, 0x02);
 499        if (ret < 0)
 500                return ret;
 501
 502        /* Write the second keycode to enable C2 Flash programming */
 503        ret = c2port_write_dr(dev, 0x01);
 504        if (ret < 0)
 505                return ret;
 506
 507        /* Delay for at least 20ms to ensure the target is ready for
 508         * C2 flash programming */
 509        mdelay(25);
 510
 511        return 0;
 512}
 513
 514static ssize_t c2port_store_flash_access(struct device *dev,
 515                                struct device_attribute *attr,
 516                                const char *buf, size_t count)
 517{
 518        struct c2port_device *c2dev = dev_get_drvdata(dev);
 519        int status;
 520        ssize_t ret;
 521
 522        ret = sscanf(buf, "%d", &status);
 523        if (ret != 1)
 524                return -EINVAL;
 525
 526        mutex_lock(&c2dev->mutex);
 527        ret = __c2port_store_flash_access(c2dev, status);
 528        mutex_unlock(&c2dev->mutex);
 529
 530        if (ret < 0) {
 531                dev_err(c2dev->dev, "cannot enable %s flash programming\n",
 532                        c2dev->name);
 533                return ret;
 534        }
 535
 536        return count;
 537}
 538
 539static ssize_t __c2port_write_flash_erase(struct c2port_device *dev)
 540{
 541        u8 status;
 542        int ret;
 543
 544        /* Target the C2 flash programming data register for C2 data register
 545         * access.
 546         */
 547        c2port_write_ar(dev, C2PORT_FPDAT);
 548
 549        /* Send device erase command */
 550        c2port_write_dr(dev, C2PORT_DEVICE_ERASE);
 551
 552        /* Wait for input acknowledge */
 553        ret = c2port_poll_in_busy(dev);
 554        if (ret < 0)
 555                return ret;
 556
 557        /* Should check status before starting FLASH access sequence */
 558
 559        /* Wait for status information */
 560        ret = c2port_poll_out_ready(dev);
 561        if (ret < 0)
 562                return ret;
 563
 564        /* Read flash programming interface status */
 565        ret = c2port_read_dr(dev, &status);
 566        if (ret < 0)
 567                return ret;
 568        if (status != C2PORT_COMMAND_OK)
 569                return -EBUSY;
 570
 571        /* Send a three-byte arming sequence to enable the device erase.
 572         * If the sequence is not received correctly, the command will be
 573         * ignored.
 574         * Sequence is: 0xde, 0xad, 0xa5.
 575         */
 576        c2port_write_dr(dev, 0xde);
 577        ret = c2port_poll_in_busy(dev);
 578        if (ret < 0)
 579                return ret;
 580        c2port_write_dr(dev, 0xad);
 581        ret = c2port_poll_in_busy(dev);
 582        if (ret < 0)
 583                return ret;
 584        c2port_write_dr(dev, 0xa5);
 585        ret = c2port_poll_in_busy(dev);
 586        if (ret < 0)
 587                return ret;
 588
 589        ret = c2port_poll_out_ready(dev);
 590        if (ret < 0)
 591                return ret;
 592
 593        return 0;
 594}
 595
 596static ssize_t c2port_store_flash_erase(struct device *dev,
 597                                struct device_attribute *attr,
 598                                const char *buf, size_t count)
 599{
 600        struct c2port_device *c2dev = dev_get_drvdata(dev);
 601        int ret;
 602
 603        /* Check the device and flash access status */
 604        if (!c2dev->access || !c2dev->flash_access)
 605                return -EBUSY;
 606
 607        mutex_lock(&c2dev->mutex);
 608        ret = __c2port_write_flash_erase(c2dev);
 609        mutex_unlock(&c2dev->mutex);
 610
 611        if (ret < 0) {
 612                dev_err(c2dev->dev, "cannot erase %s flash\n", c2dev->name);
 613                return ret;
 614        }
 615
 616        return count;
 617}
 618
 619static ssize_t __c2port_read_flash_data(struct c2port_device *dev,
 620                                char *buffer, loff_t offset, size_t count)
 621{
 622        struct c2port_ops *ops = dev->ops;
 623        u8 status, nread = 128;
 624        int i, ret;
 625
 626        /* Check for flash end */
 627        if (offset >= ops->block_size * ops->blocks_num)
 628                return 0;
 629
 630        if (ops->block_size * ops->blocks_num - offset < nread)
 631                nread = ops->block_size * ops->blocks_num - offset;
 632        if (count < nread)
 633                nread = count;
 634        if (nread == 0)
 635                return nread;
 636
 637        /* Target the C2 flash programming data register for C2 data register
 638         * access */
 639        c2port_write_ar(dev, C2PORT_FPDAT);
 640
 641        /* Send flash block read command */
 642        c2port_write_dr(dev, C2PORT_BLOCK_READ);
 643
 644        /* Wait for input acknowledge */
 645        ret = c2port_poll_in_busy(dev);
 646        if (ret < 0)
 647                return ret;
 648
 649        /* Should check status before starting FLASH access sequence */
 650
 651        /* Wait for status information */
 652        ret = c2port_poll_out_ready(dev);
 653        if (ret < 0)
 654                return ret;
 655
 656        /* Read flash programming interface status */
 657        ret = c2port_read_dr(dev, &status);
 658        if (ret < 0)
 659                return ret;
 660        if (status != C2PORT_COMMAND_OK)
 661                return -EBUSY;
 662
 663        /* Send address high byte */
 664        c2port_write_dr(dev, offset >> 8);
 665        ret = c2port_poll_in_busy(dev);
 666        if (ret < 0)
 667                return ret;
 668
 669        /* Send address low byte */
 670        c2port_write_dr(dev, offset & 0x00ff);
 671        ret = c2port_poll_in_busy(dev);
 672        if (ret < 0)
 673                return ret;
 674
 675        /* Send address block size */
 676        c2port_write_dr(dev, nread);
 677        ret = c2port_poll_in_busy(dev);
 678        if (ret < 0)
 679                return ret;
 680
 681        /* Should check status before reading FLASH block */
 682
 683        /* Wait for status information */
 684        ret = c2port_poll_out_ready(dev);
 685        if (ret < 0)
 686                return ret;
 687
 688        /* Read flash programming interface status */
 689        ret = c2port_read_dr(dev, &status);
 690        if (ret < 0)
 691                return ret;
 692        if (status != C2PORT_COMMAND_OK)
 693                return -EBUSY;
 694
 695        /* Read flash block */
 696        for (i = 0; i < nread; i++) {
 697                ret = c2port_poll_out_ready(dev);
 698                if (ret < 0)
 699                        return ret;
 700
 701                ret = c2port_read_dr(dev, buffer+i);
 702                if (ret < 0)
 703                        return ret;
 704        }
 705
 706        return nread;
 707}
 708
 709static ssize_t c2port_read_flash_data(struct kobject *kobj,
 710                                struct bin_attribute *attr,
 711                                char *buffer, loff_t offset, size_t count)
 712{
 713        struct c2port_device *c2dev =
 714                        dev_get_drvdata(container_of(kobj,
 715                                                struct device, kobj));
 716        ssize_t ret;
 717
 718        /* Check the device and flash access status */
 719        if (!c2dev->access || !c2dev->flash_access)
 720                return -EBUSY;
 721
 722        mutex_lock(&c2dev->mutex);
 723        ret = __c2port_read_flash_data(c2dev, buffer, offset, count);
 724        mutex_unlock(&c2dev->mutex);
 725
 726        if (ret < 0)
 727                dev_err(c2dev->dev, "cannot read %s flash\n", c2dev->name);
 728
 729        return ret;
 730}
 731
 732static ssize_t __c2port_write_flash_data(struct c2port_device *dev,
 733                                char *buffer, loff_t offset, size_t count)
 734{
 735        struct c2port_ops *ops = dev->ops;
 736        u8 status, nwrite = 128;
 737        int i, ret;
 738
 739        if (nwrite > count)
 740                nwrite = count;
 741        if (ops->block_size * ops->blocks_num - offset < nwrite)
 742                nwrite = ops->block_size * ops->blocks_num - offset;
 743
 744        /* Check for flash end */
 745        if (offset >= ops->block_size * ops->blocks_num)
 746                return -EINVAL;
 747
 748        /* Target the C2 flash programming data register for C2 data register
 749         * access */
 750        c2port_write_ar(dev, C2PORT_FPDAT);
 751
 752        /* Send flash block write command */
 753        c2port_write_dr(dev, C2PORT_BLOCK_WRITE);
 754
 755        /* Wait for input acknowledge */
 756        ret = c2port_poll_in_busy(dev);
 757        if (ret < 0)
 758                return ret;
 759
 760        /* Should check status before starting FLASH access sequence */
 761
 762        /* Wait for status information */
 763        ret = c2port_poll_out_ready(dev);
 764        if (ret < 0)
 765                return ret;
 766
 767        /* Read flash programming interface status */
 768        ret = c2port_read_dr(dev, &status);
 769        if (ret < 0)
 770                return ret;
 771        if (status != C2PORT_COMMAND_OK)
 772                return -EBUSY;
 773
 774        /* Send address high byte */
 775        c2port_write_dr(dev, offset >> 8);
 776        ret = c2port_poll_in_busy(dev);
 777        if (ret < 0)
 778                return ret;
 779
 780        /* Send address low byte */
 781        c2port_write_dr(dev, offset & 0x00ff);
 782        ret = c2port_poll_in_busy(dev);
 783        if (ret < 0)
 784                return ret;
 785
 786        /* Send address block size */
 787        c2port_write_dr(dev, nwrite);
 788        ret = c2port_poll_in_busy(dev);
 789        if (ret < 0)
 790                return ret;
 791
 792        /* Should check status before writing FLASH block */
 793
 794        /* Wait for status information */
 795        ret = c2port_poll_out_ready(dev);
 796        if (ret < 0)
 797                return ret;
 798
 799        /* Read flash programming interface status */
 800        ret = c2port_read_dr(dev, &status);
 801        if (ret < 0)
 802                return ret;
 803        if (status != C2PORT_COMMAND_OK)
 804                return -EBUSY;
 805
 806        /* Write flash block */
 807        for (i = 0; i < nwrite; i++) {
 808                ret = c2port_write_dr(dev, *(buffer+i));
 809                if (ret < 0)
 810                        return ret;
 811
 812                ret = c2port_poll_in_busy(dev);
 813                if (ret < 0)
 814                        return ret;
 815
 816        }
 817
 818        /* Wait for last flash write to complete */
 819        ret = c2port_poll_out_ready(dev);
 820        if (ret < 0)
 821                return ret;
 822
 823        return nwrite;
 824}
 825
 826static ssize_t c2port_write_flash_data(struct kobject *kobj,
 827                                struct bin_attribute *attr,
 828                                char *buffer, loff_t offset, size_t count)
 829{
 830        struct c2port_device *c2dev =
 831                        dev_get_drvdata(container_of(kobj,
 832                                                struct device, kobj));
 833        int ret;
 834
 835        /* Check the device access status */
 836        if (!c2dev->access || !c2dev->flash_access)
 837                return -EBUSY;
 838
 839        mutex_lock(&c2dev->mutex);
 840        ret = __c2port_write_flash_data(c2dev, buffer, offset, count);
 841        mutex_unlock(&c2dev->mutex);
 842
 843        if (ret < 0)
 844                dev_err(c2dev->dev, "cannot write %s flash\n", c2dev->name);
 845
 846        return ret;
 847}
 848
 849/*
 850 * Class attributes
 851 */
 852
 853static struct device_attribute c2port_attrs[] = {
 854        __ATTR(name, 0444, c2port_show_name, NULL),
 855        __ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL),
 856        __ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL),
 857        __ATTR(flash_size, 0444, c2port_show_flash_size, NULL),
 858        __ATTR(access, 0644, c2port_show_access, c2port_store_access),
 859        __ATTR(reset, 0200, NULL, c2port_store_reset),
 860        __ATTR(dev_id, 0444, c2port_show_dev_id, NULL),
 861        __ATTR(rev_id, 0444, c2port_show_rev_id, NULL),
 862
 863        __ATTR(flash_access, 0644, c2port_show_flash_access,
 864                                        c2port_store_flash_access),
 865        __ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase),
 866        __ATTR_NULL,
 867};
 868
 869static struct bin_attribute c2port_bin_attrs = {
 870        .attr   = {
 871                .name   = "flash_data",
 872                .mode   = 0644
 873        },
 874        .read   = c2port_read_flash_data,
 875        .write  = c2port_write_flash_data,
 876        /* .size is computed at run-time */
 877};
 878
 879/*
 880 * Exported functions
 881 */
 882
 883struct c2port_device *c2port_device_register(char *name,
 884                                        struct c2port_ops *ops, void *devdata)
 885{
 886        struct c2port_device *c2dev;
 887        int id, ret;
 888
 889        if (unlikely(!ops) || unlikely(!ops->access) || \
 890                unlikely(!ops->c2d_dir) || unlikely(!ops->c2ck_set) || \
 891                unlikely(!ops->c2d_get) || unlikely(!ops->c2d_set))
 892                return ERR_PTR(-EINVAL);
 893
 894        c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL);
 895        kmemcheck_annotate_bitfield(c2dev, flags);
 896        if (unlikely(!c2dev))
 897                return ERR_PTR(-ENOMEM);
 898
 899        ret = idr_pre_get(&c2port_idr, GFP_KERNEL);
 900        if (!ret) {
 901                ret = -ENOMEM;
 902                goto error_idr_get_new;
 903        }
 904
 905        spin_lock_irq(&c2port_idr_lock);
 906        ret = idr_get_new(&c2port_idr, c2dev, &id);
 907        spin_unlock_irq(&c2port_idr_lock);
 908
 909        if (ret < 0)
 910                goto error_idr_get_new;
 911        c2dev->id = id;
 912
 913        c2dev->dev = device_create(c2port_class, NULL, 0, c2dev,
 914                                        "c2port%d", id);
 915        if (unlikely(!c2dev->dev)) {
 916                ret = -ENOMEM;
 917                goto error_device_create;
 918        }
 919        dev_set_drvdata(c2dev->dev, c2dev);
 920
 921        strncpy(c2dev->name, name, C2PORT_NAME_LEN);
 922        c2dev->ops = ops;
 923        mutex_init(&c2dev->mutex);
 924
 925        /* Create binary file */
 926        c2port_bin_attrs.size = ops->blocks_num * ops->block_size;
 927        ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs);
 928        if (unlikely(ret))
 929                goto error_device_create_bin_file;
 930
 931        /* By default C2 port access is off */
 932        c2dev->access = c2dev->flash_access = 0;
 933        ops->access(c2dev, 0);
 934
 935        dev_info(c2dev->dev, "C2 port %s added\n", name);
 936        dev_info(c2dev->dev, "%s flash has %d blocks x %d bytes "
 937                                "(%d bytes total)\n",
 938                                name, ops->blocks_num, ops->block_size,
 939                                ops->blocks_num * ops->block_size);
 940
 941        return c2dev;
 942
 943error_device_create_bin_file:
 944        device_destroy(c2port_class, 0);
 945
 946error_device_create:
 947        spin_lock_irq(&c2port_idr_lock);
 948        idr_remove(&c2port_idr, id);
 949        spin_unlock_irq(&c2port_idr_lock);
 950
 951error_idr_get_new:
 952        kfree(c2dev);
 953
 954        return ERR_PTR(ret);
 955}
 956EXPORT_SYMBOL(c2port_device_register);
 957
 958void c2port_device_unregister(struct c2port_device *c2dev)
 959{
 960        if (!c2dev)
 961                return;
 962
 963        dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name);
 964
 965        device_remove_bin_file(c2dev->dev, &c2port_bin_attrs);
 966        spin_lock_irq(&c2port_idr_lock);
 967        idr_remove(&c2port_idr, c2dev->id);
 968        spin_unlock_irq(&c2port_idr_lock);
 969
 970        device_destroy(c2port_class, c2dev->id);
 971
 972        kfree(c2dev);
 973}
 974EXPORT_SYMBOL(c2port_device_unregister);
 975
 976/*
 977 * Module stuff
 978 */
 979
 980static int __init c2port_init(void)
 981{
 982        printk(KERN_INFO "Silicon Labs C2 port support v. " DRIVER_VERSION
 983                " - (C) 2007 Rodolfo Giometti\n");
 984
 985        c2port_class = class_create(THIS_MODULE, "c2port");
 986        if (!c2port_class) {
 987                printk(KERN_ERR "c2port: failed to allocate class\n");
 988                return -ENOMEM;
 989        }
 990        c2port_class->dev_attrs = c2port_attrs;
 991
 992        return 0;
 993}
 994
 995static void __exit c2port_exit(void)
 996{
 997        class_destroy(c2port_class);
 998}
 999
1000module_init(c2port_init);
1001module_exit(c2port_exit);
1002
1003MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
1004MODULE_DESCRIPTION("Silicon Labs C2 port support v. " DRIVER_VERSION);
1005MODULE_LICENSE("GPL");
1006
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.