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