Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/mach-sa1100/ssp.c
0004  *
0005  *  Copyright (C) 2003 Russell King.
0006  *
0007  *  Generic SSP driver.  This provides the generic core for simple
0008  *  IO-based SSP applications.
0009  */
0010 #include <linux/module.h>
0011 #include <linux/kernel.h>
0012 #include <linux/sched.h>
0013 #include <linux/errno.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/ioport.h>
0016 #include <linux/init.h>
0017 #include <linux/io.h>
0018 
0019 #include <mach/hardware.h>
0020 #include <mach/irqs.h>
0021 #include <asm/hardware/ssp.h>
0022 
0023 #define TIMEOUT 100000
0024 
0025 static irqreturn_t ssp_interrupt(int irq, void *dev_id)
0026 {
0027     unsigned int status = Ser4SSSR;
0028 
0029     if (status & SSSR_ROR)
0030         printk(KERN_WARNING "SSP: receiver overrun\n");
0031 
0032     Ser4SSSR = SSSR_ROR;
0033 
0034     return status ? IRQ_HANDLED : IRQ_NONE;
0035 }
0036 
0037 /**
0038  * ssp_write_word - write a word to the SSP port
0039  * @data: 16-bit, MSB justified data to write.
0040  *
0041  * Wait for a free entry in the SSP transmit FIFO, and write a data
0042  * word to the SSP port.  Wait for the SSP port to start sending
0043  * the data.
0044  *
0045  * The caller is expected to perform the necessary locking.
0046  *
0047  * Returns:
0048  *   %-ETIMEDOUT    timeout occurred
0049  *   0          success
0050  */
0051 int ssp_write_word(u16 data)
0052 {
0053     int timeout = TIMEOUT;
0054 
0055     while (!(Ser4SSSR & SSSR_TNF)) {
0056             if (!--timeout)
0057                 return -ETIMEDOUT;
0058         cpu_relax();
0059     }
0060 
0061     Ser4SSDR = data;
0062 
0063     timeout = TIMEOUT;
0064     while (!(Ser4SSSR & SSSR_BSY)) {
0065             if (!--timeout)
0066                 return -ETIMEDOUT;
0067         cpu_relax();
0068     }
0069 
0070     return 0;
0071 }
0072 
0073 /**
0074  * ssp_read_word - read a word from the SSP port
0075  *
0076  * Wait for a data word in the SSP receive FIFO, and return the
0077  * received data.  Data is LSB justified.
0078  *
0079  * Note: Currently, if data is not expected to be received, this
0080  * function will wait for ever.
0081  *
0082  * The caller is expected to perform the necessary locking.
0083  *
0084  * Returns:
0085  *   %-ETIMEDOUT    timeout occurred
0086  *   16-bit data    success
0087  */
0088 int ssp_read_word(u16 *data)
0089 {
0090     int timeout = TIMEOUT;
0091 
0092     while (!(Ser4SSSR & SSSR_RNE)) {
0093             if (!--timeout)
0094                 return -ETIMEDOUT;
0095         cpu_relax();
0096     }
0097 
0098     *data = (u16)Ser4SSDR;
0099 
0100     return 0;
0101 }
0102 
0103 /**
0104  * ssp_flush - flush the transmit and receive FIFOs
0105  *
0106  * Wait for the SSP to idle, and ensure that the receive FIFO
0107  * is empty.
0108  *
0109  * The caller is expected to perform the necessary locking.
0110  *
0111  * Returns:
0112  *   %-ETIMEDOUT    timeout occurred
0113  *   0          success
0114  */
0115 int ssp_flush(void)
0116 {
0117     int timeout = TIMEOUT * 2;
0118 
0119     do {
0120         while (Ser4SSSR & SSSR_RNE) {
0121                 if (!--timeout)
0122                     return -ETIMEDOUT;
0123             (void) Ser4SSDR;
0124         }
0125             if (!--timeout)
0126                 return -ETIMEDOUT;
0127     } while (Ser4SSSR & SSSR_BSY);
0128 
0129     return 0;
0130 }
0131 
0132 /**
0133  * ssp_enable - enable the SSP port
0134  *
0135  * Turn on the SSP port.
0136  */
0137 void ssp_enable(void)
0138 {
0139     Ser4SSCR0 |= SSCR0_SSE;
0140 }
0141 
0142 /**
0143  * ssp_disable - shut down the SSP port
0144  *
0145  * Turn off the SSP port, optionally powering it down.
0146  */
0147 void ssp_disable(void)
0148 {
0149     Ser4SSCR0 &= ~SSCR0_SSE;
0150 }
0151 
0152 /**
0153  * ssp_save_state - save the SSP configuration
0154  * @ssp: pointer to structure to save SSP configuration
0155  *
0156  * Save the configured SSP state for suspend.
0157  */
0158 void ssp_save_state(struct ssp_state *ssp)
0159 {
0160     ssp->cr0 = Ser4SSCR0;
0161     ssp->cr1 = Ser4SSCR1;
0162 
0163     Ser4SSCR0 &= ~SSCR0_SSE;
0164 }
0165 
0166 /**
0167  * ssp_restore_state - restore a previously saved SSP configuration
0168  * @ssp: pointer to configuration saved by ssp_save_state
0169  *
0170  * Restore the SSP configuration saved previously by ssp_save_state.
0171  */
0172 void ssp_restore_state(struct ssp_state *ssp)
0173 {
0174     Ser4SSSR = SSSR_ROR;
0175 
0176     Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
0177     Ser4SSCR1 = ssp->cr1;
0178     Ser4SSCR0 = ssp->cr0;
0179 }
0180 
0181 /**
0182  * ssp_init - setup the SSP port
0183  *
0184  * initialise and claim resources for the SSP port.
0185  *
0186  * Returns:
0187  *   %-ENODEV   if the SSP port is unavailable
0188  *   %-EBUSY    if the resources are already in use
0189  *   %0     on success
0190  */
0191 int ssp_init(void)
0192 {
0193     int ret;
0194 
0195     if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
0196         return -ENODEV;
0197 
0198     if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
0199         return -EBUSY;
0200     }
0201 
0202     Ser4SSSR = SSSR_ROR;
0203 
0204     ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
0205     if (ret)
0206         goto out_region;
0207 
0208     return 0;
0209 
0210  out_region:
0211     release_mem_region(__PREG(Ser4SSCR0), 0x18);
0212     return ret;
0213 }
0214 
0215 /**
0216  * ssp_exit - undo the effects of ssp_init
0217  *
0218  * release and free resources for the SSP port.
0219  */
0220 void ssp_exit(void)
0221 {
0222     Ser4SSCR0 &= ~SSCR0_SSE;
0223 
0224     free_irq(IRQ_Ser4SSP, NULL);
0225     release_mem_region(__PREG(Ser4SSCR0), 0x18);
0226 }
0227 
0228 MODULE_AUTHOR("Russell King");
0229 MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
0230 MODULE_LICENSE("GPL");
0231 
0232 EXPORT_SYMBOL(ssp_write_word);
0233 EXPORT_SYMBOL(ssp_read_word);
0234 EXPORT_SYMBOL(ssp_flush);
0235 EXPORT_SYMBOL(ssp_enable);
0236 EXPORT_SYMBOL(ssp_disable);
0237 EXPORT_SYMBOL(ssp_save_state);
0238 EXPORT_SYMBOL(ssp_restore_state);
0239 EXPORT_SYMBOL(ssp_init);
0240 EXPORT_SYMBOL(ssp_exit);