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