linux/drivers/scsi/aic94xx/aic94xx_sds.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Aic94xx SAS/SATA driver access to shared data structures and memory
   4 * maps.
   5 *
   6 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
   7 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
   8 */
   9
  10#include <linux/pci.h>
  11#include <linux/slab.h>
  12#include <linux/delay.h>
  13
  14#include "aic94xx.h"
  15#include "aic94xx_reg.h"
  16#include "aic94xx_sds.h"
  17
  18/* ---------- OCM stuff ---------- */
  19
  20struct asd_ocm_dir_ent {
  21        u8 type;
  22        u8 offs[3];
  23        u8 _r1;
  24        u8 size[3];
  25} __attribute__ ((packed));
  26
  27struct asd_ocm_dir {
  28        char sig[2];
  29        u8   _r1[2];
  30        u8   major;          /* 0 */
  31        u8   minor;          /* 0 */
  32        u8   _r2;
  33        u8   num_de;
  34        struct asd_ocm_dir_ent entry[15];
  35} __attribute__ ((packed));
  36
  37#define OCM_DE_OCM_DIR                  0x00
  38#define OCM_DE_WIN_DRVR                 0x01
  39#define OCM_DE_BIOS_CHIM                0x02
  40#define OCM_DE_RAID_ENGN                0x03
  41#define OCM_DE_BIOS_INTL                0x04
  42#define OCM_DE_BIOS_CHIM_OSM            0x05
  43#define OCM_DE_BIOS_CHIM_DYNAMIC        0x06
  44#define OCM_DE_ADDC2C_RES0              0x07
  45#define OCM_DE_ADDC2C_RES1              0x08
  46#define OCM_DE_ADDC2C_RES2              0x09
  47#define OCM_DE_ADDC2C_RES3              0x0A
  48
  49#define OCM_INIT_DIR_ENTRIES    5
  50/***************************************************************************
  51*  OCM directory default
  52***************************************************************************/
  53static struct asd_ocm_dir OCMDirInit =
  54{
  55        .sig = {0x4D, 0x4F},    /* signature */
  56        .num_de = OCM_INIT_DIR_ENTRIES, /* no. of directory entries */
  57};
  58
  59/***************************************************************************
  60*  OCM directory Entries default
  61***************************************************************************/
  62static struct asd_ocm_dir_ent OCMDirEntriesInit[OCM_INIT_DIR_ENTRIES] =
  63{
  64        {
  65                .type = (OCM_DE_ADDC2C_RES0),   /* Entry type  */
  66                .offs = {128},                  /* Offset */
  67                .size = {0, 4},                 /* size */
  68        },
  69        {
  70                .type = (OCM_DE_ADDC2C_RES1),   /* Entry type  */
  71                .offs = {128, 4},               /* Offset */
  72                .size = {0, 4},                 /* size */
  73        },
  74        {
  75                .type = (OCM_DE_ADDC2C_RES2),   /* Entry type  */
  76                .offs = {128, 8},               /* Offset */
  77                .size = {0, 4},                 /* size */
  78        },
  79        {
  80                .type = (OCM_DE_ADDC2C_RES3),   /* Entry type  */
  81                .offs = {128, 12},              /* Offset */
  82                .size = {0, 4},                 /* size */
  83        },
  84        {
  85                .type = (OCM_DE_WIN_DRVR),      /* Entry type  */
  86                .offs = {128, 16},              /* Offset */
  87                .size = {128, 235, 1},          /* size */
  88        },
  89};
  90
  91struct asd_bios_chim_struct {
  92        char sig[4];
  93        u8   major;          /* 1 */
  94        u8   minor;          /* 0 */
  95        u8   bios_major;
  96        u8   bios_minor;
  97        __le32  bios_build;
  98        u8   flags;
  99        u8   pci_slot;
 100        __le16  ue_num;
 101        __le16  ue_size;
 102        u8  _r[14];
 103        /* The unit element array is right here.
 104         */
 105} __attribute__ ((packed));
 106
 107/**
 108 * asd_read_ocm_seg - read an on chip memory (OCM) segment
 109 * @asd_ha: pointer to the host adapter structure
 110 * @buffer: where to write the read data
 111 * @offs: offset into OCM where to read from
 112 * @size: how many bytes to read
 113 *
 114 * Return the number of bytes not read. Return 0 on success.
 115 */
 116static int asd_read_ocm_seg(struct asd_ha_struct *asd_ha, void *buffer,
 117                            u32 offs, int size)
 118{
 119        u8 *p = buffer;
 120        if (unlikely(asd_ha->iospace))
 121                asd_read_reg_string(asd_ha, buffer, offs+OCM_BASE_ADDR, size);
 122        else {
 123                for ( ; size > 0; size--, offs++, p++)
 124                        *p = asd_read_ocm_byte(asd_ha, offs);
 125        }
 126        return size;
 127}
 128
 129static int asd_read_ocm_dir(struct asd_ha_struct *asd_ha,
 130                            struct asd_ocm_dir *dir, u32 offs)
 131{
 132        int err = asd_read_ocm_seg(asd_ha, dir, offs, sizeof(*dir));
 133        if (err) {
 134                ASD_DPRINTK("couldn't read ocm segment\n");
 135                return err;
 136        }
 137
 138        if (dir->sig[0] != 'M' || dir->sig[1] != 'O') {
 139                ASD_DPRINTK("no valid dir signature(%c%c) at start of OCM\n",
 140                            dir->sig[0], dir->sig[1]);
 141                return -ENOENT;
 142        }
 143        if (dir->major != 0) {
 144                asd_printk("unsupported major version of ocm dir:0x%x\n",
 145                           dir->major);
 146                return -ENOENT;
 147        }
 148        dir->num_de &= 0xf;
 149        return 0;
 150}
 151
 152/**
 153 * asd_write_ocm_seg - write an on chip memory (OCM) segment
 154 * @asd_ha: pointer to the host adapter structure
 155 * @buffer: where to read the write data
 156 * @offs: offset into OCM to write to
 157 * @size: how many bytes to write
 158 *
 159 * Return the number of bytes not written. Return 0 on success.
 160 */
 161static void asd_write_ocm_seg(struct asd_ha_struct *asd_ha, void *buffer,
 162                            u32 offs, int size)
 163{
 164        u8 *p = buffer;
 165        if (unlikely(asd_ha->iospace))
 166                asd_write_reg_string(asd_ha, buffer, offs+OCM_BASE_ADDR, size);
 167        else {
 168                for ( ; size > 0; size--, offs++, p++)
 169                        asd_write_ocm_byte(asd_ha, offs, *p);
 170        }
 171        return;
 172}
 173
 174#define THREE_TO_NUM(X) ((X)[0] | ((X)[1] << 8) | ((X)[2] << 16))
 175
 176static int asd_find_dir_entry(struct asd_ocm_dir *dir, u8 type,
 177                              u32 *offs, u32 *size)
 178{
 179        int i;
 180        struct asd_ocm_dir_ent *ent;
 181
 182        for (i = 0; i < dir->num_de; i++) {
 183                if (dir->entry[i].type == type)
 184                        break;
 185        }
 186        if (i >= dir->num_de)
 187                return -ENOENT;
 188        ent = &dir->entry[i];
 189        *offs = (u32) THREE_TO_NUM(ent->offs);
 190        *size = (u32) THREE_TO_NUM(ent->size);
 191        return 0;
 192}
 193
 194#define OCM_BIOS_CHIM_DE  2
 195#define BC_BIOS_PRESENT   1
 196
 197static int asd_get_bios_chim(struct asd_ha_struct *asd_ha,
 198                             struct asd_ocm_dir *dir)
 199{
 200        int err;
 201        struct asd_bios_chim_struct *bc_struct;
 202        u32 offs, size;
 203
 204        err = asd_find_dir_entry(dir, OCM_BIOS_CHIM_DE, &offs, &size);
 205        if (err) {
 206                ASD_DPRINTK("couldn't find BIOS_CHIM dir ent\n");
 207                goto out;
 208        }
 209        err = -ENOMEM;
 210        bc_struct = kmalloc(sizeof(*bc_struct), GFP_KERNEL);
 211        if (!bc_struct) {
 212                asd_printk("no memory for bios_chim struct\n");
 213                goto out;
 214        }
 215        err = asd_read_ocm_seg(asd_ha, (void *)bc_struct, offs,
 216                               sizeof(*bc_struct));
 217        if (err) {
 218                ASD_DPRINTK("couldn't read ocm segment\n");
 219                goto out2;
 220        }
 221        if (strncmp(bc_struct->sig, "SOIB", 4)
 222            && strncmp(bc_struct->sig, "IPSA", 4)) {
 223                ASD_DPRINTK("BIOS_CHIM entry has no valid sig(%c%c%c%c)\n",
 224                            bc_struct->sig[0], bc_struct->sig[1],
 225                            bc_struct->sig[2], bc_struct->sig[3]);
 226                err = -ENOENT;
 227                goto out2;
 228        }
 229        if (bc_struct->major != 1) {
 230                asd_printk("BIOS_CHIM unsupported major version:0x%x\n",
 231                           bc_struct->major);
 232                err = -ENOENT;
 233                goto out2;
 234        }
 235        if (bc_struct->flags & BC_BIOS_PRESENT) {
 236                asd_ha->hw_prof.bios.present = 1;
 237                asd_ha->hw_prof.bios.maj = bc_struct->bios_major;
 238                asd_ha->hw_prof.bios.min = bc_struct->bios_minor;
 239                asd_ha->hw_prof.bios.bld = le32_to_cpu(bc_struct->bios_build);
 240                ASD_DPRINTK("BIOS present (%d,%d), %d\n",
 241                            asd_ha->hw_prof.bios.maj,
 242                            asd_ha->hw_prof.bios.min,
 243                            asd_ha->hw_prof.bios.bld);
 244        }
 245        asd_ha->hw_prof.ue.num = le16_to_cpu(bc_struct->ue_num);
 246        asd_ha->hw_prof.ue.size= le16_to_cpu(bc_struct->ue_size);
 247        ASD_DPRINTK("ue num:%d, ue size:%d\n", asd_ha->hw_prof.ue.num,
 248                    asd_ha->hw_prof.ue.size);
 249        size = asd_ha->hw_prof.ue.num * asd_ha->hw_prof.ue.size;
 250        if (size > 0) {
 251                err = -ENOMEM;
 252                asd_ha->hw_prof.ue.area = kmalloc(size, GFP_KERNEL);
 253                if (!asd_ha->hw_prof.ue.area)
 254                        goto out2;
 255                err = asd_read_ocm_seg(asd_ha, (void *)asd_ha->hw_prof.ue.area,
 256                                       offs + sizeof(*bc_struct), size);
 257                if (err) {
 258                        kfree(asd_ha->hw_prof.ue.area);
 259                        asd_ha->hw_prof.ue.area = NULL;
 260                        asd_ha->hw_prof.ue.num  = 0;
 261                        asd_ha->hw_prof.ue.size = 0;
 262                        ASD_DPRINTK("couldn't read ue entries(%d)\n", err);
 263                }
 264        }
 265out2:
 266        kfree(bc_struct);
 267out:
 268        return err;
 269}
 270
 271static void
 272asd_hwi_initialize_ocm_dir (struct asd_ha_struct *asd_ha)
 273{
 274        int i;
 275
 276        /* Zero OCM */
 277        for (i = 0; i < OCM_MAX_SIZE; i += 4)
 278                asd_write_ocm_dword(asd_ha, i, 0);
 279
 280        /* Write Dir */
 281        asd_write_ocm_seg(asd_ha, &OCMDirInit, 0,
 282                          sizeof(struct asd_ocm_dir));
 283
 284        /* Write Dir Entries */
 285        for (i = 0; i < OCM_INIT_DIR_ENTRIES; i++)
 286                asd_write_ocm_seg(asd_ha, &OCMDirEntriesInit[i],
 287                                  sizeof(struct asd_ocm_dir) +
 288                                  (i * sizeof(struct asd_ocm_dir_ent))
 289                                  , sizeof(struct asd_ocm_dir_ent));
 290
 291}
 292
 293static int
 294asd_hwi_check_ocm_access (struct asd_ha_struct *asd_ha)
 295{
 296        struct pci_dev *pcidev = asd_ha->pcidev;
 297        u32 reg;
 298        int err = 0;
 299        u32 v;
 300
 301        /* check if OCM has been initialized by BIOS */
 302        reg = asd_read_reg_dword(asd_ha, EXSICNFGR);
 303
 304        if (!(reg & OCMINITIALIZED)) {
 305                err = pci_read_config_dword(pcidev, PCIC_INTRPT_STAT, &v);
 306                if (err) {
 307                        asd_printk("couldn't access PCIC_INTRPT_STAT of %s\n",
 308                                        pci_name(pcidev));
 309                        goto out;
 310                }
 311
 312                printk(KERN_INFO "OCM is not initialized by BIOS,"
 313                       "reinitialize it and ignore it, current IntrptStatus"
 314                       "is 0x%x\n", v);
 315
 316                if (v)
 317                        err = pci_write_config_dword(pcidev,
 318                                                     PCIC_INTRPT_STAT, v);
 319                if (err) {
 320                        asd_printk("couldn't write PCIC_INTRPT_STAT of %s\n",
 321                                        pci_name(pcidev));
 322                        goto out;
 323                }
 324
 325                asd_hwi_initialize_ocm_dir(asd_ha);
 326
 327        }
 328out:
 329        return err;
 330}
 331
 332/**
 333 * asd_read_ocm - read on chip memory (OCM)
 334 * @asd_ha: pointer to the host adapter structure
 335 */
 336int asd_read_ocm(struct asd_ha_struct *asd_ha)
 337{
 338        int err;
 339        struct asd_ocm_dir *dir;
 340
 341        if (asd_hwi_check_ocm_access(asd_ha))
 342                return -1;
 343
 344        dir = kmalloc(sizeof(*dir), GFP_KERNEL);
 345        if (!dir) {
 346                asd_printk("no memory for ocm dir\n");
 347                return -ENOMEM;
 348        }
 349
 350        err = asd_read_ocm_dir(asd_ha, dir, 0);
 351        if (err)
 352                goto out;
 353
 354        err = asd_get_bios_chim(asd_ha, dir);
 355out:
 356        kfree(dir);
 357        return err;
 358}
 359
 360/* ---------- FLASH stuff ---------- */
 361
 362#define FLASH_RESET                     0xF0
 363
 364#define ASD_FLASH_SIZE                  0x200000
 365#define FLASH_DIR_COOKIE                "*** ADAPTEC FLASH DIRECTORY *** "
 366#define FLASH_NEXT_ENTRY_OFFS           0x2000
 367#define FLASH_MAX_DIR_ENTRIES           32
 368
 369#define FLASH_DE_TYPE_MASK              0x3FFFFFFF
 370#define FLASH_DE_MS                     0x120
 371#define FLASH_DE_CTRL_A_USER            0xE0
 372
 373struct asd_flash_de {
 374        __le32   type;
 375        __le32   offs;
 376        __le32   pad_size;
 377        __le32   image_size;
 378        __le32   chksum;
 379        u8       _r[12];
 380        u8       version[32];
 381} __attribute__ ((packed));
 382
 383struct asd_flash_dir {
 384        u8    cookie[32];
 385        __le32   rev;             /* 2 */
 386        __le32   chksum;
 387        __le32   chksum_antidote;
 388        __le32   bld;
 389        u8    bld_id[32];         /* build id data */
 390        u8    ver_data[32];       /* date and time of build */
 391        __le32   ae_mask;
 392        __le32   v_mask;
 393        __le32   oc_mask;
 394        u8    _r[20];
 395        struct asd_flash_de dir_entry[FLASH_MAX_DIR_ENTRIES];
 396} __attribute__ ((packed));
 397
 398struct asd_manuf_sec {
 399        char  sig[2];             /* 'S', 'M' */
 400        u16   offs_next;
 401        u8    maj;           /* 0 */
 402        u8    min;           /* 0 */
 403        u16   chksum;
 404        u16   size;
 405        u8    _r[6];
 406        u8    sas_addr[SAS_ADDR_SIZE];
 407        u8    pcba_sn[ASD_PCBA_SN_SIZE];
 408        /* Here start the other segments */
 409        u8    linked_list[];
 410} __attribute__ ((packed));
 411
 412struct asd_manuf_phy_desc {
 413        u8    state;         /* low 4 bits */
 414#define MS_PHY_STATE_ENABLED    0
 415#define MS_PHY_STATE_REPORTED   1
 416#define MS_PHY_STATE_HIDDEN     2
 417        u8    phy_id;
 418        u16   _r;
 419        u8    phy_control_0; /* mode 5 reg 0x160 */
 420        u8    phy_control_1; /* mode 5 reg 0x161 */
 421        u8    phy_control_2; /* mode 5 reg 0x162 */
 422        u8    phy_control_3; /* mode 5 reg 0x163 */
 423} __attribute__ ((packed));
 424
 425struct asd_manuf_phy_param {
 426        char  sig[2];             /* 'P', 'M' */
 427        u16   next;
 428        u8    maj;           /* 0 */
 429        u8    min;           /* 2 */
 430        u8    num_phy_desc;  /* 8 */
 431        u8    phy_desc_size; /* 8 */
 432        u8    _r[3];
 433        u8    usage_model_id;
 434        u32   _r2;
 435        struct asd_manuf_phy_desc phy_desc[ASD_MAX_PHYS];
 436} __attribute__ ((packed));
 437
 438#if 0
 439static const char *asd_sb_type[] = {
 440        "unknown",
 441        "SGPIO",
 442        [2 ... 0x7F] = "unknown",
 443        [0x80] = "ADPT_I2C",
 444        [0x81 ... 0xFF] = "VENDOR_UNIQUExx"
 445};
 446#endif
 447
 448struct asd_ms_sb_desc {
 449        u8    type;
 450        u8    node_desc_index;
 451        u8    conn_desc_index;
 452        u8    _recvd[];
 453} __attribute__ ((packed));
 454
 455#if 0
 456static const char *asd_conn_type[] = {
 457        [0 ... 7] = "unknown",
 458        "SFF8470",
 459        "SFF8482",
 460        "SFF8484",
 461        [0x80] = "PCIX_DAUGHTER0",
 462        [0x81] = "SAS_DAUGHTER0",
 463        [0x82 ... 0xFF] = "VENDOR_UNIQUExx"
 464};
 465
 466static const char *asd_conn_location[] = {
 467        "unknown",
 468        "internal",
 469        "external",
 470        "board_to_board",
 471};
 472#endif
 473
 474struct asd_ms_conn_desc {
 475        u8    type;
 476        u8    location;
 477        u8    num_sideband_desc;
 478        u8    size_sideband_desc;
 479        u32   _resvd;
 480        u8    name[16];
 481        struct asd_ms_sb_desc sb_desc[];
 482} __attribute__ ((packed));
 483
 484struct asd_nd_phy_desc {
 485        u8    vp_attch_type;
 486        u8    attch_specific[];
 487} __attribute__ ((packed));
 488
 489#if 0
 490static const char *asd_node_type[] = {
 491        "IOP",
 492        "IO_CONTROLLER",
 493        "EXPANDER",
 494        "PORT_MULTIPLIER",
 495        "PORT_MULTIPLEXER",
 496        "MULTI_DROP_I2C_BUS",
 497};
 498#endif
 499
 500struct asd_ms_node_desc {
 501        u8    type;
 502        u8    num_phy_desc;
 503        u8    size_phy_desc;
 504        u8    _resvd;
 505        u8    name[16];
 506        struct asd_nd_phy_desc phy_desc[];
 507} __attribute__ ((packed));
 508
 509struct asd_ms_conn_map {
 510        char  sig[2];             /* 'M', 'C' */
 511        __le16 next;
 512        u8    maj;                /* 0 */
 513        u8    min;                /* 0 */
 514        __le16 cm_size;           /* size of this struct */
 515        u8    num_conn;
 516        u8    conn_size;
 517        u8    num_nodes;
 518        u8    usage_model_id;
 519        u32   _resvd;
 520        union {
 521                DECLARE_FLEX_ARRAY(struct asd_ms_conn_desc, conn_desc);
 522                DECLARE_FLEX_ARRAY(struct asd_ms_node_desc, node_desc);
 523        };
 524} __attribute__ ((packed));
 525
 526struct asd_ctrla_phy_entry {
 527        u8    sas_addr[SAS_ADDR_SIZE];
 528        u8    sas_link_rates;  /* max in hi bits, min in low bits */
 529        u8    flags;
 530        u8    sata_link_rates;
 531        u8    _r[5];
 532} __attribute__ ((packed));
 533
 534struct asd_ctrla_phy_settings {
 535        u8    id0;                /* P'h'y */
 536        u8    _r;
 537        u16   next;
 538        u8    num_phys;       /* number of PHYs in the PCI function */
 539        u8    _r2[3];
 540        struct asd_ctrla_phy_entry phy_ent[ASD_MAX_PHYS];
 541} __attribute__ ((packed));
 542
 543struct asd_ll_el {
 544        u8   id0;
 545        u8   id1;
 546        __le16  next;
 547        u8   something_here[];
 548} __attribute__ ((packed));
 549
 550static int asd_poll_flash(struct asd_ha_struct *asd_ha)
 551{
 552        int c;
 553        u8 d;
 554
 555        for (c = 5000; c > 0; c--) {
 556                d  = asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar);
 557                d ^= asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar);
 558                if (!d)
 559                        return 0;
 560                udelay(5);
 561        }
 562        return -ENOENT;
 563}
 564
 565static int asd_reset_flash(struct asd_ha_struct *asd_ha)
 566{
 567        int err;
 568
 569        err = asd_poll_flash(asd_ha);
 570        if (err)
 571                return err;
 572        asd_write_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar, FLASH_RESET);
 573        err = asd_poll_flash(asd_ha);
 574
 575        return err;
 576}
 577
 578static int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
 579                              void *buffer, u32 offs, int size)
 580{
 581        asd_read_reg_string(asd_ha, buffer, asd_ha->hw_prof.flash.bar+offs,
 582                            size);
 583        return 0;
 584}
 585
 586/**
 587 * asd_find_flash_dir - finds and reads the flash directory
 588 * @asd_ha: pointer to the host adapter structure
 589 * @flash_dir: pointer to flash directory structure
 590 *
 591 * If found, the flash directory segment will be copied to
 592 * @flash_dir.  Return 1 if found, 0 if not.
 593 */
 594static int asd_find_flash_dir(struct asd_ha_struct *asd_ha,
 595                              struct asd_flash_dir *flash_dir)
 596{
 597        u32 v;
 598        for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
 599                asd_read_flash_seg(asd_ha, flash_dir, v,
 600                                   sizeof(FLASH_DIR_COOKIE)-1);
 601                if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE,
 602                           sizeof(FLASH_DIR_COOKIE)-1) == 0) {
 603                        asd_ha->hw_prof.flash.dir_offs = v;
 604                        asd_read_flash_seg(asd_ha, flash_dir, v,
 605                                           sizeof(*flash_dir));
 606                        return 1;
 607                }
 608        }
 609        return 0;
 610}
 611
 612static int asd_flash_getid(struct asd_ha_struct *asd_ha)
 613{
 614        int err = 0;
 615        u32 reg;
 616
 617        reg = asd_read_reg_dword(asd_ha, EXSICNFGR);
 618
 619        if (pci_read_config_dword(asd_ha->pcidev, PCI_CONF_FLSH_BAR,
 620                                  &asd_ha->hw_prof.flash.bar)) {
 621                asd_printk("couldn't read PCI_CONF_FLSH_BAR of %s\n",
 622                           pci_name(asd_ha->pcidev));
 623                return -ENOENT;
 624        }
 625        asd_ha->hw_prof.flash.present = 1;
 626        asd_ha->hw_prof.flash.wide = reg & FLASHW ? 1 : 0;
 627        err = asd_reset_flash(asd_ha);
 628        if (err) {
 629                ASD_DPRINTK("couldn't reset flash(%d)\n", err);
 630                return err;
 631        }
 632        return 0;
 633}
 634
 635static u16 asd_calc_flash_chksum(u16 *p, int size)
 636{
 637        u16 chksum = 0;
 638
 639        while (size-- > 0)
 640                chksum += *p++;
 641
 642        return chksum;
 643}
 644
 645
 646static int asd_find_flash_de(struct asd_flash_dir *flash_dir, u32 entry_type,
 647                             u32 *offs, u32 *size)
 648{
 649        int i;
 650        struct asd_flash_de *de;
 651
 652        for (i = 0; i < FLASH_MAX_DIR_ENTRIES; i++) {
 653                u32 type = le32_to_cpu(flash_dir->dir_entry[i].type);
 654
 655                type &= FLASH_DE_TYPE_MASK;
 656                if (type == entry_type)
 657                        break;
 658        }
 659        if (i >= FLASH_MAX_DIR_ENTRIES)
 660                return -ENOENT;
 661        de = &flash_dir->dir_entry[i];
 662        *offs = le32_to_cpu(de->offs);
 663        *size = le32_to_cpu(de->pad_size);
 664        return 0;
 665}
 666
 667static int asd_validate_ms(struct asd_manuf_sec *ms)
 668{
 669        if (ms->sig[0] != 'S' || ms->sig[1] != 'M') {
 670                ASD_DPRINTK("manuf sec: no valid sig(%c%c)\n",
 671                            ms->sig[0], ms->sig[1]);
 672                return -ENOENT;
 673        }
 674        if (ms->maj != 0) {
 675                asd_printk("unsupported manuf. sector. major version:%x\n",
 676                           ms->maj);
 677                return -ENOENT;
 678        }
 679        ms->offs_next = le16_to_cpu((__force __le16) ms->offs_next);
 680        ms->chksum = le16_to_cpu((__force __le16) ms->chksum);
 681        ms->size = le16_to_cpu((__force __le16) ms->size);
 682
 683        if (asd_calc_flash_chksum((u16 *)ms, ms->size/2)) {
 684                asd_printk("failed manuf sector checksum\n");
 685        }
 686
 687        return 0;
 688}
 689
 690static int asd_ms_get_sas_addr(struct asd_ha_struct *asd_ha,
 691                               struct asd_manuf_sec *ms)
 692{
 693        memcpy(asd_ha->hw_prof.sas_addr, ms->sas_addr, SAS_ADDR_SIZE);
 694        return 0;
 695}
 696
 697static int asd_ms_get_pcba_sn(struct asd_ha_struct *asd_ha,
 698                              struct asd_manuf_sec *ms)
 699{
 700        memcpy(asd_ha->hw_prof.pcba_sn, ms->pcba_sn, ASD_PCBA_SN_SIZE);
 701        asd_ha->hw_prof.pcba_sn[ASD_PCBA_SN_SIZE] = '\0';
 702        return 0;
 703}
 704
 705/**
 706 * asd_find_ll_by_id - find a linked list entry by its id
 707 * @start: void pointer to the first element in the linked list
 708 * @id0: the first byte of the id  (offs 0)
 709 * @id1: the second byte of the id (offs 1)
 710 *
 711 * @start has to be the _base_ element start, since the
 712 * linked list entries's offset is from this pointer.
 713 * Some linked list entries use only the first id, in which case
 714 * you can pass 0xFF for the second.
 715 */
 716static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1)
 717{
 718        struct asd_ll_el *el = start;
 719
 720        do {
 721                switch (id1) {
 722                default:
 723                        if (el->id1 == id1) {
 724                        fallthrough;
 725                case 0xFF:
 726                                if (el->id0 == id0)
 727                                        return el;
 728                        }
 729                }
 730                el = start + le16_to_cpu(el->next);
 731        } while (el != start);
 732
 733        return NULL;
 734}
 735
 736/**
 737 * asd_ms_get_phy_params - get phy parameters from the manufacturing sector
 738 * @asd_ha: pointer to the host adapter structure
 739 * @manuf_sec: pointer to the manufacturing sector
 740 *
 741 * The manufacturing sector contans also the linked list of sub-segments,
 742 * since when it was read, its size was taken from the flash directory,
 743 * not from the structure size.
 744 *
 745 * HIDDEN phys do not count in the total count.  REPORTED phys cannot
 746 * be enabled but are reported and counted towards the total.
 747 * ENABLED phys are enabled by default and count towards the total.
 748 * The absolute total phy number is ASD_MAX_PHYS.  hw_prof->num_phys
 749 * merely specifies the number of phys the host adapter decided to
 750 * report.  E.g., it is possible for phys 0, 1 and 2 to be HIDDEN,
 751 * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED.
 752 * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2
 753 * are actually enabled (enabled by default, max number of phys
 754 * enableable in this case).
 755 */
 756static int asd_ms_get_phy_params(struct asd_ha_struct *asd_ha,
 757                                 struct asd_manuf_sec *manuf_sec)
 758{
 759        int i;
 760        int en_phys = 0;
 761        int rep_phys = 0;
 762        struct asd_manuf_phy_param *phy_param;
 763        struct asd_manuf_phy_param dflt_phy_param;
 764
 765        phy_param = asd_find_ll_by_id(manuf_sec, 'P', 'M');
 766        if (!phy_param) {
 767                ASD_DPRINTK("ms: no phy parameters found\n");
 768                ASD_DPRINTK("ms: Creating default phy parameters\n");
 769                dflt_phy_param.sig[0] = 'P';
 770                dflt_phy_param.sig[1] = 'M';
 771                dflt_phy_param.maj = 0;
 772                dflt_phy_param.min = 2;
 773                dflt_phy_param.num_phy_desc = 8;
 774                dflt_phy_param.phy_desc_size = sizeof(struct asd_manuf_phy_desc);
 775                for (i =0; i < ASD_MAX_PHYS; i++) {
 776                        dflt_phy_param.phy_desc[i].state = 0;
 777                        dflt_phy_param.phy_desc[i].phy_id = i;
 778                        dflt_phy_param.phy_desc[i].phy_control_0 = 0xf6;
 779                        dflt_phy_param.phy_desc[i].phy_control_1 = 0x10;
 780                        dflt_phy_param.phy_desc[i].phy_control_2 = 0x43;
 781                        dflt_phy_param.phy_desc[i].phy_control_3 = 0xeb;
 782                }
 783
 784                phy_param = &dflt_phy_param;
 785
 786        }
 787
 788        if (phy_param->maj != 0) {
 789                asd_printk("unsupported manuf. phy param major version:0x%x\n",
 790                           phy_param->maj);
 791                return -ENOENT;
 792        }
 793
 794        ASD_DPRINTK("ms: num_phy_desc: %d\n", phy_param->num_phy_desc);
 795        asd_ha->hw_prof.enabled_phys = 0;
 796        for (i = 0; i < phy_param->num_phy_desc; i++) {
 797                struct asd_manuf_phy_desc *pd = &phy_param->phy_desc[i];
 798                switch (pd->state & 0xF) {
 799                case MS_PHY_STATE_HIDDEN:
 800                        ASD_DPRINTK("ms: phy%d: HIDDEN\n", i);
 801                        continue;
 802                case MS_PHY_STATE_REPORTED:
 803                        ASD_DPRINTK("ms: phy%d: REPORTED\n", i);
 804                        asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 805                        rep_phys++;
 806                        continue;
 807                case MS_PHY_STATE_ENABLED:
 808                        ASD_DPRINTK("ms: phy%d: ENABLED\n", i);
 809                        asd_ha->hw_prof.enabled_phys |= (1 << i);
 810                        en_phys++;
 811                        break;
 812                }
 813                asd_ha->hw_prof.phy_desc[i].phy_control_0 = pd->phy_control_0;
 814                asd_ha->hw_prof.phy_desc[i].phy_control_1 = pd->phy_control_1;
 815                asd_ha->hw_prof.phy_desc[i].phy_control_2 = pd->phy_control_2;
 816                asd_ha->hw_prof.phy_desc[i].phy_control_3 = pd->phy_control_3;
 817        }
 818        asd_ha->hw_prof.max_phys = rep_phys + en_phys;
 819        asd_ha->hw_prof.num_phys = en_phys;
 820        ASD_DPRINTK("ms: max_phys:0x%x, num_phys:0x%x\n",
 821                    asd_ha->hw_prof.max_phys, asd_ha->hw_prof.num_phys);
 822        ASD_DPRINTK("ms: enabled_phys:0x%x\n", asd_ha->hw_prof.enabled_phys);
 823        return 0;
 824}
 825
 826static int asd_ms_get_connector_map(struct asd_ha_struct *asd_ha,
 827                                    struct asd_manuf_sec *manuf_sec)
 828{
 829        struct asd_ms_conn_map *cm;
 830
 831        cm = asd_find_ll_by_id(manuf_sec, 'M', 'C');
 832        if (!cm) {
 833                ASD_DPRINTK("ms: no connector map found\n");
 834                return 0;
 835        }
 836
 837        if (cm->maj != 0) {
 838                ASD_DPRINTK("ms: unsupported: connector map major version 0x%x"
 839                            "\n", cm->maj);
 840                return -ENOENT;
 841        }
 842
 843        /* XXX */
 844
 845        return 0;
 846}
 847
 848
 849/**
 850 * asd_process_ms - find and extract information from the manufacturing sector
 851 * @asd_ha: pointer to the host adapter structure
 852 * @flash_dir: pointer to the flash directory
 853 */
 854static int asd_process_ms(struct asd_ha_struct *asd_ha,
 855                          struct asd_flash_dir *flash_dir)
 856{
 857        int err;
 858        struct asd_manuf_sec *manuf_sec;
 859        u32 offs, size;
 860
 861        err = asd_find_flash_de(flash_dir, FLASH_DE_MS, &offs, &size);
 862        if (err) {
 863                ASD_DPRINTK("Couldn't find the manuf. sector\n");
 864                goto out;
 865        }
 866
 867        if (size == 0)
 868                goto out;
 869
 870        err = -ENOMEM;
 871        manuf_sec = kmalloc(size, GFP_KERNEL);
 872        if (!manuf_sec) {
 873                ASD_DPRINTK("no mem for manuf sector\n");
 874                goto out;
 875        }
 876
 877        err = asd_read_flash_seg(asd_ha, (void *)manuf_sec, offs, size);
 878        if (err) {
 879                ASD_DPRINTK("couldn't read manuf sector at 0x%x, size 0x%x\n",
 880                            offs, size);
 881                goto out2;
 882        }
 883
 884        err = asd_validate_ms(manuf_sec);
 885        if (err) {
 886                ASD_DPRINTK("couldn't validate manuf sector\n");
 887                goto out2;
 888        }
 889
 890        err = asd_ms_get_sas_addr(asd_ha, manuf_sec);
 891        if (err) {
 892                ASD_DPRINTK("couldn't read the SAS_ADDR\n");
 893                goto out2;
 894        }
 895        ASD_DPRINTK("manuf sect SAS_ADDR %llx\n",
 896                    SAS_ADDR(asd_ha->hw_prof.sas_addr));
 897
 898        err = asd_ms_get_pcba_sn(asd_ha, manuf_sec);
 899        if (err) {
 900                ASD_DPRINTK("couldn't read the PCBA SN\n");
 901                goto out2;
 902        }
 903        ASD_DPRINTK("manuf sect PCBA SN %s\n", asd_ha->hw_prof.pcba_sn);
 904
 905        err = asd_ms_get_phy_params(asd_ha, manuf_sec);
 906        if (err) {
 907                ASD_DPRINTK("ms: couldn't get phy parameters\n");
 908                goto out2;
 909        }
 910
 911        err = asd_ms_get_connector_map(asd_ha, manuf_sec);
 912        if (err) {
 913                ASD_DPRINTK("ms: couldn't get connector map\n");
 914                goto out2;
 915        }
 916
 917out2:
 918        kfree(manuf_sec);
 919out:
 920        return err;
 921}
 922
 923static int asd_process_ctrla_phy_settings(struct asd_ha_struct *asd_ha,
 924                                          struct asd_ctrla_phy_settings *ps)
 925{
 926        int i;
 927        for (i = 0; i < ps->num_phys; i++) {
 928                struct asd_ctrla_phy_entry *pe = &ps->phy_ent[i];
 929
 930                if (!PHY_ENABLED(asd_ha, i))
 931                        continue;
 932                if (*(u64 *)pe->sas_addr == 0) {
 933                        asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 934                        continue;
 935                }
 936                /* This is the SAS address which should be sent in IDENTIFY. */
 937                memcpy(asd_ha->hw_prof.phy_desc[i].sas_addr, pe->sas_addr,
 938                       SAS_ADDR_SIZE);
 939                asd_ha->hw_prof.phy_desc[i].max_sas_lrate =
 940                        (pe->sas_link_rates & 0xF0) >> 4;
 941                asd_ha->hw_prof.phy_desc[i].min_sas_lrate =
 942                        (pe->sas_link_rates & 0x0F);
 943                asd_ha->hw_prof.phy_desc[i].max_sata_lrate =
 944                        (pe->sata_link_rates & 0xF0) >> 4;
 945                asd_ha->hw_prof.phy_desc[i].min_sata_lrate =
 946                        (pe->sata_link_rates & 0x0F);
 947                asd_ha->hw_prof.phy_desc[i].flags = pe->flags;
 948                ASD_DPRINTK("ctrla: phy%d: sas_addr: %llx, sas rate:0x%x-0x%x,"
 949                            " sata rate:0x%x-0x%x, flags:0x%x\n",
 950                            i,
 951                            SAS_ADDR(asd_ha->hw_prof.phy_desc[i].sas_addr),
 952                            asd_ha->hw_prof.phy_desc[i].max_sas_lrate,
 953                            asd_ha->hw_prof.phy_desc[i].min_sas_lrate,
 954                            asd_ha->hw_prof.phy_desc[i].max_sata_lrate,
 955                            asd_ha->hw_prof.phy_desc[i].min_sata_lrate,
 956                            asd_ha->hw_prof.phy_desc[i].flags);
 957        }
 958
 959        return 0;
 960}
 961
 962/**
 963 * asd_process_ctrl_a_user - process CTRL-A user settings
 964 * @asd_ha: pointer to the host adapter structure
 965 * @flash_dir: pointer to the flash directory
 966 */
 967static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha,
 968                                   struct asd_flash_dir *flash_dir)
 969{
 970        int err, i;
 971        u32 offs, size;
 972        struct asd_ll_el *el = NULL;
 973        struct asd_ctrla_phy_settings *ps;
 974        struct asd_ctrla_phy_settings dflt_ps;
 975
 976        err = asd_find_flash_de(flash_dir, FLASH_DE_CTRL_A_USER, &offs, &size);
 977        if (err) {
 978                ASD_DPRINTK("couldn't find CTRL-A user settings section\n");
 979                ASD_DPRINTK("Creating default CTRL-A user settings section\n");
 980
 981                dflt_ps.id0 = 'h';
 982                dflt_ps.num_phys = 8;
 983                for (i =0; i < ASD_MAX_PHYS; i++) {
 984                        memcpy(dflt_ps.phy_ent[i].sas_addr,
 985                               asd_ha->hw_prof.sas_addr, SAS_ADDR_SIZE);
 986                        dflt_ps.phy_ent[i].sas_link_rates = 0x98;
 987                        dflt_ps.phy_ent[i].flags = 0x0;
 988                        dflt_ps.phy_ent[i].sata_link_rates = 0x0;
 989                }
 990
 991                size = sizeof(struct asd_ctrla_phy_settings);
 992                ps = &dflt_ps;
 993                goto out_process;
 994        }
 995
 996        if (size == 0)
 997                goto out;
 998
 999        err = -ENOMEM;
1000        el = kmalloc(size, GFP_KERNEL);
1001        if (!el) {
1002                ASD_DPRINTK("no mem for ctrla user settings section\n");
1003                goto out;
1004        }
1005
1006        err = asd_read_flash_seg(asd_ha, (void *)el, offs, size);
1007        if (err) {
1008                ASD_DPRINTK("couldn't read ctrla phy settings section\n");
1009                goto out2;
1010        }
1011
1012        err = -ENOENT;
1013        ps = asd_find_ll_by_id(el, 'h', 0xFF);
1014        if (!ps) {
1015                ASD_DPRINTK("couldn't find ctrla phy settings struct\n");
1016                goto out2;
1017        }
1018out_process:
1019        err = asd_process_ctrla_phy_settings(asd_ha, ps);
1020        if (err) {
1021                ASD_DPRINTK("couldn't process ctrla phy settings\n");
1022                goto out2;
1023        }
1024out2:
1025        kfree(el);
1026out:
1027        return err;
1028}
1029
1030/**
1031 * asd_read_flash - read flash memory
1032 * @asd_ha: pointer to the host adapter structure
1033 */
1034int asd_read_flash(struct asd_ha_struct *asd_ha)
1035{
1036        int err;
1037        struct asd_flash_dir *flash_dir;
1038
1039        err = asd_flash_getid(asd_ha);
1040        if (err)
1041                return err;
1042
1043        flash_dir = kmalloc(sizeof(*flash_dir), GFP_KERNEL);
1044        if (!flash_dir)
1045                return -ENOMEM;
1046
1047        err = -ENOENT;
1048        if (!asd_find_flash_dir(asd_ha, flash_dir)) {
1049                ASD_DPRINTK("couldn't find flash directory\n");
1050                goto out;
1051        }
1052
1053        if (le32_to_cpu(flash_dir->rev) != 2) {
1054                asd_printk("unsupported flash dir version:0x%x\n",
1055                           le32_to_cpu(flash_dir->rev));
1056                goto out;
1057        }
1058
1059        err = asd_process_ms(asd_ha, flash_dir);
1060        if (err) {
1061                ASD_DPRINTK("couldn't process manuf sector settings\n");
1062                goto out;
1063        }
1064
1065        err = asd_process_ctrl_a_user(asd_ha, flash_dir);
1066        if (err) {
1067                ASD_DPRINTK("couldn't process CTRL-A user settings\n");
1068                goto out;
1069        }
1070
1071out:
1072        kfree(flash_dir);
1073        return err;
1074}
1075
1076/**
1077 * asd_verify_flash_seg - verify data with flash memory
1078 * @asd_ha: pointer to the host adapter structure
1079 * @src: pointer to the source data to be verified
1080 * @dest_offset: offset from flash memory
1081 * @bytes_to_verify: total bytes to verify
1082 */
1083int asd_verify_flash_seg(struct asd_ha_struct *asd_ha,
1084                         const void *src, u32 dest_offset, u32 bytes_to_verify)
1085{
1086        const u8 *src_buf;
1087        u8 flash_char;
1088        int err;
1089        u32 nv_offset, reg, i;
1090
1091        reg = asd_ha->hw_prof.flash.bar;
1092        src_buf = NULL;
1093
1094        err = FLASH_OK;
1095        nv_offset = dest_offset;
1096        src_buf = (const u8 *)src;
1097        for (i = 0; i < bytes_to_verify; i++) {
1098                flash_char = asd_read_reg_byte(asd_ha, reg + nv_offset + i);
1099                if (flash_char != src_buf[i]) {
1100                        err = FAIL_VERIFY;
1101                        break;
1102                }
1103        }
1104        return err;
1105}
1106
1107/**
1108 * asd_write_flash_seg - write data into flash memory
1109 * @asd_ha: pointer to the host adapter structure
1110 * @src: pointer to the source data to be written
1111 * @dest_offset: offset from flash memory
1112 * @bytes_to_write: total bytes to write
1113 */
1114int asd_write_flash_seg(struct asd_ha_struct *asd_ha,
1115                        const void *src, u32 dest_offset, u32 bytes_to_write)
1116{
1117        const u8 *src_buf;
1118        u32 nv_offset, reg, i;
1119        int err;
1120
1121        reg = asd_ha->hw_prof.flash.bar;
1122        src_buf = NULL;
1123
1124        err = asd_check_flash_type(asd_ha);
1125        if (err) {
1126                ASD_DPRINTK("couldn't find the type of flash. err=%d\n", err);
1127                return err;
1128        }
1129
1130        nv_offset = dest_offset;
1131        err = asd_erase_nv_sector(asd_ha, nv_offset, bytes_to_write);
1132        if (err) {
1133                ASD_DPRINTK("Erase failed at offset:0x%x\n",
1134                        nv_offset);
1135                return err;
1136        }
1137
1138        err = asd_reset_flash(asd_ha);
1139        if (err) {
1140                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1141                return err;
1142        }
1143
1144        src_buf = (const u8 *)src;
1145        for (i = 0; i < bytes_to_write; i++) {
1146                /* Setup program command sequence */
1147                switch (asd_ha->hw_prof.flash.method) {
1148                case FLASH_METHOD_A:
1149                {
1150                        asd_write_reg_byte(asd_ha,
1151                                        (reg + 0xAAA), 0xAA);
1152                        asd_write_reg_byte(asd_ha,
1153                                        (reg + 0x555), 0x55);
1154                        asd_write_reg_byte(asd_ha,
1155                                        (reg + 0xAAA), 0xA0);
1156                        asd_write_reg_byte(asd_ha,
1157                                        (reg + nv_offset + i),
1158                                        (*(src_buf + i)));
1159                        break;
1160                }
1161                case FLASH_METHOD_B:
1162                {
1163                        asd_write_reg_byte(asd_ha,
1164                                        (reg + 0x555), 0xAA);
1165                        asd_write_reg_byte(asd_ha,
1166                                        (reg + 0x2AA), 0x55);
1167                        asd_write_reg_byte(asd_ha,
1168                                        (reg + 0x555), 0xA0);
1169                        asd_write_reg_byte(asd_ha,
1170                                        (reg + nv_offset + i),
1171                                        (*(src_buf + i)));
1172                        break;
1173                }
1174                default:
1175                        break;
1176                }
1177                if (asd_chk_write_status(asd_ha,
1178                                (nv_offset + i), 0) != 0) {
1179                        ASD_DPRINTK("aicx: Write failed at offset:0x%x\n",
1180                                reg + nv_offset + i);
1181                        return FAIL_WRITE_FLASH;
1182                }
1183        }
1184
1185        err = asd_reset_flash(asd_ha);
1186        if (err) {
1187                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1188                return err;
1189        }
1190        return 0;
1191}
1192
1193int asd_chk_write_status(struct asd_ha_struct *asd_ha,
1194         u32 sector_addr, u8 erase_flag)
1195{
1196        u32 reg;
1197        u32 loop_cnt;
1198        u8  nv_data1, nv_data2;
1199        u8  toggle_bit1;
1200
1201        /*
1202         * Read from DQ2 requires sector address
1203         * while it's dont care for DQ6
1204         */
1205        reg = asd_ha->hw_prof.flash.bar;
1206
1207        for (loop_cnt = 0; loop_cnt < 50000; loop_cnt++) {
1208                nv_data1 = asd_read_reg_byte(asd_ha, reg);
1209                nv_data2 = asd_read_reg_byte(asd_ha, reg);
1210
1211                toggle_bit1 = ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6)
1212                                 ^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ6));
1213
1214                if (toggle_bit1 == 0) {
1215                        return 0;
1216                } else {
1217                        if (nv_data2 & FLASH_STATUS_BIT_MASK_DQ5) {
1218                                nv_data1 = asd_read_reg_byte(asd_ha,
1219                                                                reg);
1220                                nv_data2 = asd_read_reg_byte(asd_ha,
1221                                                                reg);
1222                                toggle_bit1 =
1223                                ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6)
1224                                ^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ6));
1225
1226                                if (toggle_bit1 == 0)
1227                                        return 0;
1228                        }
1229                }
1230
1231                /*
1232                 * ERASE is a sector-by-sector operation and requires
1233                 * more time to finish while WRITE is byte-byte-byte
1234                 * operation and takes lesser time to finish.
1235                 *
1236                 * For some strange reason a reduced ERASE delay gives different
1237                 * behaviour across different spirit boards. Hence we set
1238                 * a optimum balance of 50mus for ERASE which works well
1239                 * across all boards.
1240                 */
1241                if (erase_flag) {
1242                        udelay(FLASH_STATUS_ERASE_DELAY_COUNT);
1243                } else {
1244                        udelay(FLASH_STATUS_WRITE_DELAY_COUNT);
1245                }
1246        }
1247        return -1;
1248}
1249
1250/**
1251 * asd_erase_nv_sector - Erase the flash memory sectors.
1252 * @asd_ha: pointer to the host adapter structure
1253 * @flash_addr: pointer to offset from flash memory
1254 * @size: total bytes to erase.
1255 */
1256int asd_erase_nv_sector(struct asd_ha_struct *asd_ha, u32 flash_addr, u32 size)
1257{
1258        u32 reg;
1259        u32 sector_addr;
1260
1261        reg = asd_ha->hw_prof.flash.bar;
1262
1263        /* sector staring address */
1264        sector_addr = flash_addr & FLASH_SECTOR_SIZE_MASK;
1265
1266        /*
1267         * Erasing an flash sector needs to be done in six consecutive
1268         * write cyles.
1269         */
1270        while (sector_addr < flash_addr+size) {
1271                switch (asd_ha->hw_prof.flash.method) {
1272                case FLASH_METHOD_A:
1273                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0xAA);
1274                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x55);
1275                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0x80);
1276                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0xAA);
1277                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x55);
1278                        asd_write_reg_byte(asd_ha, (reg + sector_addr), 0x30);
1279                        break;
1280                case FLASH_METHOD_B:
1281                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1282                        asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1283                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x80);
1284                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1285                        asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1286                        asd_write_reg_byte(asd_ha, (reg + sector_addr), 0x30);
1287                        break;
1288                default:
1289                        break;
1290                }
1291
1292                if (asd_chk_write_status(asd_ha, sector_addr, 1) != 0)
1293                        return FAIL_ERASE_FLASH;
1294
1295                sector_addr += FLASH_SECTOR_SIZE;
1296        }
1297
1298        return 0;
1299}
1300
1301int asd_check_flash_type(struct asd_ha_struct *asd_ha)
1302{
1303        u8 manuf_id;
1304        u8 dev_id;
1305        u8 sec_prot;
1306        u32 inc;
1307        u32 reg;
1308        int err;
1309
1310        /* get Flash memory base address */
1311        reg = asd_ha->hw_prof.flash.bar;
1312
1313        /* Determine flash info */
1314        err = asd_reset_flash(asd_ha);
1315        if (err) {
1316                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1317                return err;
1318        }
1319
1320        asd_ha->hw_prof.flash.method = FLASH_METHOD_UNKNOWN;
1321        asd_ha->hw_prof.flash.manuf = FLASH_MANUF_ID_UNKNOWN;
1322        asd_ha->hw_prof.flash.dev_id = FLASH_DEV_ID_UNKNOWN;
1323
1324        /* Get flash info. This would most likely be AMD Am29LV family flash.
1325         * First try the sequence for word mode.  It is the same as for
1326         * 008B (byte mode only), 160B (word mode) and 800D (word mode).
1327         */
1328        inc = asd_ha->hw_prof.flash.wide ? 2 : 1;
1329        asd_write_reg_byte(asd_ha, reg + 0xAAA, 0xAA);
1330        asd_write_reg_byte(asd_ha, reg + 0x555, 0x55);
1331        asd_write_reg_byte(asd_ha, reg + 0xAAA, 0x90);
1332        manuf_id = asd_read_reg_byte(asd_ha, reg);
1333        dev_id = asd_read_reg_byte(asd_ha, reg + inc);
1334        sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);
1335        /* Get out of autoselect mode. */
1336        err = asd_reset_flash(asd_ha);
1337        if (err) {
1338                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1339                return err;
1340        }
1341        ASD_DPRINTK("Flash MethodA manuf_id(0x%x) dev_id(0x%x) "
1342                "sec_prot(0x%x)\n", manuf_id, dev_id, sec_prot);
1343        err = asd_reset_flash(asd_ha);
1344        if (err != 0)
1345                return err;
1346
1347        switch (manuf_id) {
1348        case FLASH_MANUF_ID_AMD:
1349                switch (sec_prot) {
1350                case FLASH_DEV_ID_AM29LV800DT:
1351                case FLASH_DEV_ID_AM29LV640MT:
1352                case FLASH_DEV_ID_AM29F800B:
1353                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1354                        break;
1355                default:
1356                        break;
1357                }
1358                break;
1359        case FLASH_MANUF_ID_ST:
1360                switch (sec_prot) {
1361                case FLASH_DEV_ID_STM29W800DT:
1362                case FLASH_DEV_ID_STM29LV640:
1363                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1364                        break;
1365                default:
1366                        break;
1367                }
1368                break;
1369        case FLASH_MANUF_ID_FUJITSU:
1370                switch (sec_prot) {
1371                case FLASH_DEV_ID_MBM29LV800TE:
1372                case FLASH_DEV_ID_MBM29DL800TA:
1373                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1374                        break;
1375                }
1376                break;
1377        case FLASH_MANUF_ID_MACRONIX:
1378                switch (sec_prot) {
1379                case FLASH_DEV_ID_MX29LV800BT:
1380                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1381                        break;
1382                }
1383                break;
1384        }
1385
1386        if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN) {
1387                err = asd_reset_flash(asd_ha);
1388                if (err) {
1389                        ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1390                        return err;
1391                }
1392
1393                /* Issue Unlock sequence for AM29LV008BT */
1394                asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1395                asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1396                asd_write_reg_byte(asd_ha, (reg + 0x555), 0x90);
1397                manuf_id = asd_read_reg_byte(asd_ha, reg);
1398                dev_id = asd_read_reg_byte(asd_ha, reg + inc);
1399                sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);
1400
1401                ASD_DPRINTK("Flash MethodB manuf_id(0x%x) dev_id(0x%x) sec_prot"
1402                        "(0x%x)\n", manuf_id, dev_id, sec_prot);
1403
1404                err = asd_reset_flash(asd_ha);
1405                if (err != 0) {
1406                        ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1407                        return err;
1408                }
1409
1410                switch (manuf_id) {
1411                case FLASH_MANUF_ID_AMD:
1412                        switch (dev_id) {
1413                        case FLASH_DEV_ID_AM29LV008BT:
1414                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1415                                break;
1416                        default:
1417                                break;
1418                        }
1419                        break;
1420                case FLASH_MANUF_ID_ST:
1421                        switch (dev_id) {
1422                        case FLASH_DEV_ID_STM29008:
1423                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1424                                break;
1425                        default:
1426                                break;
1427                        }
1428                        break;
1429                case FLASH_MANUF_ID_FUJITSU:
1430                        switch (dev_id) {
1431                        case FLASH_DEV_ID_MBM29LV008TA:
1432                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1433                                break;
1434                        }
1435                        break;
1436                case FLASH_MANUF_ID_INTEL:
1437                        switch (dev_id) {
1438                        case FLASH_DEV_ID_I28LV00TAT:
1439                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1440                                break;
1441                        }
1442                        break;
1443                case FLASH_MANUF_ID_MACRONIX:
1444                        switch (dev_id) {
1445                        case FLASH_DEV_ID_I28LV00TAT:
1446                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1447                                break;
1448                        }
1449                        break;
1450                default:
1451                        return FAIL_FIND_FLASH_ID;
1452                }
1453        }
1454
1455        if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN)
1456              return FAIL_FIND_FLASH_ID;
1457
1458        asd_ha->hw_prof.flash.manuf = manuf_id;
1459        asd_ha->hw_prof.flash.dev_id = dev_id;
1460        asd_ha->hw_prof.flash.sec_prot = sec_prot;
1461        return 0;
1462}
1463