aboutsummaryrefslogtreecommitdiffstats
path: root/meta-baldeagle/recipes-kernel/amd-spi/files
diff options
context:
space:
mode:
Diffstat (limited to 'meta-baldeagle/recipes-kernel/amd-spi/files')
-rw-r--r--meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.c51
-rw-r--r--meta-baldeagle/recipes-kernel/amd-spi/files/spi_amd.h2
-rw-r--r--meta-baldeagle/recipes-kernel/amd-spi/files/spirom.c79
-rw-r--r--meta-baldeagle/recipes-kernel/amd-spi/files/spirom.h20
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 */