linux/arch/arm/mach-sa1100/ssp.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mach-sa1100/ssp.c
   3 *
   4 *  Copyright (C) 2003 Russell King.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 *  Generic SSP driver.  This provides the generic core for simple
  11 *  IO-based SSP applications.
  12 */
  13#include <linux/module.h>
  14#include <linux/kernel.h>
  15#include <linux/sched.h>
  16#include <linux/errno.h>
  17#include <linux/interrupt.h>
  18#include <linux/ioport.h>
  19#include <linux/init.h>
  20#include <linux/io.h>
  21
  22#include <mach/hardware.h>
  23#include <mach/irqs.h>
  24#include <asm/hardware/ssp.h>
  25
  26#define TIMEOUT 100000
  27
  28static irqreturn_t ssp_interrupt(int irq, void *dev_id)
  29{
  30        unsigned int status = Ser4SSSR;
  31
  32        if (status & SSSR_ROR)
  33                printk(KERN_WARNING "SSP: receiver overrun\n");
  34
  35        Ser4SSSR = SSSR_ROR;
  36
  37        return status ? IRQ_HANDLED : IRQ_NONE;
  38}
  39
  40/**
  41 * ssp_write_word - write a word to the SSP port
  42 * @data: 16-bit, MSB justified data to write.
  43 *
  44 * Wait for a free entry in the SSP transmit FIFO, and write a data
  45 * word to the SSP port.  Wait for the SSP port to start sending
  46 * the data.
  47 *
  48 * The caller is expected to perform the necessary locking.
  49 *
  50 * Returns:
  51 *   %-ETIMEDOUT        timeout occurred
  52 *   0                  success
  53 */
  54int ssp_write_word(u16 data)
  55{
  56        int timeout = TIMEOUT;
  57
  58        while (!(Ser4SSSR & SSSR_TNF)) {
  59                if (!--timeout)
  60                        return -ETIMEDOUT;
  61                cpu_relax();
  62        }
  63
  64        Ser4SSDR = data;
  65
  66        timeout = TIMEOUT;
  67        while (!(Ser4SSSR & SSSR_BSY)) {
  68                if (!--timeout)
  69                        return -ETIMEDOUT;
  70                cpu_relax();
  71        }
  72
  73        return 0;
  74}
  75
  76/**
  77 * ssp_read_word - read a word from the SSP port
  78 *
  79 * Wait for a data word in the SSP receive FIFO, and return the
  80 * received data.  Data is LSB justified.
  81 *
  82 * Note: Currently, if data is not expected to be received, this
  83 * function will wait for ever.
  84 *
  85 * The caller is expected to perform the necessary locking.
  86 *
  87 * Returns:
  88 *   %-ETIMEDOUT        timeout occurred
  89 *   16-bit data        success
  90 */
  91int ssp_read_word(u16 *data)
  92{
  93        int timeout = TIMEOUT;
  94
  95        while (!(Ser4SSSR & SSSR_RNE)) {
  96                if (!--timeout)
  97                        return -ETIMEDOUT;
  98                cpu_relax();
  99        }
 100
 101        *data = (u16)Ser4SSDR;
 102
 103        return 0;
 104}
 105
 106/**
 107 * ssp_flush - flush the transmit and receive FIFOs
 108 *
 109 * Wait for the SSP to idle, and ensure that the receive FIFO
 110 * is empty.
 111 *
 112 * The caller is expected to perform the necessary locking.
 113 *
 114 * Returns:
 115 *   %-ETIMEDOUT        timeout occurred
 116 *   0                  success
 117 */
 118int ssp_flush(void)
 119{
 120        int timeout = TIMEOUT * 2;
 121
 122        do {
 123                while (Ser4SSSR & SSSR_RNE) {
 124                        if (!--timeout)
 125                                return -ETIMEDOUT;
 126                        (void) Ser4SSDR;
 127                }
 128                if (!--timeout)
 129                        return -ETIMEDOUT;
 130        } while (Ser4SSSR & SSSR_BSY);
 131
 132        return 0;
 133}
 134
 135/**
 136 * ssp_enable - enable the SSP port
 137 *
 138 * Turn on the SSP port.
 139 */
 140void ssp_enable(void)
 141{
 142        Ser4SSCR0 |= SSCR0_SSE;
 143}
 144
 145/**
 146 * ssp_disable - shut down the SSP port
 147 *
 148 * Turn off the SSP port, optionally powering it down.
 149 */
 150void ssp_disable(void)
 151{
 152        Ser4SSCR0 &= ~SSCR0_SSE;
 153}
 154
 155/**
 156 * ssp_save_state - save the SSP configuration
 157 * @ssp: pointer to structure to save SSP configuration
 158 *
 159 * Save the configured SSP state for suspend.
 160 */
 161void ssp_save_state(struct ssp_state *ssp)
 162{
 163        ssp->cr0 = Ser4SSCR0;
 164        ssp->cr1 = Ser4SSCR1;
 165
 166        Ser4SSCR0 &= ~SSCR0_SSE;
 167}
 168
 169/**
 170 * ssp_restore_state - restore a previously saved SSP configuration
 171 * @ssp: pointer to configuration saved by ssp_save_state
 172 *
 173 * Restore the SSP configuration saved previously by ssp_save_state.
 174 */
 175void ssp_restore_state(struct ssp_state *ssp)
 176{
 177        Ser4SSSR = SSSR_ROR;
 178
 179        Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
 180        Ser4SSCR1 = ssp->cr1;
 181        Ser4SSCR0 = ssp->cr0;
 182}
 183
 184/**
 185 * ssp_init - setup the SSP port
 186 *
 187 * initialise and claim resources for the SSP port.
 188 *
 189 * Returns:
 190 *   %-ENODEV   if the SSP port is unavailable
 191 *   %-EBUSY    if the resources are already in use
 192 *   %0         on success
 193 */
 194int ssp_init(void)
 195{
 196        int ret;
 197
 198        if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
 199                return -ENODEV;
 200
 201        if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
 202                return -EBUSY;
 203        }
 204
 205        Ser4SSSR = SSSR_ROR;
 206
 207        ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
 208        if (ret)
 209                goto out_region;
 210
 211        return 0;
 212
 213 out_region:
 214        release_mem_region(__PREG(Ser4SSCR0), 0x18);
 215        return ret;
 216}
 217
 218/**
 219 * ssp_exit - undo the effects of ssp_init
 220 *
 221 * release and free resources for the SSP port.
 222 */
 223void ssp_exit(void)
 224{
 225        Ser4SSCR0 &= ~SSCR0_SSE;
 226
 227        free_irq(IRQ_Ser4SSP, NULL);
 228        release_mem_region(__PREG(Ser4SSCR0), 0x18);
 229}
 230
 231MODULE_AUTHOR("Russell King");
 232MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
 233MODULE_LICENSE("GPL");
 234
 235EXPORT_SYMBOL(ssp_write_word);
 236EXPORT_SYMBOL(ssp_read_word);
 237EXPORT_SYMBOL(ssp_flush);
 238EXPORT_SYMBOL(ssp_enable);
 239EXPORT_SYMBOL(ssp_disable);
 240EXPORT_SYMBOL(ssp_save_state);
 241EXPORT_SYMBOL(ssp_restore_state);
 242EXPORT_SYMBOL(ssp_init);
 243EXPORT_SYMBOL(ssp_exit);
 244