@ -8,16 +8,6 @@
* SPDX - License - Identifier : GPL - 2.0 +
*/
/*
* WARNING :
*
* As the code is right now , it expects all PIO ports A , B , C , . . .
* to be evenly spaced in the memory map :
* ATMEL_BASE_PIOA + port * sizeof at91pio_t
* This might not necessaryly be true in future Atmel SoCs .
* This code should be fixed to use a pointer array to the ports .
*/
# include <config.h>
# include <common.h>
# include <asm/io.h>
@ -25,19 +15,42 @@
# include <asm/arch/hardware.h>
# include <asm/arch/at91_pio.h>
static struct at91_port * at91_pio_get_port ( unsigned port )
{
switch ( port ) {
case AT91_PIO_PORTA :
return ( struct at91_port * ) ATMEL_BASE_PIOA ;
case AT91_PIO_PORTB :
return ( struct at91_port * ) ATMEL_BASE_PIOB ;
case AT91_PIO_PORTC :
return ( struct at91_port * ) ATMEL_BASE_PIOC ;
# if (ATMEL_PIO_PORTS > 3)
case AT91_PIO_PORTD :
return ( struct at91_port * ) ATMEL_BASE_PIOD ;
# if (ATMEL_PIO_PORTS > 4)
case AT91_PIO_PORTE :
return ( struct at91_port * ) ATMEL_BASE_PIOE ;
# endif
# endif
default :
return NULL ;
}
}
int at91_set_pio_pullup ( unsigned port , unsigned pin , int use_pullup )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
if ( use_pullup )
writel ( 1 < < pin , & pio - > port [ port ] . puer ) ;
writel ( 1 < < pin , & at91_ port - > puer ) ;
else
writel ( 1 < < pin , & pio - > port [ port ] . pudr ) ;
writel ( mask , & pio - > port [ port ] . per ) ;
writel ( 1 < < pin , & at91_ port - > pudr ) ;
writel ( mask , & at91_ port - > per ) ;
}
return 0 ;
}
@ -46,15 +59,16 @@ int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
*/
int at91_set_pio_periph ( unsigned port , unsigned pin , int use_pullup )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . idr ) ;
writel ( mask , & at91_ port - > idr ) ;
at91_set_pio_pullup ( port , pin , use_pullup ) ;
writel ( mask , & pi o - > port [ port ] . per ) ;
writel ( mask , & at91_ port - > per ) ;
}
return 0 ;
}
@ -63,23 +77,24 @@ int at91_set_pio_periph(unsigned port, unsigned pin, int use_pullup)
*/
int at91_set_a_periph ( unsigned port , unsigned pin , int use_pullup )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . idr ) ;
writel ( mask , & at91_ port - > idr ) ;
at91_set_pio_pullup ( port , pin , use_pullup ) ;
# if defined(CPU_HAS_PIO3)
writel ( readl ( & pi o - > port [ port ] . abcdsr1 ) & ~ mask ,
& pio - > port [ port ] . abcdsr1 ) ;
writel ( readl ( & pi o - > port [ port ] . abcdsr2 ) & ~ mask ,
& pio - > port [ port ] . abcdsr2 ) ;
writel ( readl ( & at91_ port - > abcdsr1 ) & ~ mask ,
& at91_port - > abcdsr1 ) ;
writel ( readl ( & at91_ port - > abcdsr2 ) & ~ mask ,
& at91_port - > abcdsr2 ) ;
# else
writel ( mask , & pi o - > port [ port ] . asr ) ;
writel ( mask , & at91_ port - > asr ) ;
# endif
writel ( mask , & pi o - > port [ port ] . pdr ) ;
writel ( mask , & at91_ port - > pdr ) ;
}
return 0 ;
}
@ -88,23 +103,24 @@ int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup)
*/
int at91_set_b_periph ( unsigned port , unsigned pin , int use_pullup )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . idr ) ;
writel ( mask , & at91_ port - > idr ) ;
at91_set_pio_pullup ( port , pin , use_pullup ) ;
# if defined(CPU_HAS_PIO3)
writel ( readl ( & pi o - > port [ port ] . abcdsr1 ) | mask ,
& pio - > port [ port ] . abcdsr1 ) ;
writel ( readl ( & pi o - > port [ port ] . abcdsr2 ) & ~ mask ,
& pio - > port [ port ] . abcdsr2 ) ;
writel ( readl ( & at91_ port - > abcdsr1 ) | mask ,
& at91_port - > abcdsr1 ) ;
writel ( readl ( & at91_ port - > abcdsr2 ) & ~ mask ,
& at91_port - > abcdsr2 ) ;
# else
writel ( mask , & pi o - > port [ port ] . bsr ) ;
writel ( mask , & at91_ port - > bsr ) ;
# endif
writel ( mask , & pi o - > port [ port ] . pdr ) ;
writel ( mask , & at91_ port - > pdr ) ;
}
return 0 ;
}
@ -114,19 +130,20 @@ int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup)
*/
int at91_set_c_periph ( unsigned port , unsigned pin , int use_pullup )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . idr ) ;
writel ( mask , & at91_ port - > idr ) ;
at91_set_pio_pullup ( port , pin , use_pullup ) ;
writel ( readl ( & pi o - > port [ port ] . abcdsr1 ) & ~ mask ,
& pio - > port [ port ] . abcdsr1 ) ;
writel ( readl ( & pi o - > port [ port ] . abcdsr2 ) | mask ,
& pio - > port [ port ] . abcdsr2 ) ;
writel ( mask , & pi o - > port [ port ] . pdr ) ;
writel ( readl ( & at91_ port - > abcdsr1 ) & ~ mask ,
& at91_port - > abcdsr1 ) ;
writel ( readl ( & at91_ port - > abcdsr2 ) | mask ,
& at91_port - > abcdsr2 ) ;
writel ( mask , & at91_ port - > pdr ) ;
}
return 0 ;
}
@ -135,19 +152,20 @@ int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup)
*/
int at91_set_d_periph ( unsigned port , unsigned pin , int use_pullup )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . idr ) ;
writel ( mask , & at91_ port - > idr ) ;
at91_set_pio_pullup ( port , pin , use_pullup ) ;
writel ( readl ( & pi o - > port [ port ] . abcdsr1 ) | mask ,
& pio - > port [ port ] . abcdsr1 ) ;
writel ( readl ( & pi o - > port [ port ] . abcdsr2 ) | mask ,
& pio - > port [ port ] . abcdsr2 ) ;
writel ( mask , & pi o - > port [ port ] . pdr ) ;
writel ( readl ( & at91_ port - > abcdsr1 ) | mask ,
& at91_port - > abcdsr1 ) ;
writel ( readl ( & at91_ port - > abcdsr2 ) | mask ,
& at91_port - > abcdsr2 ) ;
writel ( mask , & at91_ port - > pdr ) ;
}
return 0 ;
}
# endif
@ -158,16 +176,17 @@ int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup)
*/
int at91_set_pio_input ( unsigned port , u32 pin , int use_pullup )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . idr ) ;
writel ( mask , & at91_ port - > idr ) ;
at91_set_pio_pullup ( port , pin , use_pullup ) ;
writel ( mask , & pi o - > port [ port ] . odr ) ;
writel ( mask , & pi o - > port [ port ] . per ) ;
writel ( mask , & at91_ port - > odr ) ;
writel ( mask , & at91_ port - > per ) ;
}
return 0 ;
}
@ -177,20 +196,21 @@ int at91_set_pio_input(unsigned port, u32 pin, int use_pullup)
*/
int at91_set_pio_output ( unsigned port , u32 pin , int value )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . idr ) ;
writel ( mask , & pi o - > port [ port ] . pudr ) ;
writel ( mask , & at91_ port - > idr ) ;
writel ( mask , & at91_ port - > pudr ) ;
if ( value )
writel ( mask , & pi o - > port [ port ] . sodr ) ;
writel ( mask , & at91_ port - > sodr ) ;
else
writel ( mask , & pi o - > port [ port ] . codr ) ;
writel ( mask , & pi o - > port [ port ] . oer ) ;
writel ( mask , & pi o - > port [ port ] . per ) ;
writel ( mask , & at91_ port - > codr ) ;
writel ( mask , & at91_ port - > oer ) ;
writel ( mask , & at91_ port - > per ) ;
}
return 0 ;
}
@ -199,20 +219,21 @@ int at91_set_pio_output(unsigned port, u32 pin, int value)
*/
int at91_set_pio_deglitch ( unsigned port , unsigned pin , int is_on )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
if ( is_on ) {
# if defined(CPU_HAS_PIO3)
writel ( mask , & pi o - > port [ port ] . ifscdr ) ;
writel ( mask , & at91_ port - > ifscdr ) ;
# endif
writel ( mask , & pi o - > port [ port ] . ifer ) ;
writel ( mask , & at91_ port - > ifer ) ;
} else {
writel ( mask , & pi o - > port [ port ] . ifdr ) ;
writel ( mask , & at91_ port - > ifdr ) ;
}
}
return 0 ;
}
@ -222,19 +243,20 @@ int at91_set_pio_deglitch(unsigned port, unsigned pin, int is_on)
*/
int at91_set_pio_debounce ( unsigned port , unsigned pin , int is_on , int div )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
if ( is_on ) {
writel ( mask , & pi o - > port [ port ] . ifscer ) ;
writel ( div & PIO_SCDR_DIV , & pi o - > port [ port ] . scdr ) ;
writel ( mask , & pi o - > port [ port ] . ifer ) ;
writel ( mask , & at91_ port - > ifscer ) ;
writel ( div & PIO_SCDR_DIV , & at91_ port - > scdr ) ;
writel ( mask , & at91_ port - > ifer ) ;
} else {
writel ( mask , & pi o - > port [ port ] . ifdr ) ;
writel ( mask , & at91_ port - > ifdr ) ;
}
}
return 0 ;
}
@ -244,17 +266,18 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div)
*/
int at91_set_pio_pulldown ( unsigned port , unsigned pin , int is_on )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( mask , & pi o - > port [ port ] . pudr ) ;
writel ( mask , & at91_ port - > pudr ) ;
if ( is_on )
writel ( mask , & pi o - > port [ port ] . ppder ) ;
writel ( mask , & at91_ port - > ppder ) ;
else
writel ( mask , & pi o - > port [ port ] . ppddr ) ;
writel ( mask , & at91_ port - > ppddr ) ;
}
return 0 ;
}
@ -263,14 +286,15 @@ int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
*/
int at91_set_pio_disable_schmitt_trig ( unsigned port , unsigned pin )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
writel ( readl ( & pi o - > port [ port ] . schmitt ) | mask ,
& pio - > port [ port ] . schmitt ) ;
writel ( readl ( & at91_ port - > schmitt ) | mask ,
& at91_port - > schmitt ) ;
}
return 0 ;
}
# endif
@ -281,16 +305,17 @@ int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin)
*/
int at91_set_pio_multi_drive ( unsigned port , unsigned pin , int is_on )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
if ( is_on )
writel ( mask , & pi o - > port [ port ] . mder ) ;
writel ( mask , & at91_ port - > mder ) ;
else
writel ( mask , & pi o - > port [ port ] . mddr ) ;
writel ( mask , & at91_ port - > mddr ) ;
}
return 0 ;
}
@ -299,16 +324,17 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on)
*/
int at91_set_pio_value ( unsigned port , unsigned pin , int value )
{
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
if ( value )
writel ( mask , & pi o - > port [ port ] . sodr ) ;
writel ( mask , & at91_ port - > sodr ) ;
else
writel ( mask , & pi o - > port [ port ] . codr ) ;
writel ( mask , & at91_ port - > codr ) ;
}
return 0 ;
}
@ -317,13 +343,13 @@ int at91_set_pio_value(unsigned port, unsigned pin, int value)
*/
int at91_get_pio_value ( unsigned port , unsigned pin )
{
u32 pdsr = 0 ;
at91_pio_t * pio = ( at91_pio_t * ) ATMEL_BASE_PIOA ;
u32 mask ;
struct at91_port * at91_port = at91_pio_get_port ( port ) ;
u32 pdsr = 0 , mask ;
if ( ( port < ATMEL_PIO_PORTS ) & & ( pin < 32 ) ) {
if ( at91_port & & ( pin < 32 ) ) {
mask = 1 < < pin ;
pdsr = readl ( & pi o - > port [ port ] . pdsr ) & mask ;
pdsr = readl ( & at91_ port - > pdsr ) & mask ;
}
return pdsr ! = 0 ;
}