The Pedigree Project  0.1
Gpio.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "Gpio.h"
21 #include "pedigree/kernel/Log.h"
22 
23 Gpio Gpio::m_Instance;
24 
25 void Gpio::clearpin(int pin)
26 {
27  // Grab the GPIO MMIO range for the pin
28  int base = 0;
29  volatile uint32_t *gpio = getGpioForPin(pin, &base);
30  if (!gpio)
31  {
32  NOTICE(
33  "GPIO::clearpin - no GPIO found for pin " << Dec << pin << Hex
34  << ".");
35  return;
36  }
37 
38  // Write to the CLEARDATAOUT register
39  gpio[0x24] = (1 << base);
40 }
41 
42 void Gpio::drivepin(int pin)
43 {
44  // Grab the GPIO MMIO range for the pin
45  int base = 0;
46  volatile uint32_t *gpio = getGpioForPin(pin, &base);
47  if (!gpio)
48  {
49  NOTICE(
50  "GPIO::drivepin - no GPIO found for pin " << Dec << pin << Hex
51  << ".");
52  return;
53  }
54 
55  // Write to the SETDATAOUT register. We can set a specific bit in
56  // this register without needing to maintain the state of a full
57  // 32-bit register (zeroes have no effect).
58  gpio[0x25] = (1 << base);
59 }
60 
61 bool Gpio::pinstate(int pin)
62 {
63  // Grab the GPIO MMIO range for the pin
64  int base = 0;
65  volatile uint32_t *gpio = getGpioForPin(pin, &base);
66  if (!gpio)
67  {
68  NOTICE(
69  "GPIO::pinstate - no GPIO found for pin " << Dec << pin << Hex
70  << ".");
71  return false;
72  }
73 
74  return (gpio[0x25] & (1 << base));
75 }
76 
77 int Gpio::capturepin(int pin)
78 {
79  // Grab the GPIO MMIO range for the pin
80  int base = 0;
81  volatile uint32_t *gpio = getGpioForPin(pin, &base);
82  if (!gpio)
83  {
84  NOTICE(
85  "GPIO::capturepin - no GPIO found for pin " << Dec << pin << Hex
86  << ".");
87  return 0;
88  }
89 
90  // Read the data from the pin
91  return (gpio[0xE] & (1 << base)) >> (base ? base - 1 : 0);
92 }
93 
94 void Gpio::enableoutput(int pin)
95 {
96  // Grab the GPIO MMIO range for the pin
97  int base = 0;
98  volatile uint32_t *gpio = getGpioForPin(pin, &base);
99  if (!gpio)
100  {
101  NOTICE(
102  "GPIO::enableoutput - no GPIO found for pin " << Dec << pin << Hex
103  << ".");
104  return;
105  }
106 
107  // Set the pin as an output (if it's an input, the bit is set)
108  if (gpio[0xD] & (1 << base))
109  gpio[0xD] ^= (1 << base);
110 }
111 
112 void Gpio::initspecific(int n, volatile uint32_t *gpio)
113 {
114  if (!gpio)
115  return;
116 
117  // Write information about it
118  unsigned int rev = gpio[0];
119  NOTICE(
120  "GPIO" << Dec << n << Hex << " at " << reinterpret_cast<uintptr_t>(gpio)
121  << ": revision " << Dec << ((rev & 0xF0) >> 4) << "."
122  << (rev & 0xF) << Hex << ".");
123 
124  // 1. Perform a software reset of the GPIO.
125  gpio[0x4] = 2;
126  while (!(gpio[0x5] & 1))
127  ; // Poll GPIO_SYSSTATUS, bit 0
128 
129  // 2. Disable all IRQs
130  gpio[0x7] = 0; // GPIO_IRQENABLE1
131  gpio[0xB] = 0; // GPIO_IRQENABLE2
132 
133  // 3. Enable the module
134  gpio[0xC] = 0;
135 }
136 
137 volatile uint32_t *Gpio::getGpioForPin(int pin, int *bit)
138 {
139  volatile uint32_t *gpio = 0;
140  if (pin < 32)
141  {
142  *bit = pin;
143  gpio = reinterpret_cast<volatile uint32_t *>(m_Gpio1.virtualAddress());
144  }
145  else if ((pin >= 34) && (pin < 64))
146  {
147  *bit = pin - 34;
148  gpio = reinterpret_cast<volatile uint32_t *>(m_Gpio2.virtualAddress());
149  }
150  else if ((pin >= 64) && (pin < 96))
151  {
152  *bit = pin - 64;
153  gpio = reinterpret_cast<volatile uint32_t *>(m_Gpio3.virtualAddress());
154  }
155  else if ((pin >= 96) && (pin < 128))
156  {
157  *bit = pin - 96;
158  gpio = reinterpret_cast<volatile uint32_t *>(m_Gpio4.virtualAddress());
159  }
160  else if ((pin >= 128) && (pin < 160))
161  {
162  *bit = pin - 128;
163  gpio = reinterpret_cast<volatile uint32_t *>(m_Gpio5.virtualAddress());
164  }
165  else if ((pin >= 160) && (pin < 192))
166  {
167  *bit = pin - 160;
168  gpio = reinterpret_cast<volatile uint32_t *>(m_Gpio6.virtualAddress());
169  }
170  else
171  gpio = 0;
172  return gpio;
173 }
void initspecific(int n, volatile uint32_t *gpio)
Initialises a specific GPIO to a given set of defaults.
Definition: Gpio.cc:112
volatile uint32_t * getGpioForPin(int pin, int *bit)
Definition: Gpio.cc:137
Definition: Gpio.h:30
#define NOTICE(text)
Definition: Log.h:74
Definition: Log.h:136
void * virtualAddress() const
Definition: MemoryRegion.cc:39
Definition: Log.h:138