Commit 2b3b1c668be539d897d2a9352bc8dca54467f425
Committed by
Albert ARIBAUD
1 parent
81f40345d1
Exists in
master
and in
57 other branches
ATMEL/PIO: Enable new feature of PIO on Atmel device
Enable new PIO feature supported by Atmel SoC. Using CPU_HAS_PIO3 micro to enable PIO new feature. Signed-off-by: Bo Shen <voice.shen@atmel.com> Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
Showing 2 changed files with 167 additions and 3 deletions Side-by-side Diff
arch/arm/include/asm/arch-at91/at91_pio.h
| ... | ... | @@ -66,14 +66,50 @@ |
| 66 | 66 | u32 puer; /* 0x64 Pull-up Enable Register */ |
| 67 | 67 | u32 pusr; /* 0x68 Pad Pull-up Status Register */ |
| 68 | 68 | u32 reserved4; |
| 69 | +#if defined(CPU_HAS_PIO3) | |
| 70 | + u32 abcdsr1; /* 0x70 Peripheral ABCD Select Register 1 */ | |
| 71 | + u32 abcdsr2; /* 0x74 Peripheral ABCD Select Register 2 */ | |
| 72 | + u32 reserved5[2]; | |
| 73 | + u32 ifscdr; /* 0x80 Input Filter SCLK Disable Register */ | |
| 74 | + u32 ifscer; /* 0x84 Input Filter SCLK Enable Register */ | |
| 75 | + u32 ifscsr; /* 0x88 Input Filter SCLK Status Register */ | |
| 76 | + u32 scdr; /* 0x8C SCLK Divider Debouncing Register */ | |
| 77 | + u32 ppddr; /* 0x90 Pad Pull-down Disable Register */ | |
| 78 | + u32 ppder; /* 0x94 Pad Pull-down Enable Register */ | |
| 79 | + u32 ppdsr; /* 0x98 Pad Pull-down Status Register */ | |
| 80 | + u32 reserved6; /* */ | |
| 81 | +#else | |
| 69 | 82 | u32 asr; /* 0x70 Select A Register */ |
| 70 | 83 | u32 bsr; /* 0x74 Select B Register */ |
| 71 | 84 | u32 absr; /* 0x78 AB Select Status Register */ |
| 72 | 85 | u32 reserved5[9]; /* */ |
| 86 | +#endif | |
| 73 | 87 | u32 ower; /* 0xA0 Output Write Enable Register */ |
| 74 | 88 | u32 owdr; /* 0xA4 Output Write Disable Register */ |
| 75 | - u32 owsr; /* OxA8 utput Write Status Register */ | |
| 89 | + u32 owsr; /* OxA8 Output Write Status Register */ | |
| 90 | +#if defined(CPU_HAS_PIO3) | |
| 91 | + u32 reserved7; /* */ | |
| 92 | + u32 aimer; /* 0xB0 Additional INT Modes Enable Register */ | |
| 93 | + u32 aimdr; /* 0xB4 Additional INT Modes Disable Register */ | |
| 94 | + u32 aimmr; /* 0xB8 Additional INT Modes Mask Register */ | |
| 95 | + u32 reserved8; /* */ | |
| 96 | + u32 esr; /* 0xC0 Edge Select Register */ | |
| 97 | + u32 lsr; /* 0xC4 Level Select Register */ | |
| 98 | + u32 elsr; /* 0xC8 Edge/Level Status Register */ | |
| 99 | + u32 reserved9; /* 0xCC */ | |
| 100 | + u32 fellsr; /* 0xD0 Falling /Low Level Select Register */ | |
| 101 | + u32 rehlsr; /* 0xD4 Rising /High Level Select Register */ | |
| 102 | + u32 frlhsr; /* 0xD8 Fall/Rise - Low/High Status Register */ | |
| 103 | + u32 reserved10; /* */ | |
| 104 | + u32 locksr; /* 0xE0 Lock Status */ | |
| 105 | + u32 wpmr; /* 0xE4 Write Protect Mode Register */ | |
| 106 | + u32 wpsr; /* 0xE8 Write Protect Status Register */ | |
| 107 | + u32 reserved11[5]; /* */ | |
| 108 | + u32 schmitt; /* 0x100 Schmitt Trigger Register */ | |
| 109 | + u32 reserved12[63]; | |
| 110 | +#else | |
| 76 | 111 | u32 reserved6[85]; |
| 112 | +#endif | |
| 77 | 113 | } at91_port_t; |
| 78 | 114 | |
| 79 | 115 | typedef union at91_pio { |
| ... | ... | @@ -94,6 +130,13 @@ |
| 94 | 130 | #ifdef CONFIG_AT91_GPIO |
| 95 | 131 | int at91_set_a_periph(unsigned port, unsigned pin, int use_pullup); |
| 96 | 132 | int at91_set_b_periph(unsigned port, unsigned pin, int use_pullup); |
| 133 | +#if defined(CPU_HAS_PIO3) | |
| 134 | +int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup); | |
| 135 | +int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup); | |
| 136 | +int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div); | |
| 137 | +int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on); | |
| 138 | +int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin); | |
| 139 | +#endif | |
| 97 | 140 | int at91_set_pio_input(unsigned port, unsigned pin, int use_pullup); |
| 98 | 141 | int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on); |
| 99 | 142 | int at91_set_pio_output(unsigned port, unsigned pin, int value); |
drivers/gpio/at91_gpio.c
| ... | ... | @@ -86,7 +86,14 @@ |
| 86 | 86 | mask = 1 << pin; |
| 87 | 87 | writel(mask, &pio->port[port].idr); |
| 88 | 88 | at91_set_pio_pullup(port, pin, use_pullup); |
| 89 | +#if defined(CPU_HAS_PIO3) | |
| 90 | + writel(readl(&pio->port[port].abcdsr1) & ~mask, | |
| 91 | + &pio->port[port].abcdsr1); | |
| 92 | + writel(readl(&pio->port[port].abcdsr2) & ~mask, | |
| 93 | + &pio->port[port].abcdsr2); | |
| 94 | +#else | |
| 89 | 95 | writel(mask, &pio->port[port].asr); |
| 96 | +#endif | |
| 90 | 97 | writel(mask, &pio->port[port].pdr); |
| 91 | 98 | } |
| 92 | 99 | return 0; |
| 93 | 100 | |
| 94 | 101 | |
| 95 | 102 | |
| ... | ... | @@ -104,13 +111,64 @@ |
| 104 | 111 | mask = 1 << pin; |
| 105 | 112 | writel(mask, &pio->port[port].idr); |
| 106 | 113 | at91_set_pio_pullup(port, pin, use_pullup); |
| 114 | +#if defined(CPU_HAS_PIO3) | |
| 115 | + writel(readl(&pio->port[port].abcdsr1) | mask, | |
| 116 | + &pio->port[port].abcdsr1); | |
| 117 | + writel(readl(&pio->port[port].abcdsr2) & ~mask, | |
| 118 | + &pio->port[port].abcdsr2); | |
| 119 | +#else | |
| 107 | 120 | writel(mask, &pio->port[port].bsr); |
| 121 | +#endif | |
| 108 | 122 | writel(mask, &pio->port[port].pdr); |
| 109 | 123 | } |
| 110 | 124 | return 0; |
| 111 | 125 | } |
| 112 | 126 | |
| 127 | +#if defined(CPU_HAS_PIO3) | |
| 113 | 128 | /* |
| 129 | + * mux the pin to the "C" internal peripheral role. | |
| 130 | + */ | |
| 131 | +int at91_set_c_periph(unsigned port, unsigned pin, int use_pullup) | |
| 132 | +{ | |
| 133 | + at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; | |
| 134 | + u32 mask; | |
| 135 | + | |
| 136 | + if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { | |
| 137 | + mask = 1 << pin; | |
| 138 | + writel(mask, &pio->port[port].idr); | |
| 139 | + at91_set_pio_pullup(port, pin, use_pullup); | |
| 140 | + writel(readl(&pio->port[port].abcdsr1) & ~mask, | |
| 141 | + &pio->port[port].abcdsr1); | |
| 142 | + writel(readl(&pio->port[port].abcdsr2) | mask, | |
| 143 | + &pio->port[port].abcdsr2); | |
| 144 | + writel(mask, &pio->port[port].pdr); | |
| 145 | + } | |
| 146 | + return 0; | |
| 147 | +} | |
| 148 | + | |
| 149 | +/* | |
| 150 | + * mux the pin to the "D" internal peripheral role. | |
| 151 | + */ | |
| 152 | +int at91_set_d_periph(unsigned port, unsigned pin, int use_pullup) | |
| 153 | +{ | |
| 154 | + at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; | |
| 155 | + u32 mask; | |
| 156 | + | |
| 157 | + if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { | |
| 158 | + mask = 1 << pin; | |
| 159 | + writel(mask, &pio->port[port].idr); | |
| 160 | + at91_set_pio_pullup(port, pin, use_pullup); | |
| 161 | + writel(readl(&pio->port[port].abcdsr1) | mask, | |
| 162 | + &pio->port[port].abcdsr1); | |
| 163 | + writel(readl(&pio->port[port].abcdsr2) | mask, | |
| 164 | + &pio->port[port].abcdsr2); | |
| 165 | + writel(mask, &pio->port[port].pdr); | |
| 166 | + } | |
| 167 | + return 0; | |
| 168 | +} | |
| 169 | +#endif | |
| 170 | + | |
| 171 | +/* | |
| 114 | 172 | * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and |
| 115 | 173 | * configure it for an input. |
| 116 | 174 | */ |
| 117 | 175 | |
| 118 | 176 | |
| 119 | 177 | |
| ... | ... | @@ -162,13 +220,76 @@ |
| 162 | 220 | |
| 163 | 221 | if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { |
| 164 | 222 | mask = 1 << pin; |
| 165 | - if (is_on) | |
| 223 | + if (is_on) { | |
| 224 | +#if defined(CPU_HAS_PIO3) | |
| 225 | + writel(mask, &pio->port[port].ifscdr); | |
| 226 | +#endif | |
| 166 | 227 | writel(mask, &pio->port[port].ifer); |
| 167 | - else | |
| 228 | + } else { | |
| 168 | 229 | writel(mask, &pio->port[port].ifdr); |
| 230 | + } | |
| 169 | 231 | } |
| 170 | 232 | return 0; |
| 171 | 233 | } |
| 234 | + | |
| 235 | +#if defined(CPU_HAS_PIO3) | |
| 236 | +/* | |
| 237 | + * enable/disable the debounce filter. | |
| 238 | + */ | |
| 239 | +int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div) | |
| 240 | +{ | |
| 241 | + at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; | |
| 242 | + u32 mask; | |
| 243 | + | |
| 244 | + if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { | |
| 245 | + mask = 1 << pin; | |
| 246 | + if (is_on) { | |
| 247 | + writel(mask, &pio->port[port].ifscer); | |
| 248 | + writel(div & PIO_SCDR_DIV, &pio->port[port].scdr); | |
| 249 | + writel(mask, &pio->port[port].ifer); | |
| 250 | + } else { | |
| 251 | + writel(mask, &pio->port[port].ifdr); | |
| 252 | + } | |
| 253 | + } | |
| 254 | + return 0; | |
| 255 | +} | |
| 256 | + | |
| 257 | +/* | |
| 258 | + * enable/disable the pull-down. | |
| 259 | + * If pull-up already enabled while calling the function, we disable it. | |
| 260 | + */ | |
| 261 | +int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on) | |
| 262 | +{ | |
| 263 | + at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; | |
| 264 | + u32 mask; | |
| 265 | + | |
| 266 | + if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { | |
| 267 | + mask = 1 << pin; | |
| 268 | + writel(mask, &pio->port[port].pudr); | |
| 269 | + if (is_on) | |
| 270 | + writel(mask, &pio->port[port].ppder); | |
| 271 | + else | |
| 272 | + writel(mask, &pio->port[port].ppddr); | |
| 273 | + } | |
| 274 | + return 0; | |
| 275 | +} | |
| 276 | + | |
| 277 | +/* | |
| 278 | + * disable Schmitt trigger | |
| 279 | + */ | |
| 280 | +int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin) | |
| 281 | +{ | |
| 282 | + at91_pio_t *pio = (at91_pio_t *) ATMEL_BASE_PIOA; | |
| 283 | + u32 mask; | |
| 284 | + | |
| 285 | + if ((port < ATMEL_PIO_PORTS) && (pin < 32)) { | |
| 286 | + mask = 1 << pin; | |
| 287 | + writel(readl(&pio->port[port].schmitt) | mask, | |
| 288 | + &pio->port[port].schmitt); | |
| 289 | + } | |
| 290 | + return 0; | |
| 291 | +} | |
| 292 | +#endif | |
| 172 | 293 | |
| 173 | 294 | /* |
| 174 | 295 | * enable/disable the multi-driver. This is only valid for output and |