diff options
Diffstat (limited to 'meta-baldeagle/recipes-kernel/amd-spi/files')
4 files changed, 37 insertions, 115 deletions
diff --git a/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.c b/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.c index 6af2c6db..1ca9b69a 100644 --- a/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.c +++ b/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.c @@ -45,9 +45,9 @@ struct amd_spi { u32 rom_addr; struct spi_master *master; struct amd_platform_data controller_data; - spinlock_t lock; struct task_struct *kthread_spi; struct list_head msg_queue; + wait_queue_head_t wq; }; static struct pci_device_id amd_spi_pci_device_id[] = { @@ -155,7 +155,9 @@ static void amd_spi_execute_opcode(struct spi_master *master) spi_busy = (ioread32((u8 *)amd_spi->io_remap_addr + AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) == AMD_SPI_BUSY; while (spi_busy) { + set_current_state(TASK_INTERRUPTIBLE); schedule(); + set_current_state(TASK_RUNNING); spi_busy = (ioread32((u8 *)amd_spi->io_remap_addr + AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) == AMD_SPI_BUSY; } @@ -199,29 +201,17 @@ static int amd_spi_master_setup(struct spi_device *spi) return 0; } -static int amd_spi_master_transfer(struct spi_device *spi, +static int amd_spi_master_transfer(struct spi_master *master, struct spi_message *msg) { - struct spi_master *master = spi->master; struct amd_spi *amd_spi = spi_master_get_devdata(master); /* - * We will just add this message to the message queue set up by - * the controller, and let the kernel thread handle it later. - */ - msg->status = -EINPROGRESS; - msg->actual_length = 0; - msg->spi = spi; - /* - * There could be a situation when we are running on this processor - * and trying to add element to the end of the message queue, but - * at the same time the kernel thread is running on another processor - * and trying to find out if the list is empty or not. So protect - * against such contention. Simple spin_lock() should do. + * Add new message to the queue and let the kernel thread know + * about it. */ - spin_lock(&amd_spi->lock); list_add_tail(&msg->queue, &amd_spi->msg_queue); - spin_unlock(&amd_spi->lock); + wake_up_interruptible(&amd_spi->wq); return 0; } @@ -249,25 +239,19 @@ static int amd_spi_thread(void *t) * 4-bytes of data and 3-bytes of address. */ while (1) { - /* break condition */ + /* + * Let us wait on a wait queue till the message queue is empty. + */ + wait_event_interruptible(amd_spi->wq, + !list_empty(&amd_spi->msg_queue)); + + /* stop condition */ if (kthread_should_stop()) { set_current_state(TASK_RUNNING); break; } /* - * If the message queue is empty, then there is no need to waste - * CPU cycles. So we let other processes execute, and continue - * from the beginning of the loop when we next get to run. - */ - spin_lock(&amd_spi->lock); - if (list_empty(&amd_spi->msg_queue)) { - spin_unlock(&amd_spi->lock); - schedule(); - continue; - } - - /* * Else, pull the very first message from the queue and process * all transfers within that message. And process the messages * in a pure linear fashion. We also remove the spi_message @@ -276,7 +260,6 @@ static int amd_spi_thread(void *t) message = list_entry(amd_spi->msg_queue.next, struct spi_message, queue); list_del_init(&message->queue); - spin_unlock(&amd_spi->lock); /* We store the CS# line to be used for this spi_message */ amd_spi->controller_data.chip_select = @@ -396,7 +379,7 @@ static int amd_spi_thread(void *t) message->actual_length = tx_len + rx_len + 1; /* complete the transaction */ message->status = 0; - message->complete(message->context); + spi_finalize_current_message(master); } return 0; @@ -441,8 +424,8 @@ static int amd_spi_pci_probe(struct pci_dev *pdev, dev_dbg(dev, "io_base_addr: 0x%.8lx, io_remap_address: %p\n", amd_spi->io_base_addr, amd_spi->io_remap_addr); - spin_lock_init(&amd_spi->lock); INIT_LIST_HEAD(&amd_spi->msg_queue); + init_waitqueue_head(&amd_spi->wq); amd_spi->kthread_spi = kthread_run(amd_spi_thread, amd_spi, "amd_spi_thread"); @@ -455,7 +438,7 @@ static int amd_spi_pci_probe(struct pci_dev *pdev, master->mode_bits = 0; master->flags = 0; master->setup = amd_spi_master_setup; - master->transfer = amd_spi_master_transfer; + master->transfer_one_message = amd_spi_master_transfer; /* Register the controller with SPI framework */ err = spi_register_master(master); if (err) { diff --git a/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.h b/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.h index bc0bd6e8..b766d15c 100644 --- a/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.h +++ b/meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.h @@ -2,7 +2,7 @@ #define SPI_AMD_H #define DRIVER_NAME "spi_amd" -#define SPI_VERSION "0.1" +#define SPI_VERSION "1.0" #define PCI_DEVICE_ID_AMD_LPC_BRIDGE 0x780E diff --git a/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.c b/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.c index 99d28d31..4df6c70c 100644 --- a/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.c +++ b/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.c @@ -32,11 +32,13 @@ #include <linux/spi/spi.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/amd_imc.h> + #include <asm/uaccess.h> #include "spirom.h" -#define SPIROM_VERSION "0.1" +#define SPIROM_VERSION "0.2" /* * SPI has a character major number assigned. We allocate minor numbers @@ -52,7 +54,6 @@ #define SPI_BUS_CS1 0 static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG]; -static int imc_enabled; struct spirom_data { dev_t devt; @@ -84,7 +85,6 @@ spirom_sync(struct spirom_data *spirom, struct spi_message *message) { int status; - INIT_COMPLETION(spirom->done); message->complete = spirom_complete; message->context = &spirom->done; @@ -128,18 +128,6 @@ static int spirom_message(struct spirom_data *spirom, return -ENOMEM; transfer->tx_buf = buffer; - - /* - * In case IMC is enabled, and an erase or write operation is requested - * on the ROM, we simply print a message and return from here. Rather - * than letting the user corrupt his system never to boot again, it is - * better to play safe. - */ - if (imc_enabled && ((*buffer == ROM_CHIP_ERASE) || - (*buffer == ROM_SECTOR_ERASE) || (*buffer == ROM_BLOCK_ERASE) || - (*buffer == ROM_WRITE))) - return -EPERM; - transfer->len = 1; buffer += transfer->len; spi_message_add_tail(transfer, &msg); @@ -318,6 +306,14 @@ static int spirom_open(struct inode *inode, struct file *filp) mutex_unlock(&device_list_lock); + /* + * In case IMC is enabled, we need to inform IMC to stop + * fetching code from the BIOS ROM. We will inform IMC when + * it is safe to start fetching from ROM again once we are + * done with our SPI transactions. + */ + amd_imc_enter_scratch_ram(); + return status; } @@ -345,6 +341,14 @@ static int spirom_release(struct inode *inode, struct file *filp) } mutex_unlock(&device_list_lock); + /* + * In case IMC is enabled, we would have instructed IMC to stop + * fetching from ROM BIOS earlier in the code path. Now that we + * are done, we can safely inform IMC to start fetching from ROM + * again. + */ + amd_imc_exit_scratch_ram(); + return status; } @@ -396,57 +400,12 @@ static int spirom_probe(struct spi_device *spi) struct spirom_data *spirom; int status; unsigned long minor; - u32 val; - u8 *byte; - u32 imc_strap_status_phys; - void __iomem *imcstrapstatus; /* Allocate driver data */ spirom = kzalloc(sizeof(*spirom), GFP_KERNEL); if (!spirom) return -ENOMEM; - /* Locate ACPI MMIO Base Address */ - byte = (u8 *)&val; - - outb(AMD_PM_ACPI_MMIO_BASE0, AMD_IO_PM_INDEX_REG); - byte[0] = inb(AMD_IO_PM_DATA_REG); - outb(AMD_PM_ACPI_MMIO_BASE1, AMD_IO_PM_INDEX_REG); - byte[1] = inb(AMD_IO_PM_DATA_REG); - outb(AMD_PM_ACPI_MMIO_BASE2, AMD_IO_PM_INDEX_REG); - byte[2] = inb(AMD_IO_PM_DATA_REG); - outb(AMD_PM_ACPI_MMIO_BASE3, AMD_IO_PM_INDEX_REG); - byte[3] = inb(AMD_IO_PM_DATA_REG); - - /* Bits 31:13 is the actual ACPI MMIO Base Address */ - val &= AMD_ACPI_MMIO_ADDR_MASK; - - /* IMCStrapStatus is located at ACPI MMIO Base Address + 0xE80 */ - if (!request_mem_region_exclusive(val + AMD_IMC_STRAP_STATUS_OFFSET, - AMD_IMC_STRAP_STATUS_SIZE, "IMC Strap Status")) - pr_err("spirom: MMIO address 0x%04x already in use\n", val + - AMD_IMC_STRAP_STATUS_OFFSET); - - imc_strap_status_phys = val + AMD_IMC_STRAP_STATUS_OFFSET; - - imcstrapstatus = ioremap(imc_strap_status_phys, AMD_IMC_STRAP_STATUS_SIZE); - if (!imcstrapstatus) - pr_err("spirom: failed to map IMC Strap Status address\n"); - - /* Check if IMC is enabled */ - val = ioread32(imcstrapstatus); - if ((val & AMD_IMC_ENABLED) == AMD_IMC_ENABLED) { - pr_info("spirom: IMC is enabled\n"); - imc_enabled = 1; - } else { - pr_info("spirom: IMC is disabled\n"); - imc_enabled = 0; - } - - /* Release the region occupied by IMC Strap Status register */ - iounmap(imcstrapstatus); - release_mem_region(imc_strap_status_phys, AMD_IMC_STRAP_STATUS_SIZE); - /* Initialize the driver data */ spirom->spi = spi; spin_lock_init(&spirom->spi_lock); diff --git a/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.h b/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.h index fe142a31..1b0caafa 100644 --- a/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.h +++ b/meta-baldeagle/recipes-kernel/amd-spi/files/spirom.h @@ -39,24 +39,6 @@ struct spi_ioc_transfer { ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0) #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) -#ifdef __KERNEL__ - -/* IO port address for indirect access using the ACPI PM registers */ -#define AMD_IO_PM_INDEX_REG 0xCD6 -#define AMD_IO_PM_DATA_REG 0xCD7 - -#define AMD_PM_ACPI_MMIO_BASE0 0x24 -#define AMD_PM_ACPI_MMIO_BASE1 0x25 -#define AMD_PM_ACPI_MMIO_BASE2 0x26 -#define AMD_PM_ACPI_MMIO_BASE3 0x27 - -#define AMD_ACPI_MMIO_ADDR_MASK ~0x1FFF - -/* Offset of IMC Strap Status register in the ACPI MMIO region */ -#define AMD_IMC_STRAP_STATUS_OFFSET 0xE80 - #define AMD_IMC_ENABLED 0x4 -#define AMD_IMC_STRAP_STATUS_SIZE 4 - /* SPI ROM command codes */ #define ROM_WREN 0x06 #define ROM_WRDI 0x04 @@ -68,6 +50,4 @@ struct spi_ioc_transfer { #define ROM_READ 0x03 #define ROM_WRITE 0x02 -#endif /* __KERNEL__ */ - #endif /* SPIROM_H */ |