cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

aic94xx_sds.c (36692B)


      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}