module_init(spi_init);
module_exit(spi_cleanup);
static uint8_t get_flash_status(void)
{
uint32_t word, val;
uint8_t ret;
word = readw((void *)(spi_char.mem_virt+SPI_CTRL));
word |= SPI_CTRL_SCGO; /* set cycle */
word |= SPI_CTRL_ACS; /* Enable Atomic Cycle Sequence */
word |= SPI_CTRL_SPOP;
word &= ~SPI_CTRL_COP;
word = word | SPI_CTRL_OPMENU_RDSR<<SPI_CTRL_COP_SHIFT; /* read */
word &= ~SPI_CTRL_DBC;
word = word | 0x00<<SPI_CTRL_DBC_SHIFT; /* read count=1 */
word |= SPI_CTRL_DC;
/* check the status */
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));
while(val & SPI_STATUS_SCIP)
{
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));/* check the status */
}
writew(word, (void *)(spi_char.mem_virt+SPI_CTRL));
/* check the status */
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));
while(val & SPI_STATUS_SCIP)
{
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));/* check the status */
}
val = readl((void *)(spi_char.mem_virt+SPI_DATA0));
SPI_DBG("get_flash_status:%08x/n", val);
ret = (val&0xFF);
word = readw((void *)(spi_char.mem_virt+SPI_STATUS));
word |= SPI_STATUS_CDS; /* clear Cycle Done Status flag */
word |= SPI_STATUS_BAS; /* clear blocked flag */
writew(word, (void *)(spi_char.mem_virt+SPI_STATUS));
return (ret);
}
static uint8_t set_flash_status(uint8_t value)
{
uint32_t word, var, val;
var = value;
writel(var, (void *)(spi_char.mem_virt+SPI_DATA0));
word = readw((void *)(spi_char.mem_virt+SPI_CTRL));
word |= SPI_CTRL_SCGO; /* set cycle */
word |= SPI_CTRL_ACS; /* Enable Atomic Cycle Sequence */
word |= SPI_CTRL_SPOP;
word &= ~SPI_CTRL_COP;
word = word | SPI_CTRL_OPMENU_WRSR<<SPI_CTRL_COP_SHIFT; /* read */
word &= ~SPI_CTRL_DBC;
word = word | 0x00<<SPI_CTRL_DBC_SHIFT; /* write count=1 */
word |= SPI_CTRL_DC;
/* check the status */
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));
while(val & SPI_STATUS_SCIP)
{
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));/* check the status */
}
writew(word, (void *)(spi_char.mem_virt+SPI_CTRL));
/* check the status */
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));
while(val & SPI_STATUS_SCIP)
{
val = readw((void *)(spi_char.mem_virt+SPI_STATUS));/* check the status */
}
word = readw((void *)(spi_char.mem_virt+SPI_STATUS));
word |= SPI_STATUS_CDS; /* clear Cycle Done Status flag */
word |= SPI_STATUS_BAS; /* clear blocked flag */
writew(word, (void *)(spi_char.mem_virt+SPI_STATUS));
var = get_flash_status();
return (var);
}
static int is_bios_protection(void)
{
unsigned int ret;
ret = spi_char.bios_ctrl_addr & BIOS_NOPROTECTION;
return (!ret);
}
static int disable_bios_protection(void)
{
unsigned int temp;
struct pci_dev *pdev = NULL;
if(is_bios_protection())
{
temp = spi_char.bios_ctrl_addr | BIOS_NOPROTECTION;
pdev = pci_get_device(SPI_VENDOR_ID, SPI_DEVICE_ID, NULL);
if ( !pdev )
{
SPI_ERR("%s:spi_char_init-Could not find pci device/n", DRIVERNAME);
return (0);
}
pci_write_config_byte(pdev, BIOS_CTRL, temp);
spi_char.bios_ctrl_addr = temp;
//release reference to device
pci_dev_put(pdev);
}
return (1);
}
static int is_flash_protection(void)
{
unsigned int var;
var = get_flash_status();
var &= SPI_FLASH_PROTECTION;
if(var || is_bios_protection())
{
return (1);
}
return (0);
}
static int disable_flash_protection(void)
{
uint32_t word, var;
uint8_t ret1, ret2;
var = get_flash_status();
var &= ~SPI_FLASH_PROTECTION;
ret1 = set_flash_status(var);
ret2 = disable_bios_protection();
if(ret1 != var || !ret2)
{
return 0;
}
return (1);
} |