diff options
Diffstat (limited to 'packages/linux/linux-rp-2.6.21/locomo_spi-r4.patch')
-rw-r--r-- | packages/linux/linux-rp-2.6.21/locomo_spi-r4.patch | 947 |
1 files changed, 0 insertions, 947 deletions
diff --git a/packages/linux/linux-rp-2.6.21/locomo_spi-r4.patch b/packages/linux/linux-rp-2.6.21/locomo_spi-r4.patch deleted file mode 100644 index 7ecc48f956..0000000000 --- a/packages/linux/linux-rp-2.6.21/locomo_spi-r4.patch +++ /dev/null @@ -1,947 +0,0 @@ -Index: linux-2.6.21/drivers/spi/Kconfig -=================================================================== ---- linux-2.6.21.orig/drivers/spi/Kconfig 2007-04-26 05:08:32.000000000 +0200 -+++ linux-2.6.21/drivers/spi/Kconfig 2007-07-03 21:40:52.000000000 +0200 -@@ -89,6 +89,10 @@ - This enables using the Freescale iMX SPI controller in master - mode. - -+config SPI_LOCOMO -+ tristate "Locomo SPI master" -+ depends on SPI_MASTER && SHARP_LOCOMO && EXPERIMENTAL -+ - config SPI_MPC83xx - tristate "Freescale MPC83xx SPI controller" - depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL -Index: linux-2.6.21/drivers/spi/locomo_spi.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.21/drivers/spi/locomo_spi.c 2007-07-03 21:40:52.000000000 +0200 -@@ -0,0 +1,873 @@ -+#include <asm/io.h> -+#include <asm/irq.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/device.h> -+#include <linux/stat.h> -+#include <linux/delay.h> -+#include <linux/interrupt.h> -+#include <asm/hardware/locomo.h> -+#include <linux/mmc/host.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/mmc_spi.h> -+#include <linux/workqueue.h> -+#include <linux/spinlock.h> -+#include <linux/list.h> -+#include "locomo_spi.h" -+static struct locomospi_dev * spidev; -+static struct work_struct transfer_wq; -+int verbose=0; -+/* MMC_SPI functions *********************************************************/ -+ -+static int locomommcspi_init(struct device *dev, irqreturn_t (*isr)(int, void*), void *mmc) -+{ -+ int result; -+ locomo_gpio_set_irq(spidev->ldev->dev.parent, LOCOMO_GPIO_CARD_DETECT, LOCOMO_GPIO_IRQ_ON_RISE | LOCOMO_GPIO_IRQ_ON_FALL); -+ spidev->mmc_spi_isr = isr; -+ result=request_irq(IRQ_LOCOMO_CARDDETECT, locomospi_cardisr, SA_SHIRQ, "locomo-spi", mmc); -+ return result; -+} -+ -+static void locomommcspi_exit(struct device *dev, void* mmc) -+{ -+ free_irq(IRQ_LOCOMO_CARDDETECT, mmc); -+} -+ -+static int locomommcspi_getro(struct device *dev) -+{ -+ return locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROTECT) > 0 ? 1 : 0; -+} -+ -+static void locomommcspi_powermode(struct device *dev, unsigned char mode) -+{ -+ if(mode == MMC_POWER_OFF && spidev->card_power != 0) -+ locomospi_power(0); -+ else if( spidev->card_power != 1) -+ locomospi_power(1); -+ -+} -+ -+static void locomommcspi_reset(void) -+{ -+ /* transmit card reset sequence, should be done from mmc_layer */ -+ locomospi_setcs(1); -+ tx("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",10); -+ locomospi_setcs(0); -+} -+ -+ -+static struct mmc_spi_platform_data colliemmc ={ -+ .init = locomommcspi_init, -+ .exit = locomommcspi_exit, -+ .detect_delay = HZ, -+ .get_ro = locomommcspi_getro, -+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, -+ .setpowermode = locomommcspi_powermode, -+ .reset = locomommcspi_reset, -+}; -+ -+/* Utility function **********************************************************/ -+ -+static irqreturn_t locomospi_cardisr(int irq, void *dev_id) -+{ -+ u16 r; -+ if(locomospi_carddetect()){ -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r |= 0x80; -+ locomo_writel( r, spidev->base+LOCOMO_SPIMD); -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r |= 0x40; -+ locomo_writel( r, spidev->base+LOCOMO_SPIMD); -+ /* transmit card reset sequence, should be done from mmc_layer */ -+// locomospi_setcs(1); -+ // tx("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",10); -+// locomospi_setcs(0); -+ } else { -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r &= ~0x80; -+ locomo_writel( r, spidev->base+LOCOMO_SPIMD); -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r &= ~0x40; -+ locomo_writel( r, spidev->base+LOCOMO_SPIMD); -+ } -+ return spidev->mmc_spi_isr(irq, dev_id); -+} -+ -+static void locomospi_power(int on) -+{ -+ locomo_gpio_write(spidev->ldev->dev.parent, LOCOMO_GPIO_CARD_POWER, on); -+ spidev->card_power=on; -+ set_current_state(TASK_INTERRUPTIBLE); -+ if(on){ -+ schedule_timeout(HZ/10); -+ } else { -+ schedule_timeout(2*HZ); -+ } -+ -+} -+ -+static void locomospi_setclock(unsigned int base, unsigned int mult) -+{ -+ u16 r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ base &= 0x7; -+ mult &= 0x3; -+ r &= ~(0x7 | 0x18 | 0x40); -+ locomo_writel(r,spidev->base+LOCOMO_SPIMD); -+ r |= (base | (mult <<3) | 0x40); -+ locomo_writel(r,spidev->base+LOCOMO_SPIMD); -+ spidev->clock_base = base; -+ spidev->clock_mult = mult; -+ -+} -+// returns 1 if card ist present, 0 otherwise -+static int locomospi_carddetect() -+{ -+ return (locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1; -+} -+ -+static void locomospi_togglecs() -+{ -+ u16 r; -+ r = locomo_readl(spidev->base + LOCOMO_SPICT); -+ r ^= 0x40; // I think this is CHIPSELECTHIGH -+ locomo_writel(r, spidev->base + LOCOMO_SPICT); -+} -+ -+static void locomospi_setcs(int high) -+{ -+ u16 r; -+ r = locomo_readl(spidev->base + LOCOMO_SPICT); -+ if(high) -+ r |= 0x40; -+ else -+ r &= ~0x40; -+ locomo_writel(r, spidev->base + LOCOMO_SPICT); -+} -+ -+static void locomospi_reg_open() -+{ -+ u16 r; -+ spidev->clock_base = 4; -+ spidev->clock_mult = 0; -+ locomospi_power(1); -+ locomo_writel( 0x6c00 | (2 <<3)|4, spidev->base+LOCOMO_SPIMD); -+ if(locomospi_carddetect()){ -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r |= 0x80; -+ locomo_writel( r, spidev->base+LOCOMO_SPIMD); -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r |= 0x40; -+ locomo_writel( r, spidev->base+LOCOMO_SPIMD); -+ } -+ locomo_writel( 0x40, spidev->base+LOCOMO_SPICT); -+ r = locomo_readl(spidev->base+LOCOMO_SPICT); -+ r |= 0x80; -+ locomo_writel( r, spidev->base+LOCOMO_SPICT); -+ udelay(200); -+ r = locomo_readl(spidev->base+LOCOMO_SPICT); -+ locomo_writel(r, spidev->base+LOCOMO_SPICT); -+ r = locomo_readl(spidev->base+LOCOMO_SPICT); -+ r |= 0x1; -+ locomo_writel(r, spidev->base+LOCOMO_SPICT); -+ r = locomo_readl(spidev->base+LOCOMO_SPICT); -+ r &= ~0x40; -+ locomo_writel(r, spidev->base+LOCOMO_SPICT); -+} -+ -+static void locomospi_reg_release() -+{ -+ u16 r; -+ r = locomo_readl(spidev->base+LOCOMO_SPICT); -+ r &= ~0x80; -+ locomo_writel(r, spidev->base+LOCOMO_SPICT); -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r &= ~0x40; -+ locomo_writel(r, spidev->base+LOCOMO_SPIMD); -+ r = locomo_readl(spidev->base+LOCOMO_SPIMD); -+ r &= ~0x80; -+ locomo_writel(r, spidev->base+LOCOMO_SPIMD); -+ r = locomo_readl(spidev->base+LOCOMO_SPICT); -+ r |= 0x40; -+ locomo_writel(r, spidev->base+LOCOMO_SPICT); -+ locomospi_power(0); -+} -+ -+static int tx(const char* buffer, int size) -+{ -+ int i=0,j=0; -+// int result=0; -+ int wait; -+ if(!spidev->clock_base && !spidev->clock_mult) -+ return 0; -+ if(spidev->clock_base == 4) -+ wait = 0x10000; -+ else -+ wait = 8; -+ -+ for(i=0; i<size; i++){ -+/* if(!(locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)){ -+ result = wait_event_interruptible(spidev->waitqueue, locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW); -+ if(result) { -+ dev_err(&spidev->sdev->dev, "received Signal. giving up tx."); -+ return i; -+ } -+ }*/ -+ for(j=0; j <= wait; j++){ -+ if(locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW) -+ break; -+ } -+ locomo_writel((u16) buffer[i], spidev->base+LOCOMO_SPITD); -+ if(verbose) -+ printk(KERN_DEBUG "locomospi: sent: char :%x\n", (u16) buffer[i]); -+ if(spidev->clock_base){ -+ for(j=0; j <= wait; j++){ -+ if(!(locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)) -+ break; -+ } -+ } -+ } -+ if(spidev->clock_base){ -+ for(i=0; i <= wait; i++){ -+ if(locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_TEND) -+ break; -+ } -+ } -+ return j; -+} -+ -+static int rx(char* buffer, int size) -+{ -+ int i,j; -+// int result=0; -+ int wait; -+ u16 rd; -+ if(!spidev->clock_base && !spidev->clock_mult) -+ return 0; -+ if(spidev->clock_base == 4) -+ wait = 0x10000; -+ else -+ wait = 8; -+ -+ for(i=0; i<size; i++){ -+/* if(!(locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW)){ -+ result = wait_event_interruptible(spidev->waitqueue, locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFW); -+ if(result) { -+ dev_err(&spidev->sdev->dev, "received Signal. giving up tx."); -+ return i; -+ } -+ }*/ -+ for(j=0; j <= wait; j++){ -+ if(locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR) -+ break; -+ } -+ rd= locomo_readl(spidev->base+LOCOMO_SPIRD); -+ if(verbose) -+ printk(KERN_DEBUG "locomospi: received: char :%x\n", (u16) buffer[i]); -+ buffer[i]=(char) rd; -+ if(spidev->clock_base){ -+ for(j=0; j <= wait; j++){ -+ if(!(locomo_readl(spidev->base+LOCOMO_SPIST) & LOCOMO_SPI_RFR)) -+ break; -+ } -+ } -+ } -+ return i; -+} -+ -+/* -+static irqreturn_t locomospi_rwready(int irq, void *dev_id) -+{ -+ struct locomospi_dev* dev=(struct locomospi_dev*) dev_id; -+// dev_dbg(&spidev->sdev->dev, "IRQ: %d\n", irq); -+// printk(KERN_DEBUG "locomospi: IRQ: %d\n", irq); -+ wake_up_interruptible(&dev->waitqueue); -+ return IRQ_HANDLED; -+} -+ -+static irqreturn_t locomospi_testisr(int irq, void *dev_id) -+{ -+ char *buf=""; -+ switch(irq){ -+ case IRQ_LOCOMO_SPI_RFR: buf="RFR"; -+ break; -+ case IRQ_LOCOMO_SPI_RFW: buf="RFW"; -+ break; -+ case IRQ_LOCOMO_SPI_OVRN:buf="OVRN"; -+ break; -+ case IRQ_LOCOMO_SPI_TEND:buf="TEND"; -+ break; -+ case IRQ_LOCOMO_CARDDETECT: -+ buf="CARD_DETECT"; -+ break; -+ default: return IRQ_NONE; -+ } -+ printk(KERN_DEBUG "locomospi: IRQ: %s\n",buf); -+// dev_dbg(&spidev->sdev->dev, "IRQ: %s\n",buf); -+ return IRQ_HANDLED; -+} -+*/ -+/* sysfs attributes used for debug *******************************************/ -+ -+/* SPI registers */ -+ssize_t locomospi_showspimd(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIMD)); -+} -+ -+ssize_t locomospi_storespimd(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIMD); -+ return count; -+} -+static DRIVER_ATTR(spimd, S_IWUSR | S_IRUGO, locomospi_showspimd, locomospi_storespimd); -+ -+ssize_t locomospi_showspict(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPICT)); -+} -+ -+ssize_t locomospi_storespict(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPICT); -+ return count; -+} -+static DRIVER_ATTR(spict, S_IWUSR | S_IRUGO, locomospi_showspict, locomospi_storespict); -+ -+ssize_t locomospi_showspist(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIST)); -+} -+ -+ssize_t locomospi_storespist(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIST); -+ return count; -+} -+static DRIVER_ATTR(spist, S_IWUSR | S_IRUGO, locomospi_showspist, locomospi_storespist); -+ -+ssize_t locomospi_showspiis(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIIS)); -+} -+ -+ssize_t locomospi_storespiis(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIIS); -+ return count; -+} -+static DRIVER_ATTR(spiis, S_IWUSR | S_IRUGO, locomospi_showspiis, locomospi_storespiis); -+ -+ssize_t locomospi_showspiwe(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIWE)); -+} -+ -+ssize_t locomospi_storespiwe(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIWE); -+ return count; -+} -+static DRIVER_ATTR(spiwe, S_IWUSR | S_IRUGO, locomospi_showspiwe, locomospi_storespiwe); -+ -+ssize_t locomospi_showspiie(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIIE)); -+} -+ -+ssize_t locomospi_storespiie(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIIE); -+ return count; -+} -+static DRIVER_ATTR(spiie, S_IWUSR | S_IRUGO, locomospi_showspiie, locomospi_storespiie); -+ -+ssize_t locomospi_showspiir(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIIR)); -+} -+ -+ssize_t locomospi_storespiir(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIIR); -+ return count; -+} -+static DRIVER_ATTR(spiir, S_IWUSR | S_IRUGO, locomospi_showspiir, locomospi_storespiir); -+ -+ssize_t locomospi_showspitd(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPITD)); -+} -+ -+ssize_t locomospi_storespitd(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITD); -+ return count; -+} -+static DRIVER_ATTR(spitd, S_IWUSR | S_IRUGO, locomospi_showspitd, locomospi_storespitd); -+ -+ssize_t locomospi_showspird(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIRD)); -+} -+ -+ssize_t locomospi_storespird(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRD); -+ return count; -+} -+static DRIVER_ATTR(spird, S_IWUSR | S_IRUGO, locomospi_showspird, locomospi_storespird); -+ -+ssize_t locomospi_showspits(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPITS)); -+} -+ -+ssize_t locomospi_storespits(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPITS); -+ return count; -+} -+static DRIVER_ATTR(spits, S_IWUSR | S_IRUGO, locomospi_showspits, locomospi_storespits); -+ -+ssize_t locomospi_showspirs(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%x\n", locomo_readl(spidev->base+LOCOMO_SPIRS)); -+} -+ -+ssize_t locomospi_storespirs(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomo_writel(simple_strtoul(buf, NULL, 16), spidev->base+LOCOMO_SPIRS); -+ return count; -+} -+static DRIVER_ATTR(spirs, S_IWUSR | S_IRUGO, locomospi_showspirs, locomospi_storespirs); -+ -+/* MMC Card status */ -+ -+ssize_t locomospi_showpower(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "%d\n", spidev->card_power); -+} -+ -+ssize_t locomospi_storepower(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomospi_power(simple_strtoul(buf, NULL, 10)); -+ return count; -+} -+static DRIVER_ATTR(cardpower, S_IWUSR | S_IRUGO, locomospi_showpower, locomospi_storepower); -+ -+ssize_t locomospi_detectcard(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_CARD_DETECT)>0)?0:1); -+} -+static DRIVER_ATTR(carddetect, S_IRUGO, locomospi_detectcard, NULL); -+ -+ssize_t locomospi_writeprotect(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "%d\n",(locomo_gpio_read_level(spidev->ldev->dev.parent,LOCOMO_GPIO_WRITE_PROTECT)>0)?1:0); -+} -+static DRIVER_ATTR(cardwriteprotect, S_IRUGO, locomospi_writeprotect, NULL); -+ -+ssize_t locomospi_showclockbase(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "%d\n", spidev->clock_base); -+} -+ -+ssize_t locomospi_storeclockbase(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomospi_setclock(simple_strtoul(buf, NULL, 10), spidev->clock_mult); -+ return count; -+} -+static DRIVER_ATTR(clockbase, S_IWUSR | S_IRUGO, locomospi_showclockbase, locomospi_storeclockbase); -+ -+ssize_t locomospi_showclockmult(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "%d\n", spidev->clock_mult); -+} -+ -+ssize_t locomospi_storeclockmult(struct device_driver *drv, const char *buf, size_t count) -+{ -+ locomospi_setclock(spidev->clock_base, simple_strtoul(buf, NULL, 10)); -+ return count; -+} -+static DRIVER_ATTR(clockmult, S_IWUSR | S_IRUGO, locomospi_showclockmult, locomospi_storeclockmult); -+ -+/* debug */ -+ -+ssize_t locomospi_reset(struct device_driver *drv, const char *buf, size_t count) -+{ -+ int choice = simple_strtoul(buf, NULL, 10); -+// char buff[10]; -+ switch(choice){ -+ case 0: locomospi_reg_release(); -+ locomospi_reg_open(); -+ break; -+ case 1: tx("\x40\x00\x00\x00\x00\x95",6); -+ break; -+ case 2: locomospi_setcs(1); -+ tx("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",10); -+ locomospi_setcs(0); -+ break; -+ default: /* do nothing */; -+ } -+ return count; -+} -+static DRIVER_ATTR(reset, S_IWUSR, NULL, locomospi_reset); -+ -+ssize_t locomospi_showverbose(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "%d\n", verbose); -+} -+ -+ssize_t locomospi_storeverbose(struct device_driver *drv, const char *buf, size_t count) -+{ -+ verbose=simple_strtoul(buf, NULL, 10); -+ return count; -+} -+static DRIVER_ATTR(verbose, S_IWUSR | S_IRUGO, locomospi_showverbose, locomospi_storeverbose); -+ -+/* SPI functions *************************************************************/ -+ -+static void locomospi_do_transfer(struct work_struct *wrk) -+{ -+ struct list_head *mptr, *tptr, *mptr2; -+ struct spi_transfer *entry; -+ struct spi_message *msg; -+ -+ list_for_each_safe(mptr, mptr2, &spidev->message_list){ -+ int i; -+ msg = list_entry(mptr, struct spi_message, queue); -+ -+ msg->status = 0; -+ msg->actual_length = 0; -+ list_for_each(tptr, &msg->transfers){ -+ entry = list_entry(tptr, struct spi_transfer, transfer_list); -+ if(entry->tx_buf && entry->rx_buf){ //duplex -+ for(i=0; i< entry->len; i++){ -+ tx(((char*) entry->tx_buf)+i*sizeof(char),1); -+ rx(((char*) entry->rx_buf)+i*sizeof(char),1); -+ } -+ msg->actual_length += entry->len; -+ } else if(entry->tx_buf && !entry->rx_buf){ //write -+ tx((char*) entry->tx_buf, entry->len); -+ msg->actual_length += entry->len; -+ } else if(!entry->tx_buf && entry->rx_buf){ //read -+ rx((char*) entry->rx_buf, entry->len); -+ msg->actual_length += entry->len; -+ } else if(!entry->tx_buf && !entry->rx_buf){ //error -+ dev_err(&spidev->sdev->dev, "do_transfer: no buffers allocated\n"); -+ msg->status = -EFAULT; -+ } -+ } -+ spin_lock(&spidev->message_lock); -+ list_del(mptr); -+ spin_unlock(&spidev->message_lock); -+ msg->complete(msg->context); -+ } -+} -+ -+static int locomospi_setup(struct spi_device *spi) -+{ -+ if((spi->mode & SPI_CS_HIGH) != (spidev->spimode & SPI_CS_HIGH)) -+ locomospi_togglecs(); -+ spidev->spimode = spi->mode; -+ -+ if(spi->max_speed_hz == 0) -+ locomospi_setclock(0, 0); -+ else if(spi->max_speed_hz >= 25000000) -+ locomospi_setclock(0, 2); -+ else if(spi->max_speed_hz >= 22500000) -+ locomospi_setclock(0, 1); -+ else if(spi->max_speed_hz >= 12500000) -+ locomospi_setclock(1, 2); -+ else if(spi->max_speed_hz >= 10000000) -+ locomospi_setclock(1, 1); -+ else if(spi->max_speed_hz >= 9000000) -+ locomospi_setclock(1, 0); -+ else if(spi->max_speed_hz >= 6230000) -+ locomospi_setclock(2, 2); -+ else if(spi->max_speed_hz >= 5660000) -+ locomospi_setclock(2, 1); -+ else if(spi->max_speed_hz >= 4640000) -+ locomospi_setclock(2, 0); -+ else if(spi->max_speed_hz >= 3030000) -+ locomospi_setclock(3, 2); -+ else if(spi->max_speed_hz >= 2870000) -+ locomospi_setclock(3, 1); -+ else if(spi->max_speed_hz >= 2330000) -+ locomospi_setclock(3, 0); -+ else if(spi->max_speed_hz >= 383000) -+ locomospi_setclock(4, 2); -+ else if(spi->max_speed_hz >= 350000) -+ locomospi_setclock(4, 1); -+ else -+ locomospi_setclock(4, 0); -+ return 0; -+} -+ -+static int locomospi_transfer(struct spi_device *spi, struct spi_message *msg) -+{ -+ -+ spin_lock(&spidev->message_lock); -+ list_add_tail(&msg->queue, &spidev->message_list); -+ spin_unlock(&spidev->message_lock); -+ schedule_work(&transfer_wq); -+ return 0; -+} -+ -+static struct locomo_driver locomo_spi_driver = { -+ .drv = { -+ .name = "locomo-spi", -+ }, -+ .devid = LOCOMO_DEVID_SPI, -+ .probe = locomospi_probe, -+ .remove = locomospi_remove, -+#ifdef CONFIG_PM -+ .suspend = locomospi_suspend, -+ .resume = locomospi_resume, -+#endif -+}; -+ -+static struct spi_board_info board = { -+ .modalias = "mmc_spi", -+ .platform_data = (void*) &colliemmc, -+ .controller_data= NULL, -+ .irq = 0, -+ .max_speed_hz = 25000000, -+ .bus_num = 0, -+ .chip_select = 0, -+ .mode = 0, -+}; -+ -+#ifdef CONFIG_PM -+static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state) -+{ -+ disable_irq(IRQ_LOCOMO_CARDDETECT); -+ return 0; -+} -+ -+static int locomospi_resume(struct locomo_dev *dev) -+{ -+ enable_irq(IRQ_LOCOMO_CARDDETECT); -+ return 0; -+} -+#endif -+ -+static int locomospi_probe(struct locomo_dev *dev) -+{ -+ int result=0; -+ printk(KERN_DEBUG "Collie MMC over SPI Driver\n"); -+ spidev=kmalloc(sizeof(struct locomospi_dev),GFP_KERNEL); -+ if(!spidev){ -+ return -ENOMEM; -+ } -+ spidev->ldev = dev; -+ spidev->card_power = 0; -+ spidev->spimode = 0; -+ if(!request_mem_region((unsigned long) dev->mapbase, dev->length, LOCOMO_DRIVER_NAME(dev))) { -+ dev_err(&dev->dev, " Can't aquire access to io memory\n"); -+ return -EBUSY; -+ } -+ spidev->base=(unsigned long) dev->mapbase; -+ -+ locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_POWER, 0); -+ locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_CARD_DETECT, 1); -+ locomo_gpio_set_dir(dev->dev.parent, LOCOMO_GPIO_WRITE_PROTECT, 1); -+ -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardpower); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_carddetect); -+ if(result){ -+ dev_err(&dev->dev,"error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_cardwriteprotect); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spimd); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spict); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spist); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spiis); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spiwe); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spiie); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spiir); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spitd); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spird); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spits); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_spirs); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_clockbase); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_clockmult); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_reset); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ result=driver_create_file(&locomo_spi_driver.drv, &driver_attr_verbose); -+ if(result){ -+ dev_err(&dev->dev, "error creating driver attribute\n"); -+ goto region; -+ } -+ INIT_WORK(&transfer_wq, locomospi_do_transfer); -+ INIT_LIST_HEAD(&spidev->message_list); -+ spin_lock_init(&spidev->message_lock); -+ init_waitqueue_head(&spidev->waitqueue); -+ spidev->master=spi_alloc_master(&dev->dev,0); -+ if(!spidev->master){ -+ result=-ENOMEM; -+ goto region; -+ } -+ spidev->master->bus_num = 0; -+ spidev->master->num_chipselect = 0; -+ spidev->master->setup = locomospi_setup; -+ spidev->master->transfer = locomospi_transfer; -+ spidev->sdev = spi_new_device(spidev->master, &board); -+ if(!spidev->sdev){ -+ dev_err(&dev->dev, "failed to register spi device\n"); -+ goto master; -+ } -+/* result=request_irq(IRQ_LOCOMO_SPI_RFR, locomospi_rwready, SA_SHIRQ, "locomo-spi", (void*) spidev); -+ if(result) { -+ dev_err(&dev->dev, "Could not get IRQ: RFR\n"); -+ goto regdev; -+ } -+ result=request_irq(IRQ_LOCOMO_SPI_RFW, locomospi_rwready, SA_SHIRQ, "locomo-spi", (void*) spidev); -+ if(result) { -+ dev_err(&dev->dev, "Could not get IRQ: RFW\n"); -+ goto irq1; -+ } -+ result=request_irq(IRQ_LOCOMO_SPI_OVRN, locomospi_testisr, SA_SHIRQ, "locomo-spi", (void*) spidev); -+ if(result) { -+ dev_err(&dev->dev, "Could not get IRQ: OVRN\n"); -+ goto irq2; -+ }*/ -+/* result=request_irq(IRQ_LOCOMO_SPI_TEND, locomospi_testisr, SA_SHIRQ, "locomo-spi", (void*) spidev); -+ if(result) { -+ dev_err(&dev->dev, "Could not get IRQ: TEND\n"); -+ goto irq3; -+ }*/ -+ locomospi_reg_open(); -+ spidev->workqueue = create_singlethread_workqueue("locomo-spi"); -+ if(!spidev->workqueue){ -+ dev_err(&dev->dev, "failed to create workqueue\n"); -+ goto irq3; -+ } -+ result=spi_register_master(spidev->master); -+ if(result){ -+ dev_err(&dev->dev, "failed to register spimaster\n"); -+ goto wq; -+ } -+ return 0; -+wq: -+ destroy_workqueue(spidev->workqueue); -+irq3: -+// free_irq(IRQ_LOCOMO_SPI_OVRN, (void*) spidev); -+//irq2: -+// free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev); -+//irq1: -+// free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev); -+//regdev: -+ spi_unregister_device(spidev->sdev); -+master: -+ spi_master_put(spidev->master); -+region: -+ release_mem_region((unsigned long) dev->mapbase, dev->length); -+ kfree(spidev); -+ return result; -+ -+} -+ -+static int locomospi_remove(struct locomo_dev *dev) -+{ -+ spi_unregister_device(spidev->sdev); -+ spi_unregister_master(spidev->master); -+ destroy_workqueue(spidev->workqueue); -+ locomospi_reg_release(); -+// free_irq(IRQ_LOCOMO_SPI_TEND, (void*) spidev); -+// free_irq(IRQ_LOCOMO_SPI_OVRN, (void*) spidev); -+// free_irq(IRQ_LOCOMO_SPI_RFW, (void*) spidev); -+// free_irq(IRQ_LOCOMO_SPI_RFR, (void*) spidev); -+ spi_master_put(spidev->master); -+ release_mem_region((unsigned long) dev->mapbase, dev->length); -+ kfree(spidev); -+ return 0; -+} -+ -+ -+ -+static int __init locomospi_init(void) -+{ -+ int ret = locomo_driver_register(&locomo_spi_driver); -+ if (ret) -+ return ret; -+ -+ -+ return 0; -+} -+ -+static void __exit locomospi_exit(void) -+{ -+ locomo_driver_unregister(&locomo_spi_driver); -+} -+ -+module_init(locomospi_init); -+module_exit(locomospi_exit); -+ -+MODULE_AUTHOR("Thomas Kunze thommy@tabao.de"); -+MODULE_DESCRIPTION("Collie mmc driver"); -+MODULE_LICENSE("GPL"); -Index: linux-2.6.21/drivers/spi/locomo_spi.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.21/drivers/spi/locomo_spi.h 2007-07-03 21:40:52.000000000 +0200 -@@ -0,0 +1,37 @@ -+#include <asm/hardware/locomo.h> -+#ifndef __LOCOMO_SPI_H__ -+#define __LOCOMO_SPI_H__ -+#define IRQ_LOCOMO_CARDDETECT IRQ_LOCOMO_GPIO13 -+#define HIGH 1 -+#define LOW 0 -+struct locomospi_dev { -+ struct locomo_dev *ldev; -+ struct spi_master *master; -+ struct spi_device *sdev; -+ int card_power; -+ int clock_base; -+ int clock_mult; -+ unsigned long base; -+ u8 spimode; -+ wait_queue_head_t waitqueue; -+ struct workqueue_struct *workqueue; -+ struct list_head message_list; -+ spinlock_t message_lock; -+ irqreturn_t (*mmc_spi_isr)(int, void*); -+}; -+ -+ -+static irqreturn_t locomospi_cardisr(int, void*); -+static int locomospi_probe(struct locomo_dev*); -+static int locomospi_remove(struct locomo_dev*); -+static int locomospi_carddetect(void); -+static void locomospi_reg_open(void); -+static void locomospi_reg_release(void); -+static int tx(const char*, int); -+static int rx(char *, int); -+static void locomospi_togglecs(void); -+static void locomospi_power(int on); -+static int locomospi_suspend(struct locomo_dev *dev, pm_message_t state); -+static int locomospi_resume(struct locomo_dev *dev); -+static void locomospi_setcs(int high); -+#endif -Index: linux-2.6.21/drivers/spi/Makefile -=================================================================== ---- linux-2.6.21.orig/drivers/spi/Makefile 2007-04-26 05:08:32.000000000 +0200 -+++ linux-2.6.21/drivers/spi/Makefile 2007-07-03 21:41:16.000000000 +0200 -@@ -20,6 +20,7 @@ - obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o - obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o - obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o -+obj-$(CONFIG_SPI_LOCOMO) += locomo_spi.o - # ... add above this line ... - - # SPI protocol drivers (device/link on bus) |