aboutsummaryrefslogtreecommitdiffstats
path: root/meta-v1000
diff options
context:
space:
mode:
Diffstat (limited to 'meta-v1000')
-rw-r--r--meta-v1000/recipes-kernel/amd-spi/amd-spi_1.0.bb16
-rw-r--r--meta-v1000/recipes-kernel/amd-spi/files/Makefile14
-rw-r--r--meta-v1000/recipes-kernel/amd-spi/files/spi_amd.c479
-rw-r--r--meta-v1000/recipes-kernel/amd-spi/files/spi_amd.h28
-rw-r--r--meta-v1000/recipes-kernel/amd-spi/files/spirom.c519
-rw-r--r--meta-v1000/recipes-kernel/amd-spi/files/spirom.h53
6 files changed, 0 insertions, 1109 deletions
diff --git a/meta-v1000/recipes-kernel/amd-spi/amd-spi_1.0.bb b/meta-v1000/recipes-kernel/amd-spi/amd-spi_1.0.bb
deleted file mode 100644
index b23e5ce6..00000000
--- a/meta-v1000/recipes-kernel/amd-spi/amd-spi_1.0.bb
+++ /dev/null
@@ -1,16 +0,0 @@
-DESCRIPTION = "This kernel module provides support for AMD SPI controller driver"
-LICENSE = "BSD | GPLv2"
-LIC_FILES_CHKSUM = "file://spi_amd.c;endline=29;md5=e9fdf6da58412e619d89ec9e135a1be3"
-
-inherit module
-
-SRC_URI = "file://Makefile \
- file://spi_amd.c \
- file://spi_amd.h \
- file://spirom.c \
- file://spirom.h \
- "
-
-S = "${WORKDIR}"
-
-# The inherit of module.bbclass will take care of the rest
diff --git a/meta-v1000/recipes-kernel/amd-spi/files/Makefile b/meta-v1000/recipes-kernel/amd-spi/files/Makefile
deleted file mode 100644
index f778a69a..00000000
--- a/meta-v1000/recipes-kernel/amd-spi/files/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-obj-m := spi_amd.o spirom.o
-
-SRC := $(shell pwd)
-
-all:
- $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
-
-modules_install:
- $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
-
-clean:
- rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
- rm -f Module.markers Module.symvers modules.order
- rm -rf .tmp_versions Modules.symvers
diff --git a/meta-v1000/recipes-kernel/amd-spi/files/spi_amd.c b/meta-v1000/recipes-kernel/amd-spi/files/spi_amd.c
deleted file mode 100644
index 998d9ea6..00000000
--- a/meta-v1000/recipes-kernel/amd-spi/files/spi_amd.c
+++ /dev/null
@@ -1,479 +0,0 @@
-/*****************************************************************************
-*
-* Copyright (c) 2013, Advanced Micro Devices, Inc.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* * Neither the name of Advanced Micro Devices, Inc. nor the names of
-* its contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
-* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-*
-***************************************************************************/
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/spi/spi.h>
-#include <linux/kthread.h>
-
-#include "spi_amd.h"
-
-struct amd_platform_data {
- u8 chip_select;
-};
-
-struct amd_spi {
- void __iomem *io_remap_addr;
- unsigned long io_base_addr;
- u32 rom_addr;
- struct spi_master *master;
- struct amd_platform_data controller_data;
- 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[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LPC_BRIDGE) },
- {}
-};
-MODULE_DEVICE_TABLE(pci, amd_spi_pci_device_id);
-
-static inline u8 amd_spi_readreg8(struct spi_master *master, int idx)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
-
- return ioread8((u8 *)amd_spi->io_remap_addr + idx);
-}
-
-static inline void amd_spi_writereg8(struct spi_master *master, int idx,
- u8 val)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
-
- iowrite8(val, ((u8 *)amd_spi->io_remap_addr + idx));
-}
-
-static inline void amd_spi_setclear_reg8(struct spi_master *master, int idx,
- u8 set, u8 clear)
-{
- u8 tmp = amd_spi_readreg8(master, idx);
- tmp = (tmp & ~clear) | set;
- amd_spi_writereg8(master, idx, tmp);
-}
-
-static inline u32 amd_spi_readreg32(struct spi_master *master, int idx)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
-
- return ioread32((u8 *)amd_spi->io_remap_addr + idx);
-}
-
-static inline void amd_spi_writereg32(struct spi_master *master, int idx,
- u32 val)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
-
- iowrite32(val, ((u8 *)amd_spi->io_remap_addr + idx));
-}
-
-static inline void amd_spi_setclear_reg32(struct spi_master *master, int idx,
- u32 set, u32 clear)
-{
- u32 tmp = amd_spi_readreg32(master, idx);
- tmp = (tmp & ~clear) | set;
- amd_spi_writereg32(master, idx, tmp);
-}
-
-static void amd_spi_select_chip(struct spi_master *master)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
- u8 chip_select = amd_spi->controller_data.chip_select;
-
- amd_spi_setclear_reg8(master, AMD_SPI_ALT_CS_REG, chip_select,
- AMD_SPI_ALT_CS_MASK);
-}
-
-
-static void amd_spi_clear_fifo_ptr(struct spi_master *master)
-{
- amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR,
- AMD_SPI_FIFO_CLEAR);
-}
-
-static void amd_spi_set_opcode(struct spi_master *master, u8 cmd_opcode)
-{
- amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, cmd_opcode,
- AMD_SPI_OPCODE_MASK);
-}
-
-static inline void amd_spi_set_rx_count(struct spi_master *master,
- u8 rx_count)
-{
- amd_spi_setclear_reg8(master, AMD_SPI_RX_COUNT_REG, rx_count, 0xff);
-}
-
-static inline void amd_spi_set_tx_count(struct spi_master *master,
- u8 tx_count)
-{
- amd_spi_setclear_reg8(master, AMD_SPI_TX_COUNT_REG, tx_count, 0xff);
-}
-
-static void amd_spi_execute_opcode(struct spi_master *master)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
- bool spi_busy;
-
- /* Set ExecuteOpCode bit in the CTRL0 register */
- amd_spi_setclear_reg32(master, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD,
- AMD_SPI_EXEC_CMD);
-
- /* poll for SPI bus to become idle */
- 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;
- }
-}
-
-/* Helper function */
-#ifdef CONFIG_SPI_DEBUG
-static void amd_spi_dump_reg(struct spi_master *master)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
-
- printk(KERN_DEBUG DRIVER_NAME ": SPI CTRL 0 registers: 0x%.8x\n",
- ioread32((u8 *)amd_spi->io_remap_addr + AMD_SPI_CTRL0_REG));
- /*
- * We cannot read CTRL1 register, because reading it would
- * inadvertently increment the FIFO pointer.
- */
- printk(KERN_DEBUG DRIVER_NAME ": SPI ALT CS registers: 0x%.2x\n",
- ioread8((u8 *)amd_spi->io_remap_addr + AMD_SPI_ALT_CS_REG));
- printk(KERN_DEBUG DRIVER_NAME ": SPI Tx Byte Count: 0x%.2x\n",
- ioread8((u8 *)amd_spi->io_remap_addr + AMD_SPI_TX_COUNT_REG));
- printk(KERN_DEBUG DRIVER_NAME ": SPI Rx Byte Count: 0x%.2x\n",
- ioread8((u8 *)amd_spi->io_remap_addr + AMD_SPI_RX_COUNT_REG));
- printk(KERN_DEBUG DRIVER_NAME ": SPI Status registers: 0x%.8x\n",
- ioread32((u8 *)amd_spi->io_remap_addr + AMD_SPI_STATUS_REG));
-}
-#else
-static void amd_spi_dump_reg(struct spi_master *master) {}
-#endif
-
-
-static int amd_spi_master_setup(struct spi_device *spi)
-{
- struct spi_master *master = spi->master;
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
-
- amd_spi->controller_data.chip_select = spi->chip_select;
-
- amd_spi_select_chip(master);
-
- return 0;
-}
-
-static int amd_spi_master_transfer(struct spi_master *master,
- struct spi_message *msg)
-{
- struct amd_spi *amd_spi = spi_master_get_devdata(master);
-
- /*
- * Add new message to the queue and let the kernel thread know
- * about it.
- */
- list_add_tail(&msg->queue, &amd_spi->msg_queue);
- wake_up_interruptible(&amd_spi->wq);
-
- return 0;
-}
-static int amd_spi_thread(void *t)
-{
- struct amd_spi *amd_spi = t;
- struct spi_master *master = amd_spi->master;
- struct spi_transfer *transfer = NULL;
- struct spi_message *message = NULL;
- int direction = 0,i = 0,saved_index = 0;
- int opcode_found = 0,recv_flag = 0,tx_len = 0,rx_len = 0;
- u8 cmd_opcode = 0;
- long timeout = 0;
- u8 *buffer = NULL;
-
- /*
- * What we do here is actually pretty simple. We pick one message
- * at a time from the message queue set up by the controller, and
- * then process all the spi_transfers of that spi_message in one go.
- * We then remove the message from the queue, and complete the
- * transaction. This might not be the best approach, but this is how
- * we chose to implement this. Note that out SPI controller has FIFO
- * size of 70 bytes, but we consider it to contain a maximum of
- * 64-bytes of data and 3-bytes of address.
- */
- while (1) {
- /*
- * Let us wait on a wait queue till the message queue is empty.
- */
- do {
- timeout = wait_event_interruptible_timeout(amd_spi->wq,
- !list_empty(&amd_spi->msg_queue),1000);
-
- /* check stop condition */
- if (kthread_should_stop()) {
- set_current_state(TASK_RUNNING);
- return 0;
- }
- } while(timeout == 0);
-
- /*
- * 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
- * from the queue.
- */
- message = list_entry(amd_spi->msg_queue.next,
- struct spi_message, queue);
- list_del_init(&message->queue);
-
- /* We store the CS# line to be used for this spi_message */
- amd_spi->controller_data.chip_select =
- message->spi->chip_select;
-
- /* Setting all variables to default value. */
- direction = i = 0;
- opcode_found = 0;
- recv_flag = tx_len = rx_len = 0;
- cmd_opcode = 0;
- buffer = NULL;
- saved_index = 0;
-
- amd_spi_select_chip(master);
-
- /*
- * This loop extracts spi_transfers from the spi message,
- * programs the command into command register. Pointer variable
- * *buffer* points to either tx_buf or rx_buf of spi_transfer
- * depending on direction of transfer. Also programs FIFO of
- * controller if data has to be transmitted.
- */
- list_for_each_entry(transfer, &message->transfers,
- transfer_list)
- {
- if(transfer->rx_buf != NULL)
- direction = RECEIVE;
- else if(transfer->tx_buf != NULL)
- direction = TRANSMIT;
-
- switch (direction) {
- case TRANSMIT:
- buffer = (u8 *)transfer->tx_buf;
-
- if(opcode_found != 1) {
- /* Store no. of bytes to be sent into
- * FIFO */
- tx_len = transfer->len - 1;
- /* Store opcode */
- cmd_opcode = *(u8 *)transfer->tx_buf;
- /* Pointing to start of TX data */
- buffer++;
- /* Program the command register*/
- amd_spi_set_opcode(master, cmd_opcode);
- opcode_found = 1;
- } else {
- /* Store no. of bytes to be sent into
- * FIFO */
- tx_len = transfer->len;
- }
-
- /* Write data into the FIFO. */
- for (i = 0; i < tx_len; i++) {
- iowrite8(buffer[i],
- ((u8 *)amd_spi->io_remap_addr +
- AMD_SPI_FIFO_BASE +
- i + saved_index));
- }
-
- /* Set no. of bytes to be transmitted */
- amd_spi_set_tx_count(master,
- tx_len + saved_index);
-
- /*
- * Saving the index, from where next
- * spi_transfer's data will be stored in FIFO.
- */
- saved_index = i;
- break;
- case RECEIVE:
- /* Store no. of bytes to be received from
- * FIFO */
- rx_len = transfer->len;
- buffer = (u8 *)transfer->rx_buf;
- recv_flag=1;
- break;
- }
- }
-
- /* Set the RX count to the number of bytes to expect in
- * response */
- amd_spi_set_rx_count(master, rx_len );
- amd_spi_clear_fifo_ptr(master);
- amd_spi_dump_reg(master);
- /* Executing command */
- amd_spi_execute_opcode(master);
- amd_spi_dump_reg(master);
-
- if(recv_flag == 1) {
- /* Read data from FIFO to receive buffer */
- for (i = 0; i < rx_len; i++) {
- buffer[i] = ioread8((u8 *)amd_spi->io_remap_addr
- + AMD_SPI_FIFO_BASE
- + tx_len + i);
- }
-
- recv_flag = 0;
- }
-
- /* Update statistics */
- message->actual_length = tx_len + rx_len + 1 ;
- /* complete the transaction */
- message->status = 0;
- spi_finalize_current_message(master);
- }
-
- return 0;
-}
-
-static int amd_spi_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- struct device *dev = &pdev->dev;
- struct spi_master *master;
- struct amd_spi *amd_spi;
- u32 io_base_addr;
- int err = 0;
-
- /* Allocate storage for spi_master and driver private data */
- master = spi_alloc_master(dev, sizeof(struct amd_spi));
- if (master == NULL) {
- dev_err(dev, "Error allocating SPI master\n");
- return -ENOMEM;
- }
-
- amd_spi = spi_master_get_devdata(master);
- amd_spi->master = master;
-
- /*
- * Lets first get the base address of SPI registers. The SPI Base
- * Address is stored at offset 0xA0 into the LPC PCI configuration
- * space. As per the specification, it is stored at bits 6:31 of the
- * register. The address is aligned at 64-byte boundary,
- * so we should just mask the lower 6 bits and get the address.
- */
- pci_read_config_dword(pdev, AMD_PCI_LPC_SPI_BASE_ADDR_REG,
- &io_base_addr);
- amd_spi->io_base_addr = io_base_addr & AMD_SPI_BASE_ADDR_MASK;
- amd_spi->io_remap_addr = ioremap_nocache(amd_spi->io_base_addr,
- AMD_SPI_MEM_SIZE);
- if (amd_spi->io_remap_addr == NULL) {
- dev_err(dev, "ioremap of SPI registers failed\n");
- err = -ENOMEM;
- goto err_free_master;
- }
- dev_dbg(dev, "io_base_addr: 0x%.8lx, io_remap_address: %p\n",
- amd_spi->io_base_addr, amd_spi->io_remap_addr);
- 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");
-
- /* Now lets initialize the fields of spi_master */
- master->bus_num = 0; /*
- * This should be the same as passed in
- * spi_board_info structure
- */
- master->num_chipselect = 4; /* Can be overwritten later during setup */
- master->mode_bits = 0;
- master->flags = 0;
- master->setup = amd_spi_master_setup;
- master->transfer_one_message = amd_spi_master_transfer;
- /* Register the controller with SPI framework */
- err = spi_register_master(master);
- if (err) {
- dev_err(dev, "error registering SPI controller\n");
- goto err_iounmap;
- }
- pci_set_drvdata(pdev, amd_spi);
-
- return 0;
-
-err_iounmap:
- iounmap(amd_spi->io_remap_addr);
-err_free_master:
- spi_master_put(master);
-
- return 0;
-}
-
-static void amd_spi_pci_remove(struct pci_dev *pdev)
-{
- struct amd_spi *amd_spi = pci_get_drvdata(pdev);
-
- kthread_stop(amd_spi->kthread_spi);
- iounmap(amd_spi->io_remap_addr);
- spi_unregister_master(amd_spi->master);
- spi_master_put(amd_spi->master);
- pci_set_drvdata(pdev, NULL);
-}
-
-static struct pci_driver amd_spi_pci_driver = {
- .name = "amd_spi",
- .id_table = amd_spi_pci_device_id,
- .probe = amd_spi_pci_probe,
- .remove = amd_spi_pci_remove,
-};
-
-static int __init amd_spi_init(void)
-{
- int ret;
-
- pr_info("AMD SPI Driver v%s\n", SPI_VERSION);
-
- ret = pci_register_driver(&amd_spi_pci_driver);
- if (ret)
- return ret;
-
- return 0;
-}
-module_init(amd_spi_init);
-
-static void __exit amd_spi_exit(void)
-{
- pci_unregister_driver(&amd_spi_pci_driver);
-}
-module_exit(amd_spi_exit);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Arindam Nath <arindam.nath@amd.com>");
-MODULE_AUTHOR("Sanjay Mehta <sanju.mehta@amd.com>");
-MODULE_DESCRIPTION("AMD SPI Master Controller Driver");
diff --git a/meta-v1000/recipes-kernel/amd-spi/files/spi_amd.h b/meta-v1000/recipes-kernel/amd-spi/files/spi_amd.h
deleted file mode 100644
index ec58b9a8..00000000
--- a/meta-v1000/recipes-kernel/amd-spi/files/spi_amd.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef SPI_AMD_H
-#define SPI_AMD_H
-
-#define DRIVER_NAME "spi_amd"
-#define SPI_VERSION "1.0"
-
-#define AMD_SPI_CTRL0_REG 0x00
- #define AMD_SPI_EXEC_CMD (0x1 << 16)
- #define AMD_SPI_OPCODE_MASK 0xFF
- #define AMD_SPI_FIFO_CLEAR (0x1 << 20)
- #define AMD_SPI_BUSY (0x1 << 31)
-#define AMD_SPI_ALT_CS_REG 0x1D
- #define AMD_SPI_ALT_CS_MASK 0x3
-#define AMD_SPI_FIFO_BASE 0x80
-#define AMD_SPI_TX_COUNT_REG 0x48
-#define AMD_SPI_RX_COUNT_REG 0x4B
-#define AMD_SPI_STATUS_REG 0x4C
-
-#define AMD_PCI_LPC_SPI_BASE_ADDR_REG 0xA0
-#define AMD_SPI_BASE_ADDR_MASK ~0x3F
-#define AMD_SPI_MEM_SIZE 200
-
-#define PCI_DEVICE_ID_AMD_LPC_BRIDGE 0x790E
-
-#define TRANSMIT 1
-#define RECEIVE 2
-
-#endif /* SPI_AMD_H */
diff --git a/meta-v1000/recipes-kernel/amd-spi/files/spirom.c b/meta-v1000/recipes-kernel/amd-spi/files/spirom.c
deleted file mode 100644
index cb5970ba..00000000
--- a/meta-v1000/recipes-kernel/amd-spi/files/spirom.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*****************************************************************************
-*
-* spirom.c - SPI ROM client driver
-*
-* Copyright (c) 2014, Advanced Micro Devices, Inc.
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*
-***************************************************************************/
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/ioctl.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/spi/spi.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include <linux/uaccess.h>
-
-#include "spirom.h"
-
-#define SPIROM_VERSION "0.2"
-
-/*
- * SPI has a character major number assigned. We allocate minor numbers
- * dynamically using a bitmask. You must use hotplug tools, such as udev
- * (or mdev with busybox) to create and destroy the /dev/spiromB.C device
- * nodes, since there is no fixed association of minor numbers with any
- * particular SPI bus or device.
- */
-#define SPIROM_MAJOR 153 /* assigned */
-#define N_SPI_MINORS 32 /* ... up to 256 */
-
-#define SPI_BUS 0
-#define SPI_BUS_CS1 0
-
-static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG];
-
-
-struct spirom_data {
- dev_t devt;
- spinlock_t spi_lock;
- struct spi_device *spi;
- struct list_head device_entry;
- struct completion done;
-
- struct mutex buf_lock;
- unsigned users;
-};
-
-static LIST_HEAD(device_list);
-static DEFINE_MUTEX(device_list_lock);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * We can't use the standard synchronous wrappers for file I/O; we
- * need to protect against async removal of the underlying spi_device.
- */
-static void spirom_complete(void *arg)
-{
- complete(arg);
-}
-
-static ssize_t
-spirom_sync(struct spirom_data *spirom, struct spi_message *message)
-{
- int status;
-
- message->complete = spirom_complete;
- message->context = &spirom->done;
-
- spin_lock_irq(&spirom->spi_lock);
- if (spirom->spi == NULL)
- status = -ESHUTDOWN;
- else
- status = spi_async(spirom->spi, message);
- spin_unlock_irq(&spirom->spi_lock);
-
- if (status == 0) {
- /*
- * There might be cases where the controller driver has been
- * unloaded in the middle of a transaction. So we might end up
- * in a situation where we will be waiting for an event which
- * will never happen. So we provide a timeout of 1 second for
- * situations like this.
- */
- wait_for_completion_timeout(&spirom->done, HZ);
- status = message->status;
- if (status == 0)
- status = message->actual_length;
- }
- return status;
-}
-
-static int spirom_message(struct spirom_data *spirom,
- struct spi_ioc_transfer *u_trans, unsigned long arg)
-{
- struct spi_message msg;
- struct spi_transfer *transfer;
- u8 *buffer;
- int status = u_trans->len;
-
- buffer = u_trans->buf;
- spi_message_init(&msg);
-
- /* The very first spi_transfer will contain the command only */
- transfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
- if (!transfer)
- return -ENOMEM;
-
- transfer->tx_buf = buffer;
- transfer->len = 1;
- buffer += transfer->len;
- spi_message_add_tail(transfer, &msg);
-
- /*
- * If the command expects an address as its argument, we populate
- * it in the very next spi_transfer.
- */
- if (u_trans->addr_present) {
- transfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
- if (!transfer)
- return -ENOMEM;
-
- transfer->tx_buf = buffer;
- transfer->len = 3; // 3-byte address
- buffer += transfer->len;
- spi_message_add_tail(transfer, &msg);
- }
-
- /*
- * Next is data, which can have a maximum of 64-bytes, the size limited
- * by the number of bytes that can stored in the controller FIFO.
- */
- if (u_trans->len) {
- transfer = kzalloc(sizeof(struct spi_transfer), GFP_KERNEL);
- if (!transfer)
- return -ENOMEM;
-
- if (u_trans->direction == TRANSMIT)
- transfer->tx_buf = buffer;
- else if (u_trans->direction == RECEIVE)
- transfer->rx_buf = buffer;
-
- transfer->len = u_trans->len;
- /* No need to increment buffer pointer */
- spi_message_add_tail(transfer, &msg);
- }
-
- status = spirom_sync(spirom, &msg);
-
- if (u_trans->direction == RECEIVE) {
- /*
- * The received data should have been populated in
- * u_trans->buf, so we just need to copy it into the
- * user-space buffer.
- */
- buffer = u_trans->buf;
- if (u_trans->addr_present) {
- buffer += 4; // 1-byte command and 3-byte address
- if(__copy_to_user((u8 __user *)
- (((struct spi_ioc_transfer *)arg)->buf) + 4,
- buffer, u_trans->len)) {
- status = -EFAULT;
- }
- } else {
- buffer += 1; // 1-byte command only
- if(__copy_to_user((u8 __user *)
- (((struct spi_ioc_transfer *)arg)->buf) + 1,
- buffer, u_trans->len)) {
- status = -EFAULT;
- }
- }
- }
-
- /* Done with everything, free the memory taken by spi_transfer */
- while (msg.transfers.next != &msg.transfers) {
- transfer = list_entry(msg.transfers.next, struct spi_transfer,
- transfer_list);
- msg.transfers.next = transfer->transfer_list.next;
- transfer->transfer_list.next->prev = &msg.transfers;
- kfree(transfer);
- }
-
- return status;
-}
-
-static long
-spirom_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- int err = 0;
- int retval = 0;
- struct spirom_data *spirom;
- struct spi_device *spi;
- u32 tmp;
- struct spi_ioc_transfer *ioc;
-
- /* Check type and command number */
- if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC)
- return -ENOTTY;
-
- /* Check access direction once here; don't repeat below.
- * IOC_DIR is from the user perspective, while access_ok is
- * from the kernel perspective; so they look reversed.
- */
- if (_IOC_DIR(cmd) & _IOC_READ)
- err = !access_ok(VERIFY_WRITE,
- (void __user *)arg, _IOC_SIZE(cmd));
- if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE)
- err = !access_ok(VERIFY_READ,
- (void __user *)arg, _IOC_SIZE(cmd));
- if (err)
- return -EFAULT;
-
- /* guard against device removal before, or while,
- * we issue this ioctl.
- */
- spirom = filp->private_data;
- spin_lock_irq(&spirom->spi_lock);
- spi = spi_dev_get(spirom->spi);
- spin_unlock_irq(&spirom->spi_lock);
-
- if (spi == NULL)
- return -ESHUTDOWN;
-
- /* use the buffer lock here for triple duty:
- * - prevent I/O (from us) so calling spi_setup() is safe;
- * - prevent concurrent SPI_IOC_WR_* from morphing
- * data fields while SPI_IOC_RD_* reads them;
- * - SPI_IOC_MESSAGE needs the buffer locked "normally".
- */
- mutex_lock(&spirom->buf_lock);
-
- /* segmented and/or full-duplex I/O request */
- if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) ||
- _IOC_DIR(cmd) !=_IOC_WRITE) {
- retval = -ENOTTY;
- goto out;
- }
-
- tmp = sizeof(struct spi_ioc_transfer);
-
- /* copy into scratch area */
- ioc = kzalloc(tmp, GFP_KERNEL);
- if (!ioc) {
- retval = -ENOMEM;
- goto out;
- }
- if (__copy_from_user(ioc, (struct spi_ioc_transfer __user *)arg,
- tmp)) {
- kfree(ioc);
- retval = -EFAULT;
- goto out;
- }
-
- /* translate to spi_message, execute */
- retval = spirom_message(spirom, ioc, arg);
- kfree(ioc);
-
-out:
- mutex_unlock(&spirom->buf_lock);
- spi_dev_put(spi);
- return retval;
-}
-
-static int spirom_open(struct inode *inode, struct file *filp)
-{
- struct spirom_data *spirom;
- int status = -ENXIO;
-
- mutex_lock(&device_list_lock);
-
- list_for_each_entry(spirom, &device_list, device_entry) {
- if (spirom->devt == inode->i_rdev) {
- status = 0;
- break;
- }
- }
- if (status == 0) {
- if (status == 0) {
- spirom->users++;
- filp->private_data = spirom;
- nonseekable_open(inode, filp);
- }
- } else
- pr_debug("spirom: nothing for minor %d\n", iminor(inode));
-
- mutex_unlock(&device_list_lock);
- return status;
-}
-
-static int spirom_release(struct inode *inode, struct file *filp)
-{
- struct spirom_data *spirom;
- int status = 0;
-
- mutex_lock(&device_list_lock);
- spirom = filp->private_data;
- filp->private_data = NULL;
-
- /* last close? */
- spirom->users--;
- if (!spirom->users) {
- int dofree;
-
- /* ... after we unbound from the underlying device? */
- spin_lock_irq(&spirom->spi_lock);
- dofree = (spirom->spi == NULL);
- spin_unlock_irq(&spirom->spi_lock);
-
- if (dofree)
- kfree(spirom);
- }
- mutex_unlock(&device_list_lock);
-
- return status;
-}
-
-static const struct file_operations spirom_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = spirom_ioctl,
- .open = spirom_open,
- .release = spirom_release,
-};
-
-static int __init add_spi_device_to_bus(void)
-{
- struct spi_master *spi_master;
- struct spi_device *spi_device;
- struct spi_board_info spi_info;
-
- spi_master = spi_busnum_to_master(SPI_BUS);
- if (!spi_master) {
- printk(KERN_ALERT "Please make sure to \'modprobe "
- "spi_amd\' driver first\n");
- return -1;
- }
- memset(&spi_info, 0, sizeof(struct spi_board_info));
-
- strlcpy(spi_info.modalias, "spirom", SPI_NAME_SIZE);
- spi_info.bus_num = SPI_BUS; //Bus number of SPI master
- spi_info.chip_select = SPI_BUS_CS1; //CS on which SPI device is connected
-
- spi_device = spi_new_device(spi_master, &spi_info);
- if (!spi_device)
- return -ENODEV;
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* The main reason to have this class is to make mdev/udev create the
- * /dev/spiromB.C character device nodes exposing our userspace API.
- * It also simplifies memory management.
- */
-
-static struct class *spirom_class;
-
-/*-------------------------------------------------------------------------*/
-
-static int spirom_probe(struct spi_device *spi)
-{
- struct spirom_data *spirom;
- int status;
- unsigned long minor;
-
- /* Allocate driver data */
- spirom = kzalloc(sizeof(*spirom), GFP_KERNEL);
- if (!spirom)
- return -ENOMEM;
-
- /* Initialize the driver data */
- spirom->spi = spi;
- spin_lock_init(&spirom->spi_lock);
- mutex_init(&spirom->buf_lock);
-
- INIT_LIST_HEAD(&spirom->device_entry);
- init_completion(&spirom->done);
-
- /* If we can allocate a minor number, hook up this device.
- * Reusing minors is fine so long as udev or mdev is working.
- */
- mutex_lock(&device_list_lock);
- minor = find_first_zero_bit(minors, N_SPI_MINORS);
- if (minor < N_SPI_MINORS) {
- struct device *dev;
-
- spirom->devt = MKDEV(SPIROM_MAJOR, minor);
- dev = device_create(spirom_class, &spi->dev, spirom->devt,
- spirom, "spirom%d.%d",
- spi->master->bus_num, spi->chip_select);
- status = IS_ERR(dev) ? PTR_ERR(dev) : 0;
- } else {
- dev_dbg(&spi->dev, "no minor number available!\n");
- status = -ENODEV;
- }
- if (status == 0) {
- set_bit(minor, minors);
- list_add(&spirom->device_entry, &device_list);
- }
- mutex_unlock(&device_list_lock);
-
- if (status == 0)
- spi_set_drvdata(spi, spirom);
- else
- kfree(spirom);
-
- return status;
-}
-
-static int spirom_remove(struct spi_device *spi)
-{
- struct spirom_data *spirom = spi_get_drvdata(spi);
-
- /* make sure ops on existing fds can abort cleanly */
- spin_lock_irq(&spirom->spi_lock);
- spirom->spi = NULL;
- spi_set_drvdata(spi, NULL);
- spin_unlock_irq(&spirom->spi_lock);
-
- /* prevent new opens */
- mutex_lock(&device_list_lock);
- list_del(&spirom->device_entry);
- clear_bit(MINOR(spirom->devt), minors);
- device_destroy(spirom_class, spirom->devt);
- if (spirom->users == 0)
- kfree(spirom);
- mutex_unlock(&device_list_lock);
-
- return 0;
-}
-
-static struct spi_driver spirom_spi = {
- .driver = {
- .name = "spirom",
- .owner = THIS_MODULE,
- },
- .probe = spirom_probe,
- .remove = spirom_remove,
-
- /* NOTE: suspend/resume methods are not necessary here.
- * We don't do anything except pass the requests to/from
- * the underlying controller. The refrigerator handles
- * most issues; the controller driver handles the rest.
- */
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int __init spirom_init(void)
-{
- int status;
-
- pr_info("AMD SPIROM Driver v%s\n", SPIROM_VERSION);
-
- /* Claim our 256 reserved device numbers. Then register a class
- * that will key udev/mdev to add/remove /dev nodes. Last, register
- * the driver which manages those device numbers.
- */
- BUILD_BUG_ON(N_SPI_MINORS > 256);
- status = register_chrdev(SPIROM_MAJOR, "spi", &spirom_fops);
- if (status < 0)
- return status;
-
- spirom_class = class_create(THIS_MODULE, "spirom");
- if (IS_ERR(spirom_class)) {
- unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
- return PTR_ERR(spirom_class);
- }
-
- status = spi_register_driver(&spirom_spi);
- if (status < 0) {
- class_destroy(spirom_class);
- unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
- }
-
- status = add_spi_device_to_bus();
- if (status < 0) {
- spi_unregister_driver(&spirom_spi);
- class_destroy(spirom_class);
- unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
- }
-
- return status;
-}
-module_init(spirom_init);
-
-static void __exit spirom_exit(void)
-{
- spi_unregister_driver(&spirom_spi);
- class_destroy(spirom_class);
- unregister_chrdev(SPIROM_MAJOR, spirom_spi.driver.name);
-}
-module_exit(spirom_exit);
-
-MODULE_AUTHOR("Arindam Nath <arindam.nath@amd.com>");
-MODULE_DESCRIPTION("User mode SPI ROM interface");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("spi:spirom");
diff --git a/meta-v1000/recipes-kernel/amd-spi/files/spirom.h b/meta-v1000/recipes-kernel/amd-spi/files/spirom.h
deleted file mode 100644
index 941b357a..00000000
--- a/meta-v1000/recipes-kernel/amd-spi/files/spirom.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef SPIROM_H
-#define SPIROM_H
-
-#include <linux/types.h>
-
-/*---------------------------------------------------------------------------*/
-
-/* IOCTL commands */
-
-#define SPI_IOC_MAGIC 'k'
-
-#define TRANSMIT 1
-#define RECEIVE 2
-
-/*
- * struct spi_ioc_transfer - interface structure between application and ioctl
- *
- * @buf: Buffer to hold 1-byte command, 3-bytes address, and 64-byte data for
- * transmit or receive. The internal FIFO of our controller can hold a
- * maximum of 70 bytes, including the address. But here we assume the
- * maximum data excluding address to be 64-bytes long.
- *
- * @direction: Direction of data transfer, either TRANSMIT or RECEIVE.
- *
- * @len: Length of data excluding command and address.
- *
- * @addr_present: Flag to indicate whether 'buf' above contains an address.
- */
-struct spi_ioc_transfer {
- __u8 buf[64 + 1 + 3];
- __u8 direction;
- __u8 len;
- __u8 addr_present;
-};
-
-/* not all platforms use <asm-generic/ioctl.h> or _IOC_TYPECHECK() ... */
-#define SPI_MSGSIZE(N) \
- ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \
- ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)
-#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
-
-/* SPI ROM command codes */
-#define ROM_WREN 0x06
-#define ROM_WRDI 0x04
-#define ROM_RDSR 0x05
-#define ROM_RDID 0x9F
-#define ROM_CHIP_ERASE 0x60
-#define ROM_SECTOR_ERASE 0x20
-#define ROM_BLOCK_ERASE 0xD8
-#define ROM_READ 0x03
-#define ROM_WRITE 0x02
-
-#endif /* SPIROM_H */