brintos

brintos / linux-shallow public Read only

0
0
Text · 35.8 KiB · 5def83c Raw
1463 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Aic94xx SAS/SATA driver access to shared data structures and memory4 * 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			0x0038#define	OCM_DE_WIN_DRVR			0x0139#define	OCM_DE_BIOS_CHIM		0x0240#define	OCM_DE_RAID_ENGN		0x0341#define	OCM_DE_BIOS_INTL		0x0442#define	OCM_DE_BIOS_CHIM_OSM		0x0543#define	OCM_DE_BIOS_CHIM_DYNAMIC	0x0644#define	OCM_DE_ADDC2C_RES0		0x0745#define	OCM_DE_ADDC2C_RES1		0x0846#define	OCM_DE_ADDC2C_RES2		0x0947#define	OCM_DE_ADDC2C_RES3		0x0A48 49#define OCM_INIT_DIR_ENTRIES	550/***************************************************************************51*  OCM directory default52***************************************************************************/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 default61***************************************************************************/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) segment109 * @asd_ha: pointer to the host adapter structure110 * @buffer: where to write the read data111 * @offs: offset into OCM where to read from112 * @size: how many bytes to read113 *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) segment154 * @asd_ha: pointer to the host adapter structure155 * @buffer: where to read the write data156 * @offs: offset into OCM to write to157 * @size: how many bytes to write158 *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  2195#define BC_BIOS_PRESENT   1196 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 void272asd_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 int294asd_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 structure335 */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			0xF0363 364#define ASD_FLASH_SIZE                  0x200000365#define FLASH_DIR_COOKIE                "*** ADAPTEC FLASH DIRECTORY *** "366#define FLASH_NEXT_ENTRY_OFFS		0x2000367#define FLASH_MAX_DIR_ENTRIES		32368 369#define FLASH_DE_TYPE_MASK              0x3FFFFFFF370#define FLASH_DE_MS                     0x120371#define FLASH_DE_CTRL_A_USER            0xE0372 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    0415#define MS_PHY_STATE_REPORTED   1416#define MS_PHY_STATE_HIDDEN     2417	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 0439static const char *asd_sb_type[] = {440	"unknown",441	"SGPIO",442	[2 ... 0x7F] = "unknown",443	[0x80] = "ADPT_I2C",444	[0x81 ... 0xFF] = "VENDOR_UNIQUExx"445};446#endif447 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 0456static 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#endif473 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 0490static 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#endif499 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 directory588 * @asd_ha: pointer to the host adapter structure589 * @flash_dir: pointer to flash directory structure590 *591 * If found, the flash directory segment will be copied to592 * @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 id707 * @start: void pointer to the first element in the linked list708 * @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 the712 * linked list entries's offset is from this pointer.713 * Some linked list entries use only the first id, in which case714 * 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 sector738 * @asd_ha: pointer to the host adapter structure739 * @manuf_sec: pointer to the manufacturing sector740 *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 cannot746 * 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_phys749 * merely specifies the number of phys the host adapter decided to750 * 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 2753 * are actually enabled (enabled by default, max number of phys754 * 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 sector851 * @asd_ha: pointer to the host adapter structure852 * @flash_dir: pointer to the flash directory853 */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 settings964 * @asd_ha: pointer to the host adapter structure965 * @flash_dir: pointer to the flash directory966 */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 memory1032 * @asd_ha: pointer to the host adapter structure1033 */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 memory1078 * @asd_ha: pointer to the host adapter structure1079 * @src: pointer to the source data to be verified1080 * @dest_offset: offset from flash memory1081 * @bytes_to_verify: total bytes to verify1082 */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 memory1109 * @asd_ha: pointer to the host adapter structure1110 * @src: pointer to the source data to be written1111 * @dest_offset: offset from flash memory1112 * @bytes_to_write: total bytes to write1113 */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 address1203	 * while it's dont care for DQ61204	 */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 requires1233		 * more time to finish while WRITE is byte-byte-byte1234		 * operation and takes lesser time to finish.1235		 *1236		 * For some strange reason a reduced ERASE delay gives different1237		 * behaviour across different spirit boards. Hence we set1238		 * a optimum balance of 50mus for ERASE which works well1239		 * 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 structure1253 * @flash_addr: pointer to offset from flash memory1254 * @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 consecutive1268	 * 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 for1326	 * 008B (byte mode only), 160B (word mode) and 800D (word mode).1327	 */1328	inc = asd_ha->hw_prof.flash.wide ? 2 : 1;1329	asd_write_reg_byte(asd_ha, reg + 0xAAA, 0xAA);1330	asd_write_reg_byte(asd_ha, reg + 0x555, 0x55);1331	asd_write_reg_byte(asd_ha, reg + 0xAAA, 0x90);1332	manuf_id = asd_read_reg_byte(asd_ha, reg);1333	dev_id = asd_read_reg_byte(asd_ha, reg + inc);1334	sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);1335	/* Get out of autoselect mode. */1336	err = asd_reset_flash(asd_ha);1337	if (err) {1338		ASD_DPRINTK("couldn't reset flash. err=%d\n", err);1339		return err;1340	}1341	ASD_DPRINTK("Flash MethodA manuf_id(0x%x) dev_id(0x%x) "1342		"sec_prot(0x%x)\n", manuf_id, dev_id, sec_prot);1343	err = asd_reset_flash(asd_ha);1344	if (err != 0)1345		return err;1346 1347	switch (manuf_id) {1348	case FLASH_MANUF_ID_AMD:1349		switch (sec_prot) {1350		case FLASH_DEV_ID_AM29LV800DT:1351		case FLASH_DEV_ID_AM29LV640MT:1352		case FLASH_DEV_ID_AM29F800B:1353			asd_ha->hw_prof.flash.method = FLASH_METHOD_A;1354			break;1355		default:1356			break;1357		}1358		break;1359	case FLASH_MANUF_ID_ST:1360		switch (sec_prot) {1361		case FLASH_DEV_ID_STM29W800DT:1362		case FLASH_DEV_ID_STM29LV640:1363			asd_ha->hw_prof.flash.method = FLASH_METHOD_A;1364			break;1365		default:1366			break;1367		}1368		break;1369	case FLASH_MANUF_ID_FUJITSU:1370		switch (sec_prot) {1371		case FLASH_DEV_ID_MBM29LV800TE:1372		case FLASH_DEV_ID_MBM29DL800TA:1373			asd_ha->hw_prof.flash.method = FLASH_METHOD_A;1374			break;1375		}1376		break;1377	case FLASH_MANUF_ID_MACRONIX:1378		switch (sec_prot) {1379		case FLASH_DEV_ID_MX29LV800BT:1380			asd_ha->hw_prof.flash.method = FLASH_METHOD_A;1381			break;1382		}1383		break;1384	}1385 1386	if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN) {1387		err = asd_reset_flash(asd_ha);1388		if (err) {1389			ASD_DPRINTK("couldn't reset flash. err=%d\n", err);1390			return err;1391		}1392 1393		/* Issue Unlock sequence for AM29LV008BT */1394		asd_write_reg_byte(asd_ha, (reg + 0x555), 0xAA);1395		asd_write_reg_byte(asd_ha, (reg + 0x2AA), 0x55);1396		asd_write_reg_byte(asd_ha, (reg + 0x555), 0x90);1397		manuf_id = asd_read_reg_byte(asd_ha, reg);1398		dev_id = asd_read_reg_byte(asd_ha, reg + inc);1399		sec_prot = asd_read_reg_byte(asd_ha, reg + inc + inc);1400 1401		ASD_DPRINTK("Flash MethodB manuf_id(0x%x) dev_id(0x%x) sec_prot"1402			"(0x%x)\n", manuf_id, dev_id, sec_prot);1403 1404		err = asd_reset_flash(asd_ha);1405		if (err != 0) {1406			ASD_DPRINTK("couldn't reset flash. err=%d\n", err);1407			return err;1408		}1409 1410		switch (manuf_id) {1411		case FLASH_MANUF_ID_AMD:1412			switch (dev_id) {1413			case FLASH_DEV_ID_AM29LV008BT:1414				asd_ha->hw_prof.flash.method = FLASH_METHOD_B;1415				break;1416			default:1417				break;1418			}1419			break;1420		case FLASH_MANUF_ID_ST:1421			switch (dev_id) {1422			case FLASH_DEV_ID_STM29008:1423				asd_ha->hw_prof.flash.method = FLASH_METHOD_B;1424				break;1425			default:1426				break;1427			}1428			break;1429		case FLASH_MANUF_ID_FUJITSU:1430			switch (dev_id) {1431			case FLASH_DEV_ID_MBM29LV008TA:1432				asd_ha->hw_prof.flash.method = FLASH_METHOD_B;1433				break;1434			}1435			break;1436		case FLASH_MANUF_ID_INTEL:1437			switch (dev_id) {1438			case FLASH_DEV_ID_I28LV00TAT:1439				asd_ha->hw_prof.flash.method = FLASH_METHOD_B;1440				break;1441			}1442			break;1443		case FLASH_MANUF_ID_MACRONIX:1444			switch (dev_id) {1445			case FLASH_DEV_ID_I28LV00TAT:1446				asd_ha->hw_prof.flash.method = FLASH_METHOD_B;1447				break;1448			}1449			break;1450		default:1451			return FAIL_FIND_FLASH_ID;1452		}1453	}1454 1455	if (asd_ha->hw_prof.flash.method == FLASH_METHOD_UNKNOWN)1456	      return FAIL_FIND_FLASH_ID;1457 1458	asd_ha->hw_prof.flash.manuf = manuf_id;1459	asd_ha->hw_prof.flash.dev_id = dev_id;1460	asd_ha->hw_prof.flash.sec_prot = sec_prot;1461	return 0;1462}1463