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        struct asd_ms_conn_desc conn_desc[0];
 521        struct asd_ms_node_desc node_desc[];
 522} __attribute__ ((packed));
 523
 524struct asd_ctrla_phy_entry {
 525        u8    sas_addr[SAS_ADDR_SIZE];
 526        u8    sas_link_rates;  /* max in hi bits, min in low bits */
 527        u8    flags;
 528        u8    sata_link_rates;
 529        u8    _r[5];
 530} __attribute__ ((packed));
 531
 532struct asd_ctrla_phy_settings {
 533        u8    id0;                /* P'h'y */
 534        u8    _r;
 535        u16   next;
 536        u8    num_phys;       /* number of PHYs in the PCI function */
 537        u8    _r2[3];
 538        struct asd_ctrla_phy_entry phy_ent[ASD_MAX_PHYS];
 539} __attribute__ ((packed));
 540
 541struct asd_ll_el {
 542        u8   id0;
 543        u8   id1;
 544        __le16  next;
 545        u8   something_here[];
 546} __attribute__ ((packed));
 547
 548static int asd_poll_flash(struct asd_ha_struct *asd_ha)
 549{
 550        int c;
 551        u8 d;
 552
 553        for (c = 5000; c > 0; c--) {
 554                d  = asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar);
 555                d ^= asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar);
 556                if (!d)
 557                        return 0;
 558                udelay(5);
 559        }
 560        return -ENOENT;
 561}
 562
 563static int asd_reset_flash(struct asd_ha_struct *asd_ha)
 564{
 565        int err;
 566
 567        err = asd_poll_flash(asd_ha);
 568        if (err)
 569                return err;
 570        asd_write_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar, FLASH_RESET);
 571        err = asd_poll_flash(asd_ha);
 572
 573        return err;
 574}
 575
 576static int asd_read_flash_seg(struct asd_ha_struct *asd_ha,
 577                              void *buffer, u32 offs, int size)
 578{
 579        asd_read_reg_string(asd_ha, buffer, asd_ha->hw_prof.flash.bar+offs,
 580                            size);
 581        return 0;
 582}
 583
 584/**
 585 * asd_find_flash_dir - finds and reads the flash directory
 586 * @asd_ha: pointer to the host adapter structure
 587 * @flash_dir: pointer to flash directory structure
 588 *
 589 * If found, the flash directory segment will be copied to
 590 * @flash_dir.  Return 1 if found, 0 if not.
 591 */
 592static int asd_find_flash_dir(struct asd_ha_struct *asd_ha,
 593                              struct asd_flash_dir *flash_dir)
 594{
 595        u32 v;
 596        for (v = 0; v < ASD_FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) {
 597                asd_read_flash_seg(asd_ha, flash_dir, v,
 598                                   sizeof(FLASH_DIR_COOKIE)-1);
 599                if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE,
 600                           sizeof(FLASH_DIR_COOKIE)-1) == 0) {
 601                        asd_ha->hw_prof.flash.dir_offs = v;
 602                        asd_read_flash_seg(asd_ha, flash_dir, v,
 603                                           sizeof(*flash_dir));
 604                        return 1;
 605                }
 606        }
 607        return 0;
 608}
 609
 610static int asd_flash_getid(struct asd_ha_struct *asd_ha)
 611{
 612        int err = 0;
 613        u32 reg;
 614
 615        reg = asd_read_reg_dword(asd_ha, EXSICNFGR);
 616
 617        if (pci_read_config_dword(asd_ha->pcidev, PCI_CONF_FLSH_BAR,
 618                                  &asd_ha->hw_prof.flash.bar)) {
 619                asd_printk("couldn't read PCI_CONF_FLSH_BAR of %s\n",
 620                           pci_name(asd_ha->pcidev));
 621                return -ENOENT;
 622        }
 623        asd_ha->hw_prof.flash.present = 1;
 624        asd_ha->hw_prof.flash.wide = reg & FLASHW ? 1 : 0;
 625        err = asd_reset_flash(asd_ha);
 626        if (err) {
 627                ASD_DPRINTK("couldn't reset flash(%d)\n", err);
 628                return err;
 629        }
 630        return 0;
 631}
 632
 633static u16 asd_calc_flash_chksum(u16 *p, int size)
 634{
 635        u16 chksum = 0;
 636
 637        while (size-- > 0)
 638                chksum += *p++;
 639
 640        return chksum;
 641}
 642
 643
 644static int asd_find_flash_de(struct asd_flash_dir *flash_dir, u32 entry_type,
 645                             u32 *offs, u32 *size)
 646{
 647        int i;
 648        struct asd_flash_de *de;
 649
 650        for (i = 0; i < FLASH_MAX_DIR_ENTRIES; i++) {
 651                u32 type = le32_to_cpu(flash_dir->dir_entry[i].type);
 652
 653                type &= FLASH_DE_TYPE_MASK;
 654                if (type == entry_type)
 655                        break;
 656        }
 657        if (i >= FLASH_MAX_DIR_ENTRIES)
 658                return -ENOENT;
 659        de = &flash_dir->dir_entry[i];
 660        *offs = le32_to_cpu(de->offs);
 661        *size = le32_to_cpu(de->pad_size);
 662        return 0;
 663}
 664
 665static int asd_validate_ms(struct asd_manuf_sec *ms)
 666{
 667        if (ms->sig[0] != 'S' || ms->sig[1] != 'M') {
 668                ASD_DPRINTK("manuf sec: no valid sig(%c%c)\n",
 669                            ms->sig[0], ms->sig[1]);
 670                return -ENOENT;
 671        }
 672        if (ms->maj != 0) {
 673                asd_printk("unsupported manuf. sector. major version:%x\n",
 674                           ms->maj);
 675                return -ENOENT;
 676        }
 677        ms->offs_next = le16_to_cpu((__force __le16) ms->offs_next);
 678        ms->chksum = le16_to_cpu((__force __le16) ms->chksum);
 679        ms->size = le16_to_cpu((__force __le16) ms->size);
 680
 681        if (asd_calc_flash_chksum((u16 *)ms, ms->size/2)) {
 682                asd_printk("failed manuf sector checksum\n");
 683        }
 684
 685        return 0;
 686}
 687
 688static int asd_ms_get_sas_addr(struct asd_ha_struct *asd_ha,
 689                               struct asd_manuf_sec *ms)
 690{
 691        memcpy(asd_ha->hw_prof.sas_addr, ms->sas_addr, SAS_ADDR_SIZE);
 692        return 0;
 693}
 694
 695static int asd_ms_get_pcba_sn(struct asd_ha_struct *asd_ha,
 696                              struct asd_manuf_sec *ms)
 697{
 698        memcpy(asd_ha->hw_prof.pcba_sn, ms->pcba_sn, ASD_PCBA_SN_SIZE);
 699        asd_ha->hw_prof.pcba_sn[ASD_PCBA_SN_SIZE] = '\0';
 700        return 0;
 701}
 702
 703/**
 704 * asd_find_ll_by_id - find a linked list entry by its id
 705 * @start: void pointer to the first element in the linked list
 706 * @id0: the first byte of the id  (offs 0)
 707 * @id1: the second byte of the id (offs 1)
 708 *
 709 * @start has to be the _base_ element start, since the
 710 * linked list entries's offset is from this pointer.
 711 * Some linked list entries use only the first id, in which case
 712 * you can pass 0xFF for the second.
 713 */
 714static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1)
 715{
 716        struct asd_ll_el *el = start;
 717
 718        do {
 719                switch (id1) {
 720                default:
 721                        if (el->id1 == id1)
 722                case 0xFF:
 723                                if (el->id0 == id0)
 724                                        return el;
 725                }
 726                el = start + le16_to_cpu(el->next);
 727        } while (el != start);
 728
 729        return NULL;
 730}
 731
 732/**
 733 * asd_ms_get_phy_params - get phy parameters from the manufacturing sector
 734 * @asd_ha: pointer to the host adapter structure
 735 * @manuf_sec: pointer to the manufacturing sector
 736 *
 737 * The manufacturing sector contans also the linked list of sub-segments,
 738 * since when it was read, its size was taken from the flash directory,
 739 * not from the structure size.
 740 *
 741 * HIDDEN phys do not count in the total count.  REPORTED phys cannot
 742 * be enabled but are reported and counted towards the total.
 743 * ENABLED phys are enabled by default and count towards the total.
 744 * The absolute total phy number is ASD_MAX_PHYS.  hw_prof->num_phys
 745 * merely specifies the number of phys the host adapter decided to
 746 * report.  E.g., it is possible for phys 0, 1 and 2 to be HIDDEN,
 747 * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED.
 748 * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2
 749 * are actually enabled (enabled by default, max number of phys
 750 * enableable in this case).
 751 */
 752static int asd_ms_get_phy_params(struct asd_ha_struct *asd_ha,
 753                                 struct asd_manuf_sec *manuf_sec)
 754{
 755        int i;
 756        int en_phys = 0;
 757        int rep_phys = 0;
 758        struct asd_manuf_phy_param *phy_param;
 759        struct asd_manuf_phy_param dflt_phy_param;
 760
 761        phy_param = asd_find_ll_by_id(manuf_sec, 'P', 'M');
 762        if (!phy_param) {
 763                ASD_DPRINTK("ms: no phy parameters found\n");
 764                ASD_DPRINTK("ms: Creating default phy parameters\n");
 765                dflt_phy_param.sig[0] = 'P';
 766                dflt_phy_param.sig[1] = 'M';
 767                dflt_phy_param.maj = 0;
 768                dflt_phy_param.min = 2;
 769                dflt_phy_param.num_phy_desc = 8;
 770                dflt_phy_param.phy_desc_size = sizeof(struct asd_manuf_phy_desc);
 771                for (i =0; i < ASD_MAX_PHYS; i++) {
 772                        dflt_phy_param.phy_desc[i].state = 0;
 773                        dflt_phy_param.phy_desc[i].phy_id = i;
 774                        dflt_phy_param.phy_desc[i].phy_control_0 = 0xf6;
 775                        dflt_phy_param.phy_desc[i].phy_control_1 = 0x10;
 776                        dflt_phy_param.phy_desc[i].phy_control_2 = 0x43;
 777                        dflt_phy_param.phy_desc[i].phy_control_3 = 0xeb;
 778                }
 779
 780                phy_param = &dflt_phy_param;
 781
 782        }
 783
 784        if (phy_param->maj != 0) {
 785                asd_printk("unsupported manuf. phy param major version:0x%x\n",
 786                           phy_param->maj);
 787                return -ENOENT;
 788        }
 789
 790        ASD_DPRINTK("ms: num_phy_desc: %d\n", phy_param->num_phy_desc);
 791        asd_ha->hw_prof.enabled_phys = 0;
 792        for (i = 0; i < phy_param->num_phy_desc; i++) {
 793                struct asd_manuf_phy_desc *pd = &phy_param->phy_desc[i];
 794                switch (pd->state & 0xF) {
 795                case MS_PHY_STATE_HIDDEN:
 796                        ASD_DPRINTK("ms: phy%d: HIDDEN\n", i);
 797                        continue;
 798                case MS_PHY_STATE_REPORTED:
 799                        ASD_DPRINTK("ms: phy%d: REPORTED\n", i);
 800                        asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 801                        rep_phys++;
 802                        continue;
 803                case MS_PHY_STATE_ENABLED:
 804                        ASD_DPRINTK("ms: phy%d: ENABLED\n", i);
 805                        asd_ha->hw_prof.enabled_phys |= (1 << i);
 806                        en_phys++;
 807                        break;
 808                }
 809                asd_ha->hw_prof.phy_desc[i].phy_control_0 = pd->phy_control_0;
 810                asd_ha->hw_prof.phy_desc[i].phy_control_1 = pd->phy_control_1;
 811                asd_ha->hw_prof.phy_desc[i].phy_control_2 = pd->phy_control_2;
 812                asd_ha->hw_prof.phy_desc[i].phy_control_3 = pd->phy_control_3;
 813        }
 814        asd_ha->hw_prof.max_phys = rep_phys + en_phys;
 815        asd_ha->hw_prof.num_phys = en_phys;
 816        ASD_DPRINTK("ms: max_phys:0x%x, num_phys:0x%x\n",
 817                    asd_ha->hw_prof.max_phys, asd_ha->hw_prof.num_phys);
 818        ASD_DPRINTK("ms: enabled_phys:0x%x\n", asd_ha->hw_prof.enabled_phys);
 819        return 0;
 820}
 821
 822static int asd_ms_get_connector_map(struct asd_ha_struct *asd_ha,
 823                                    struct asd_manuf_sec *manuf_sec)
 824{
 825        struct asd_ms_conn_map *cm;
 826
 827        cm = asd_find_ll_by_id(manuf_sec, 'M', 'C');
 828        if (!cm) {
 829                ASD_DPRINTK("ms: no connector map found\n");
 830                return 0;
 831        }
 832
 833        if (cm->maj != 0) {
 834                ASD_DPRINTK("ms: unsupported: connector map major version 0x%x"
 835                            "\n", cm->maj);
 836                return -ENOENT;
 837        }
 838
 839        /* XXX */
 840
 841        return 0;
 842}
 843
 844
 845/**
 846 * asd_process_ms - find and extract information from the manufacturing sector
 847 * @asd_ha: pointer to the host adapter structure
 848 * @flash_dir: pointer to the flash directory
 849 */
 850static int asd_process_ms(struct asd_ha_struct *asd_ha,
 851                          struct asd_flash_dir *flash_dir)
 852{
 853        int err;
 854        struct asd_manuf_sec *manuf_sec;
 855        u32 offs, size;
 856
 857        err = asd_find_flash_de(flash_dir, FLASH_DE_MS, &offs, &size);
 858        if (err) {
 859                ASD_DPRINTK("Couldn't find the manuf. sector\n");
 860                goto out;
 861        }
 862
 863        if (size == 0)
 864                goto out;
 865
 866        err = -ENOMEM;
 867        manuf_sec = kmalloc(size, GFP_KERNEL);
 868        if (!manuf_sec) {
 869                ASD_DPRINTK("no mem for manuf sector\n");
 870                goto out;
 871        }
 872
 873        err = asd_read_flash_seg(asd_ha, (void *)manuf_sec, offs, size);
 874        if (err) {
 875                ASD_DPRINTK("couldn't read manuf sector at 0x%x, size 0x%x\n",
 876                            offs, size);
 877                goto out2;
 878        }
 879
 880        err = asd_validate_ms(manuf_sec);
 881        if (err) {
 882                ASD_DPRINTK("couldn't validate manuf sector\n");
 883                goto out2;
 884        }
 885
 886        err = asd_ms_get_sas_addr(asd_ha, manuf_sec);
 887        if (err) {
 888                ASD_DPRINTK("couldn't read the SAS_ADDR\n");
 889                goto out2;
 890        }
 891        ASD_DPRINTK("manuf sect SAS_ADDR %llx\n",
 892                    SAS_ADDR(asd_ha->hw_prof.sas_addr));
 893
 894        err = asd_ms_get_pcba_sn(asd_ha, manuf_sec);
 895        if (err) {
 896                ASD_DPRINTK("couldn't read the PCBA SN\n");
 897                goto out2;
 898        }
 899        ASD_DPRINTK("manuf sect PCBA SN %s\n", asd_ha->hw_prof.pcba_sn);
 900
 901        err = asd_ms_get_phy_params(asd_ha, manuf_sec);
 902        if (err) {
 903                ASD_DPRINTK("ms: couldn't get phy parameters\n");
 904                goto out2;
 905        }
 906
 907        err = asd_ms_get_connector_map(asd_ha, manuf_sec);
 908        if (err) {
 909                ASD_DPRINTK("ms: couldn't get connector map\n");
 910                goto out2;
 911        }
 912
 913out2:
 914        kfree(manuf_sec);
 915out:
 916        return err;
 917}
 918
 919static int asd_process_ctrla_phy_settings(struct asd_ha_struct *asd_ha,
 920                                          struct asd_ctrla_phy_settings *ps)
 921{
 922        int i;
 923        for (i = 0; i < ps->num_phys; i++) {
 924                struct asd_ctrla_phy_entry *pe = &ps->phy_ent[i];
 925
 926                if (!PHY_ENABLED(asd_ha, i))
 927                        continue;
 928                if (*(u64 *)pe->sas_addr == 0) {
 929                        asd_ha->hw_prof.enabled_phys &= ~(1 << i);
 930                        continue;
 931                }
 932                /* This is the SAS address which should be sent in IDENTIFY. */
 933                memcpy(asd_ha->hw_prof.phy_desc[i].sas_addr, pe->sas_addr,
 934                       SAS_ADDR_SIZE);
 935                asd_ha->hw_prof.phy_desc[i].max_sas_lrate =
 936                        (pe->sas_link_rates & 0xF0) >> 4;
 937                asd_ha->hw_prof.phy_desc[i].min_sas_lrate =
 938                        (pe->sas_link_rates & 0x0F);
 939                asd_ha->hw_prof.phy_desc[i].max_sata_lrate =
 940                        (pe->sata_link_rates & 0xF0) >> 4;
 941                asd_ha->hw_prof.phy_desc[i].min_sata_lrate =
 942                        (pe->sata_link_rates & 0x0F);
 943                asd_ha->hw_prof.phy_desc[i].flags = pe->flags;
 944                ASD_DPRINTK("ctrla: phy%d: sas_addr: %llx, sas rate:0x%x-0x%x,"
 945                            " sata rate:0x%x-0x%x, flags:0x%x\n",
 946                            i,
 947                            SAS_ADDR(asd_ha->hw_prof.phy_desc[i].sas_addr),
 948                            asd_ha->hw_prof.phy_desc[i].max_sas_lrate,
 949                            asd_ha->hw_prof.phy_desc[i].min_sas_lrate,
 950                            asd_ha->hw_prof.phy_desc[i].max_sata_lrate,
 951                            asd_ha->hw_prof.phy_desc[i].min_sata_lrate,
 952                            asd_ha->hw_prof.phy_desc[i].flags);
 953        }
 954
 955        return 0;
 956}
 957
 958/**
 959 * asd_process_ctrl_a_user - process CTRL-A user settings
 960 * @asd_ha: pointer to the host adapter structure
 961 * @flash_dir: pointer to the flash directory
 962 */
 963static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha,
 964                                   struct asd_flash_dir *flash_dir)
 965{
 966        int err, i;
 967        u32 offs, size;
 968        struct asd_ll_el *el = NULL;
 969        struct asd_ctrla_phy_settings *ps;
 970        struct asd_ctrla_phy_settings dflt_ps;
 971
 972        err = asd_find_flash_de(flash_dir, FLASH_DE_CTRL_A_USER, &offs, &size);
 973        if (err) {
 974                ASD_DPRINTK("couldn't find CTRL-A user settings section\n");
 975                ASD_DPRINTK("Creating default CTRL-A user settings section\n");
 976
 977                dflt_ps.id0 = 'h';
 978                dflt_ps.num_phys = 8;
 979                for (i =0; i < ASD_MAX_PHYS; i++) {
 980                        memcpy(dflt_ps.phy_ent[i].sas_addr,
 981                               asd_ha->hw_prof.sas_addr, SAS_ADDR_SIZE);
 982                        dflt_ps.phy_ent[i].sas_link_rates = 0x98;
 983                        dflt_ps.phy_ent[i].flags = 0x0;
 984                        dflt_ps.phy_ent[i].sata_link_rates = 0x0;
 985                }
 986
 987                size = sizeof(struct asd_ctrla_phy_settings);
 988                ps = &dflt_ps;
 989                goto out_process;
 990        }
 991
 992        if (size == 0)
 993                goto out;
 994
 995        err = -ENOMEM;
 996        el = kmalloc(size, GFP_KERNEL);
 997        if (!el) {
 998                ASD_DPRINTK("no mem for ctrla user settings section\n");
 999                goto out;
1000        }
1001
1002        err = asd_read_flash_seg(asd_ha, (void *)el, offs, size);
1003        if (err) {
1004                ASD_DPRINTK("couldn't read ctrla phy settings section\n");
1005                goto out2;
1006        }
1007
1008        err = -ENOENT;
1009        ps = asd_find_ll_by_id(el, 'h', 0xFF);
1010        if (!ps) {
1011                ASD_DPRINTK("couldn't find ctrla phy settings struct\n");
1012                goto out2;
1013        }
1014out_process:
1015        err = asd_process_ctrla_phy_settings(asd_ha, ps);
1016        if (err) {
1017                ASD_DPRINTK("couldn't process ctrla phy settings\n");
1018                goto out2;
1019        }
1020out2:
1021        kfree(el);
1022out:
1023        return err;
1024}
1025
1026/**
1027 * asd_read_flash - read flash memory
1028 * @asd_ha: pointer to the host adapter structure
1029 */
1030int asd_read_flash(struct asd_ha_struct *asd_ha)
1031{
1032        int err;
1033        struct asd_flash_dir *flash_dir;
1034
1035        err = asd_flash_getid(asd_ha);
1036        if (err)
1037                return err;
1038
1039        flash_dir = kmalloc(sizeof(*flash_dir), GFP_KERNEL);
1040        if (!flash_dir)
1041                return -ENOMEM;
1042
1043        err = -ENOENT;
1044        if (!asd_find_flash_dir(asd_ha, flash_dir)) {
1045                ASD_DPRINTK("couldn't find flash directory\n");
1046                goto out;
1047        }
1048
1049        if (le32_to_cpu(flash_dir->rev) != 2) {
1050                asd_printk("unsupported flash dir version:0x%x\n",
1051                           le32_to_cpu(flash_dir->rev));
1052                goto out;
1053        }
1054
1055        err = asd_process_ms(asd_ha, flash_dir);
1056        if (err) {
1057                ASD_DPRINTK("couldn't process manuf sector settings\n");
1058                goto out;
1059        }
1060
1061        err = asd_process_ctrl_a_user(asd_ha, flash_dir);
1062        if (err) {
1063                ASD_DPRINTK("couldn't process CTRL-A user settings\n");
1064                goto out;
1065        }
1066
1067out:
1068        kfree(flash_dir);
1069        return err;
1070}
1071
1072/**
1073 * asd_verify_flash_seg - verify data with flash memory
1074 * @asd_ha: pointer to the host adapter structure
1075 * @src: pointer to the source data to be verified
1076 * @dest_offset: offset from flash memory
1077 * @bytes_to_verify: total bytes to verify
1078 */
1079int asd_verify_flash_seg(struct asd_ha_struct *asd_ha,
1080                         const void *src, u32 dest_offset, u32 bytes_to_verify)
1081{
1082        const u8 *src_buf;
1083        u8 flash_char;
1084        int err;
1085        u32 nv_offset, reg, i;
1086
1087        reg = asd_ha->hw_prof.flash.bar;
1088        src_buf = NULL;
1089
1090        err = FLASH_OK;
1091        nv_offset = dest_offset;
1092        src_buf = (const u8 *)src;
1093        for (i = 0; i < bytes_to_verify; i++) {
1094                flash_char = asd_read_reg_byte(asd_ha, reg + nv_offset + i);
1095                if (flash_char != src_buf[i]) {
1096                        err = FAIL_VERIFY;
1097                        break;
1098                }
1099        }
1100        return err;
1101}
1102
1103/**
1104 * asd_write_flash_seg - write data into flash memory
1105 * @asd_ha: pointer to the host adapter structure
1106 * @src: pointer to the source data to be written
1107 * @dest_offset: offset from flash memory
1108 * @bytes_to_write: total bytes to write
1109 */
1110int asd_write_flash_seg(struct asd_ha_struct *asd_ha,
1111                        const void *src, u32 dest_offset, u32 bytes_to_write)
1112{
1113        const u8 *src_buf;
1114        u32 nv_offset, reg, i;
1115        int err;
1116
1117        reg = asd_ha->hw_prof.flash.bar;
1118        src_buf = NULL;
1119
1120        err = asd_check_flash_type(asd_ha);
1121        if (err) {
1122                ASD_DPRINTK("couldn't find the type of flash. err=%d\n", err);
1123                return err;
1124        }
1125
1126        nv_offset = dest_offset;
1127        err = asd_erase_nv_sector(asd_ha, nv_offset, bytes_to_write);
1128        if (err) {
1129                ASD_DPRINTK("Erase failed at offset:0x%x\n",
1130                        nv_offset);
1131                return err;
1132        }
1133
1134        err = asd_reset_flash(asd_ha);
1135        if (err) {
1136                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1137                return err;
1138        }
1139
1140        src_buf = (const u8 *)src;
1141        for (i = 0; i < bytes_to_write; i++) {
1142                /* Setup program command sequence */
1143                switch (asd_ha->hw_prof.flash.method) {
1144                case FLASH_METHOD_A:
1145                {
1146                        asd_write_reg_byte(asd_ha,
1147                                        (reg + 0xAAA), 0xAA);
1148                        asd_write_reg_byte(asd_ha,
1149                                        (reg + 0x555), 0x55);
1150                        asd_write_reg_byte(asd_ha,
1151                                        (reg + 0xAAA), 0xA0);
1152                        asd_write_reg_byte(asd_ha,
1153                                        (reg + nv_offset + i),
1154                                        (*(src_buf + i)));
1155                        break;
1156                }
1157                case FLASH_METHOD_B:
1158                {
1159                        asd_write_reg_byte(asd_ha,
1160                                        (reg + 0x555), 0xAA);
1161                        asd_write_reg_byte(asd_ha,
1162                                        (reg + 0x2AA), 0x55);
1163                        asd_write_reg_byte(asd_ha,
1164                                        (reg + 0x555), 0xA0);
1165                        asd_write_reg_byte(asd_ha,
1166                                        (reg + nv_offset + i),
1167                                        (*(src_buf + i)));
1168                        break;
1169                }
1170                default:
1171                        break;
1172                }
1173                if (asd_chk_write_status(asd_ha,
1174                                (nv_offset + i), 0) != 0) {
1175                        ASD_DPRINTK("aicx: Write failed at offset:0x%x\n",
1176                                reg + nv_offset + i);
1177                        return FAIL_WRITE_FLASH;
1178                }
1179        }
1180
1181        err = asd_reset_flash(asd_ha);
1182        if (err) {
1183                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1184                return err;
1185        }
1186        return 0;
1187}
1188
1189int asd_chk_write_status(struct asd_ha_struct *asd_ha,
1190         u32 sector_addr, u8 erase_flag)
1191{
1192        u32 reg;
1193        u32 loop_cnt;
1194        u8  nv_data1, nv_data2;
1195        u8  toggle_bit1;
1196
1197        /*
1198         * Read from DQ2 requires sector address
1199         * while it's dont care for DQ6
1200         */
1201        reg = asd_ha->hw_prof.flash.bar;
1202
1203        for (loop_cnt = 0; loop_cnt < 50000; loop_cnt++) {
1204                nv_data1 = asd_read_reg_byte(asd_ha, reg);
1205                nv_data2 = asd_read_reg_byte(asd_ha, reg);
1206
1207                toggle_bit1 = ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6)
1208                                 ^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ6));
1209
1210                if (toggle_bit1 == 0) {
1211                        return 0;
1212                } else {
1213                        if (nv_data2 & FLASH_STATUS_BIT_MASK_DQ5) {
1214                                nv_data1 = asd_read_reg_byte(asd_ha,
1215                                                                reg);
1216                                nv_data2 = asd_read_reg_byte(asd_ha,
1217                                                                reg);
1218                                toggle_bit1 =
1219                                ((nv_data1 & FLASH_STATUS_BIT_MASK_DQ6)
1220                                ^ (nv_data2 & FLASH_STATUS_BIT_MASK_DQ6));
1221
1222                                if (toggle_bit1 == 0)
1223                                        return 0;
1224                        }
1225                }
1226
1227                /*
1228                 * ERASE is a sector-by-sector operation and requires
1229                 * more time to finish while WRITE is byte-byte-byte
1230                 * operation and takes lesser time to finish.
1231                 *
1232                 * For some strange reason a reduced ERASE delay gives different
1233                 * behaviour across different spirit boards. Hence we set
1234                 * a optimum balance of 50mus for ERASE which works well
1235                 * across all boards.
1236                 */
1237                if (erase_flag) {
1238                        udelay(FLASH_STATUS_ERASE_DELAY_COUNT);
1239                } else {
1240                        udelay(FLASH_STATUS_WRITE_DELAY_COUNT);
1241                }
1242        }
1243        return -1;
1244}
1245
1246/**
1247 * asd_hwi_erase_nv_sector - Erase the flash memory sectors.
1248 * @asd_ha: pointer to the host adapter structure
1249 * @flash_addr: pointer to offset from flash memory
1250 * @size: total bytes to erase.
1251 */
1252int asd_erase_nv_sector(struct asd_ha_struct *asd_ha, u32 flash_addr, u32 size)
1253{
1254        u32 reg;
1255        u32 sector_addr;
1256
1257        reg = asd_ha->hw_prof.flash.bar;
1258
1259        /* sector staring address */
1260        sector_addr = flash_addr & FLASH_SECTOR_SIZE_MASK;
1261
1262        /*
1263         * Erasing an flash sector needs to be done in six consecutive
1264         * write cyles.
1265         */
1266        while (sector_addr < flash_addr+size) {
1267                switch (asd_ha->hw_prof.flash.method) {
1268                case FLASH_METHOD_A:
1269                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0xAA);
1270                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x55);
1271                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0x80);
1272                        asd_write_reg_byte(asd_ha, (reg + 0xAAA), 0xAA);
1273                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x55);
1274                        asd_write_reg_byte(asd_ha, (reg + sector_addr), 0x30);
1275                        break;
1276                case FLASH_METHOD_B:
1277                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1278                        asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1279                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0x80);
1280                        asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1281                        asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1282                        asd_write_reg_byte(asd_ha, (reg + sector_addr), 0x30);
1283                        break;
1284                default:
1285                        break;
1286                }
1287
1288                if (asd_chk_write_status(asd_ha, sector_addr, 1) != 0)
1289                        return FAIL_ERASE_FLASH;
1290
1291                sector_addr += FLASH_SECTOR_SIZE;
1292        }
1293
1294        return 0;
1295}
1296
1297int asd_check_flash_type(struct asd_ha_struct *asd_ha)
1298{
1299        u8 manuf_id;
1300        u8 dev_id;
1301        u8 sec_prot;
1302        u32 inc;
1303        u32 reg;
1304        int err;
1305
1306        /* get Flash memory base address */
1307        reg = asd_ha->hw_prof.flash.bar;
1308
1309        /* Determine flash info */
1310        err = asd_reset_flash(asd_ha);
1311        if (err) {
1312                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1313                return err;
1314        }
1315
1316        asd_ha->hw_prof.flash.method = FLASH_METHOD_UNKNOWN;
1317        asd_ha->hw_prof.flash.manuf = FLASH_MANUF_ID_UNKNOWN;
1318        asd_ha->hw_prof.flash.dev_id = FLASH_DEV_ID_UNKNOWN;
1319
1320        /* Get flash info. This would most likely be AMD Am29LV family flash.
1321         * First try the sequence for word mode.  It is the same as for
1322         * 008B (byte mode only), 160B (word mode) and 800D (word mode).
1323         */
1324        inc = asd_ha->hw_prof.flash.wide ? 2 : 1;
1325        asd_write_reg_byte(asd_ha, reg + 0xAAA, 0xAA);
1326        asd_write_reg_byte(asd_ha, reg + 0x555, 0x55);
1327        asd_write_reg_byte(asd_ha, reg + 0xAAA, 0x90);
1328        manuf_id = asd_read_reg_byte(asd_ha, reg);
1329        dev_id = asd_read_reg_byte(asd_ha, reg + inc);
1330        sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);
1331        /* Get out of autoselect mode. */
1332        err = asd_reset_flash(asd_ha);
1333        if (err) {
1334                ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1335                return err;
1336        }
1337        ASD_DPRINTK("Flash MethodA manuf_id(0x%x) dev_id(0x%x) "
1338                "sec_prot(0x%x)\n", manuf_id, dev_id, sec_prot);
1339        err = asd_reset_flash(asd_ha);
1340        if (err != 0)
1341                return err;
1342
1343        switch (manuf_id) {
1344        case FLASH_MANUF_ID_AMD:
1345                switch (sec_prot) {
1346                case FLASH_DEV_ID_AM29LV800DT:
1347                case FLASH_DEV_ID_AM29LV640MT:
1348                case FLASH_DEV_ID_AM29F800B:
1349                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1350                        break;
1351                default:
1352                        break;
1353                }
1354                break;
1355        case FLASH_MANUF_ID_ST:
1356                switch (sec_prot) {
1357                case FLASH_DEV_ID_STM29W800DT:
1358                case FLASH_DEV_ID_STM29LV640:
1359                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1360                        break;
1361                default:
1362                        break;
1363                }
1364                break;
1365        case FLASH_MANUF_ID_FUJITSU:
1366                switch (sec_prot) {
1367                case FLASH_DEV_ID_MBM29LV800TE:
1368                case FLASH_DEV_ID_MBM29DL800TA:
1369                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1370                        break;
1371                }
1372                break;
1373        case FLASH_MANUF_ID_MACRONIX:
1374                switch (sec_prot) {
1375                case FLASH_DEV_ID_MX29LV800BT:
1376                        asd_ha->hw_prof.flash.method = FLASH_METHOD_A;
1377                        break;
1378                }
1379                break;
1380        }
1381
1382        if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN) {
1383                err = asd_reset_flash(asd_ha);
1384                if (err) {
1385                        ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1386                        return err;
1387                }
1388
1389                /* Issue Unlock sequence for AM29LV008BT */
1390                asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);
1391                asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);
1392                asd_write_reg_byte(asd_ha, (reg + 0x555), 0x90);
1393                manuf_id = asd_read_reg_byte(asd_ha, reg);
1394                dev_id = asd_read_reg_byte(asd_ha, reg + inc);
1395                sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);
1396
1397                ASD_DPRINTK("Flash MethodB manuf_id(0x%x) dev_id(0x%x) sec_prot"
1398                        "(0x%x)\n", manuf_id, dev_id, sec_prot);
1399
1400                err = asd_reset_flash(asd_ha);
1401                if (err != 0) {
1402                        ASD_DPRINTK("couldn't reset flash. err=%d\n", err);
1403                        return err;
1404                }
1405
1406                switch (manuf_id) {
1407                case FLASH_MANUF_ID_AMD:
1408                        switch (dev_id) {
1409                        case FLASH_DEV_ID_AM29LV008BT:
1410                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1411                                break;
1412                        default:
1413                                break;
1414                        }
1415                        break;
1416                case FLASH_MANUF_ID_ST:
1417                        switch (dev_id) {
1418                        case FLASH_DEV_ID_STM29008:
1419                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1420                                break;
1421                        default:
1422                                break;
1423                        }
1424                        break;
1425                case FLASH_MANUF_ID_FUJITSU:
1426                        switch (dev_id) {
1427                        case FLASH_DEV_ID_MBM29LV008TA:
1428                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1429                                break;
1430                        }
1431                        break;
1432                case FLASH_MANUF_ID_INTEL:
1433                        switch (dev_id) {
1434                        case FLASH_DEV_ID_I28LV00TAT:
1435                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1436                                break;
1437                        }
1438                        break;
1439                case FLASH_MANUF_ID_MACRONIX:
1440                        switch (dev_id) {
1441                        case FLASH_DEV_ID_I28LV00TAT:
1442                                asd_ha->hw_prof.flash.method = FLASH_METHOD_B;
1443                                break;
1444                        }
1445                        break;
1446                default:
1447                        return FAIL_FIND_FLASH_ID;
1448                }
1449        }
1450
1451        if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN)
1452              return FAIL_FIND_FLASH_ID;
1453
1454        asd_ha->hw_prof.flash.manuf = manuf_id;
1455        asd_ha->hw_prof.flash.dev_id = dev_id;
1456        asd_ha->hw_prof.flash.sec_prot = sec_prot;
1457        return 0;
1458}
1459