Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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