File Index
Files and directories
Sign in
FILE

aic94xx_sds.c

File preview with syntax highlighting.

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