root/arch/arm/mach-sa1100/jornada720_ssp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. jornada_ssp_reverse
  2. jornada_ssp_byte
  3. jornada_ssp_inout
  4. jornada_ssp_start
  5. jornada_ssp_end
  6. jornada_ssp_probe
  7. jornada_ssp_remove
  8. jornada_ssp_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /**
   3  *  arch/arm/mac-sa1100/jornada720_ssp.c
   4  *
   5  *  Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
   6  *   Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl>
   7  *
   8  *  SSP driver for the HP Jornada 710/720/728
   9  */
  10 
  11 #include <linux/delay.h>
  12 #include <linux/errno.h>
  13 #include <linux/init.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/sched.h>
  18 #include <linux/io.h>
  19 
  20 #include <mach/hardware.h>
  21 #include <mach/jornada720.h>
  22 #include <asm/hardware/ssp.h>
  23 
  24 static DEFINE_SPINLOCK(jornada_ssp_lock);
  25 static unsigned long jornada_ssp_flags;
  26 
  27 /**
  28  * jornada_ssp_reverse - reverses input byte
  29  *
  30  * we need to reverse all data we receive from the mcu due to its physical location
  31  * returns : 01110111 -> 11101110
  32  */
  33 inline u8 jornada_ssp_reverse(u8 byte)
  34 {
  35         return
  36                 ((0x80 & byte) >> 7) |
  37                 ((0x40 & byte) >> 5) |
  38                 ((0x20 & byte) >> 3) |
  39                 ((0x10 & byte) >> 1) |
  40                 ((0x08 & byte) << 1) |
  41                 ((0x04 & byte) << 3) |
  42                 ((0x02 & byte) << 5) |
  43                 ((0x01 & byte) << 7);
  44 };
  45 EXPORT_SYMBOL(jornada_ssp_reverse);
  46 
  47 /**
  48  * jornada_ssp_byte - waits for ready ssp bus and sends byte
  49  *
  50  * waits for fifo buffer to clear and then transmits, if it doesn't then we will
  51  * timeout after <timeout> rounds. Needs mcu running before its called.
  52  *
  53  * returns : %mcu output on success
  54  *         : %-ETIMEDOUT on timeout
  55  */
  56 int jornada_ssp_byte(u8 byte)
  57 {
  58         int timeout = 400000;
  59         u16 ret;
  60 
  61         while ((GPLR & GPIO_GPIO10)) {
  62                 if (!--timeout) {
  63                         printk(KERN_WARNING "SSP: timeout while waiting for transmit\n");
  64                         return -ETIMEDOUT;
  65                 }
  66                 cpu_relax();
  67         }
  68 
  69         ret = jornada_ssp_reverse(byte) << 8;
  70 
  71         ssp_write_word(ret);
  72         ssp_read_word(&ret);
  73 
  74         return jornada_ssp_reverse(ret);
  75 };
  76 EXPORT_SYMBOL(jornada_ssp_byte);
  77 
  78 /**
  79  * jornada_ssp_inout - decide if input is command or trading byte
  80  *
  81  * returns : (jornada_ssp_byte(byte)) on success
  82  *         : %-ETIMEDOUT on timeout failure
  83  */
  84 int jornada_ssp_inout(u8 byte)
  85 {
  86         int ret, i;
  87 
  88         /* true means command byte */
  89         if (byte != TXDUMMY) {
  90                 ret = jornada_ssp_byte(byte);
  91                 /* Proper return to commands is TxDummy */
  92                 if (ret != TXDUMMY) {
  93                         for (i = 0; i < 256; i++)/* flushing bus */
  94                                 if (jornada_ssp_byte(TXDUMMY) == -1)
  95                                         break;
  96                         return -ETIMEDOUT;
  97                 }
  98         } else /* Exchange TxDummy for data */
  99                 ret = jornada_ssp_byte(TXDUMMY);
 100 
 101         return ret;
 102 };
 103 EXPORT_SYMBOL(jornada_ssp_inout);
 104 
 105 /**
 106  * jornada_ssp_start - enable mcu
 107  *
 108  */
 109 void jornada_ssp_start(void)
 110 {
 111         spin_lock_irqsave(&jornada_ssp_lock, jornada_ssp_flags);
 112         GPCR = GPIO_GPIO25;
 113         udelay(50);
 114         return;
 115 };
 116 EXPORT_SYMBOL(jornada_ssp_start);
 117 
 118 /**
 119  * jornada_ssp_end - disable mcu and turn off lock
 120  *
 121  */
 122 void jornada_ssp_end(void)
 123 {
 124         GPSR = GPIO_GPIO25;
 125         spin_unlock_irqrestore(&jornada_ssp_lock, jornada_ssp_flags);
 126         return;
 127 };
 128 EXPORT_SYMBOL(jornada_ssp_end);
 129 
 130 static int jornada_ssp_probe(struct platform_device *dev)
 131 {
 132         int ret;
 133 
 134         GPSR = GPIO_GPIO25;
 135 
 136         ret = ssp_init();
 137 
 138         /* worked fine, lets not bother with anything else */
 139         if (!ret) {
 140                 printk(KERN_INFO "SSP: device initialized with irq\n");
 141                 return ret;
 142         }
 143 
 144         printk(KERN_WARNING "SSP: initialization failed, trying non-irq solution \n");
 145 
 146         /* init of Serial 4 port */
 147         Ser4MCCR0 = 0;
 148         Ser4SSCR0 = 0x0387;
 149         Ser4SSCR1 = 0x18;
 150 
 151         /* clear out any left over data */
 152         ssp_flush();
 153 
 154         /* enable MCU */
 155         jornada_ssp_start();
 156 
 157         /* see if return value makes sense */
 158         ret = jornada_ssp_inout(GETBRIGHTNESS);
 159 
 160         /* seems like it worked, just feed it with TxDummy to get rid of data */
 161         if (ret == TXDUMMY)
 162                 jornada_ssp_inout(TXDUMMY);
 163 
 164         jornada_ssp_end();
 165 
 166         /* failed, lets just kill everything */
 167         if (ret == -ETIMEDOUT) {
 168                 printk(KERN_WARNING "SSP: attempts failed, bailing\n");
 169                 ssp_exit();
 170                 return -ENODEV;
 171         }
 172 
 173         /* all fine */
 174         printk(KERN_INFO "SSP: device initialized\n");
 175         return 0;
 176 };
 177 
 178 static int jornada_ssp_remove(struct platform_device *dev)
 179 {
 180         /* Note that this doesn't actually remove the driver, since theres nothing to remove
 181          * It just makes sure everything is turned off */
 182         GPSR = GPIO_GPIO25;
 183         ssp_exit();
 184         return 0;
 185 };
 186 
 187 struct platform_driver jornadassp_driver = {
 188         .probe  = jornada_ssp_probe,
 189         .remove = jornada_ssp_remove,
 190         .driver = {
 191                 .name   = "jornada_ssp",
 192         },
 193 };
 194 
 195 static int __init jornada_ssp_init(void)
 196 {
 197         return platform_driver_register(&jornadassp_driver);
 198 }
 199 
 200 module_init(jornada_ssp_init);

/* [<][>][^][v][top][bottom][index][help] */