ppc32-8xx: Generic pin interface
PATCH 1/1 ppc32-8xx: Generic pin interface
8xx pin generic interface.
---
commit 978475b1cf2b5b060bd07321ec482918966ac20b
tree b6b43444da43746669759d7313012e058fe658c5
parent 83f5e0be8db948f28442dd279f6472bd3367ea45
author Pantelis Antoniou <[email protected]> Tue, 06 Dec 2005 23:16:45 +0200 committer Pantelis Antoniou <[email protected]> Tue, 06 Dec 2005 23:16:45 +0200
include/asm-ppc/8xx_pin.h | 206 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 206 insertions(+), 0 deletions(-)
include/asm-ppc/8xx_pin.h new file +206 -0
@@ -0,0 +1,206 @@ +/* +* A way to access fast the PORT pins of 8xx systems. +* +* Copyright (c) 2005 Pantelis Antoniou <[email protected]> +* Dan Malek <[email protected]> +* +*/ +#ifndef __8XX_PIN_H +#define __8XX_PIN_H + +#include <asm/8xx_immap.h> +#include <asm/commproc.h> + +/* + +A few words about this. Yes the macros are a bit weird and hard to follow +but it is done for two reasons. + +1) The implementation is very fast. The resulting set & clr port bit code +is the minimal possible. One load, one and/or, one store. + +2) The pin definition for each pin is quite clear. + +For example let's take two pins called RXD, TXD. +They are connected to PC6 & PE12. + +We define them as simply: + +#define RXD_PORT PORTC +#define RXD_BIT 6 + +#define TXD_PORT PORTE +#define TXD_BIT 12 + +To configure RXD as an input, and TXD as an output do: + +_PIN_CFG_IN(RXD) +_PIN_CFG_OUT(TXD) + +To read RXD do: + +_PIN_GET(RXD) + +To set TXD do: + +_PIN_SET(TXD, 0|1) + +Please take note that we assume that IMAP_ADDR is a constant define. +This code will *not* work with ioremaped IMAP. + +*/ + +/********************************************************************************/ + +/* shorthand for the ports data registers */ +#define PORTA (((volatile immap_t *)IMAP_ADDR)->im_ioport.iop_padat) +#define PORTB (((volatile immap_t *)IMAP_ADDR)->im_cpm.cp_pbdat) +#define PORTC (((volatile immap_t *)IMAP_ADDR)->im_ioport.iop_pcdat) +#define PORTD (((volatile immap_t *)IMAP_ADDR)->im_ioport.iop_pddat) +#define PORTE (((volatile immap_t *)IMAP_ADDR)->im_cpm.cp_pedat) + +/********************************************************************************/ + +#define PIN_PORT_EQ (p, x) ((void *) & x ## _PORT == (void *) & p) +#define PIN_PORT_NE (p, x) ((void *) & x ## _PORT != (void *) & p) + +#define PIN_PORT_RW (x) (PIN_PORT_NE(PORTXWO, x) && PIN_PORT_NE(PORTXRO, x)) +#define PIN_PORT_RO (x) PIN_PORT_EQ(PORTXRO, x) +#define PIN_PORT_WO (x) PIN_PORT_EQ(PORTXWO, x) + +/********************************************************************************/ + +#define PIN_SFT (x) ((sizeof(x ## _PORT) * 8 - 1) - x ## _BIT) +#define PIN_MSK (x) (1U << PIN_SFT(x)) + +/********************************************************************************/ + +/* normal m8xx pins */ +#define _PIN_HI (x) \ + do { \ + x ## _PORT |= PIN_MSK(x); \ + } while(0) + +#define _PIN_LO (x) \ + do { \ + x ## _PORT &= ~PIN_MSK(x); \ + } while(0) + +#define _PIN_TGL (x) \ + do { \ + x ## _PORT ^= PIN_MSK(x); \ + } while(0) + +#define _PIN_GET (x) \ + (!!(x ## _PORT & PIN_MSK(x))) + +#define _PIN_SET (x, v) \ + do { \ + if (__builtin_constant_p(v)) { \ + if ((v) != 0) \ + _PIN_HI(x); \ + else \ + _PIN_LO(x); \ + } else \ + x ## _PORT = ( x ## _PORT & ~PIN_MSK(x)) | (!!(v) << PIN_SFT(x)); \ + } while(0) + +#define _PIN_CFG_IN (x) \ + do { \ + if (PIN_PORT_EQ(PORTA, x)) \ + PORTA_config(PIN_MSK(x), 0, 0); \ + if (PIN_PORT_EQ(PORTB, x)) \ + PORTB_config(PIN_MSK(x), 0, 0); \ + if (PIN_PORT_EQ(PORTC, x)) \ + PORTC_config(PIN_MSK(x), 0, 0); \ + if (PIN_PORT_EQ(PORTD, x)) \ + PORTD_config(PIN_MSK(x), 0, 0); \ + if (PIN_PORT_EQ(PORTE, x)) \ + PORTE_config(PIN_MSK(x), 0, 0); \ + } while(0) + +#define _PIN_CFG_INT_ANY (x) \ + do { \ + if (PIN_PORT_EQ(PORTC, x)) \ + PORTC_config(PIN_MSK(x), 0, 0); \ + } while(0) + +#define _PIN_CFG_INT_FALL (x) \ + do { \ + if (PIN_PORT_EQ(PORTC, x)) \ + PORTC_config(PIN_MSK(x), 0, 0); \ + } while(0) + +#define _PIN_CFG_OUT (x, v) \ + do { \ + _PIN_SET(x, v); \ + if (PIN_PORT_EQ(PORTA, x)) \ + PORTA_config(0, PIN_MSK(x), 0); \ + if (PIN_PORT_EQ(PORTB, x)) \ + PORTB_config(0, PIN_MSK(x), 0); \ + if (PIN_PORT_EQ(PORTC, x)) \ + PORTC_config(0, PIN_MSK(x), 0); \ + if (PIN_PORT_EQ(PORTD, x)) \ + PORTD_config(0, PIN_MSK(x), 0); \ + if (PIN_PORT_EQ(PORTE, x)) \ + PORTE_config(0, PIN_MSK(x), 0); \ + } while(0) + +#define _PIN_CFG_OUT_HI (x) _PIN_CFG_OUT(x, 1) +#define _PIN_CFG_OUT_LO (x) _PIN_CFG_OUT(x, 0) + +#ifndef __ASSEMBLY__ + +static inline void PORTA_config (uint inmsk,uint outmsk,uint dummy) +{ +volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR ; +ushort msk = (ushort )inmsk | (ushort )outmsk; + + imap->im_ioport.iop_padir = (imap->im_ioport.iop_padir & ~(ushort )inmsk) | (ushort )outmsk; + imap->im_ioport.iop_paodr &= ~msk; + imap->im_ioport.iop_papar &= ~msk; +} + +static inline void PORTB_config (uint inmsk,uint outmsk,uint dummy) +{ +volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR ; +uint msk = inmsk | outmsk; + + imap->im_cpm.cp_pbdir = (imap->im_cpm.cp_pbdir & ~inmsk) | outmsk; + imap->im_cpm.cp_pbodr &= ~msk; + imap->im_cpm.cp_pbpar &= ~msk; +} + +static inline void PORTC_config (uint inmsk,uint outmsk,uint fallmsk) +{ +volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR ; +ushort msk = (ushort )inmsk | (ushort )outmsk; + + imap->im_ioport.iop_pcdir = (imap->im_ioport.iop_pcdir & ~(ushort )inmsk) | (ushort )outmsk; + imap->im_ioport.iop_pcso &= ~msk; + imap->im_ioport.iop_pcint = (imap->im_ioport.iop_pcint & ~(ushort )inmsk) | ((ushort )fallmsk & (ushort )inmsk); + imap->im_ioport.iop_pcpar &= ~msk; +} + +static inline void PORTD_config (uint inmsk,uint outmsk,uint dummy) +{ +volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR ; +ushort msk = (ushort )inmsk | (ushort )outmsk; + + imap->im_ioport.iop_pddir = (imap->im_ioport.iop_pddir & ~(ushort )inmsk) | (ushort )outmsk; + imap->im_ioport.iop_pdpar &= ~msk; +} + +static inline void PORTE_config (uint inmsk,uint outmsk,uint dummy) +{ +volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR ; +uint msk = inmsk | outmsk; + + imap->im_cpm.cp_pedir = (imap->im_cpm.cp_pedir & ~inmsk) | outmsk; + imap->im_cpm.cp_peodr &= ~msk; + imap->im_cpm.cp_pepar &= ~msk; +} + +#endif /* __ASSEMBLY */ + +#endif