Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(414)

Side by Side Diff: gpio_setup.py

Issue 2656004: add c++ version of the firmware utilities (Closed) Base URL: ssh://gitrw.chromium.org/firmware-utils.git
Patch Set: removed python scripts and add comments for range names in gpio Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gpio_setup.cc ('k') | reboot_mode.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 """A script to create symlinks to platform specific GPIO pins.
8
9 This script creates a set of symlinks pointing at the sys fs files returning
10 the appropriate GPIO pin values. Each symlink is named to represent the actual
11 GPIO pin function.
12
13 The location of the symlinks generated by this script can be specified using
14 the --symlink_root command line option. By default /home/gpio directory is
15 used. The symlink directory must exist before this script is run.
16
17 The GPIO pins' values are available through a GPIO device present in sys fs.
18 The device is identified by its PCI bus address. The default PCI address of
19 the GPIO device (set to 0:0:1f.0), can be changed using the --pci_address
20 command line option.
21
22 The platform specific bit usage of the GPIO device is derived from the ACPI,
23 also using files found in a fixed location in sys fs. The default location of
24 /sys/bus/platform/devices/chromeos_acpi could be changed using the --acpi_root
25 command line option.
26
27 Each GPIO pin is represented through ACPI as a subdirectory with several files
28 in it. A typical name of the GPIO pin file looks as follows:
29
30 <acpi_root>/GPIO.<instance>/GPIO.[0-3]
31
32 where <instance> is a zero based number assigned to this GPIO pin by the BIOS.
33
34 In particular, file GPIO.0 represents encoded pin signal type (from which the
35 symlink name is derived), and file GPIO.2 represents the actual zero based
36 GPIO pin number within this GPIO device range.
37
38 This script reads the ACPI provided mapping, enables the appropriate GPIO pins
39 and creates symlinks mapping these GPIOs' values.
40 """
41
42 __author__ = 'The Chromium OS Authors'
43
44 import glob
45 import os
46 import optparse
47 import sys
48
49 GPIO_ROOT = '/sys/class/gpio'
50 GPIO_DEVICE_ROOT = GPIO_ROOT + '/gpiochip'
51 GPIO_ENABLE_FILE = '/sys/class/gpio/' + 'export'
52
53 # Can be changed using --pci_address command line option.
54 GPIO_DEVICE_PCI_ADDRESS = '0000:00:1f.0'
55
56 # Can be changed using --acpi_root command line option.
57 ACPI_ROOT = '/sys/bus/platform/devices/chromeos_acpi'
58 GPIO_SIGNAL_TYPE_EXTENSION = '0'
59 GPIO_PIN_NUMBER_EXTENSION = '2'
60
61 # can be changed using --symlink_root command line option.
62 DEFAULT_SYMLINK_ROOT = '/home/gpio'
63
64 # This dictionary maps GPIO signal types codes into their actual names.
65 GPIO_SIGNAL_TYPES = {
66 1: 'recovery_button',
67 2: 'developer_switch',
68 3: 'write_protect'
69 }
70
71 # Debug header signal type codes are offset by 0x100, the tuple below
72 # represents the range of valid codes for the debug header. The range starts
73 # at 0x100 and is 0x100 wide.
74 GPIO_DEBUG_HEADER_RANGE = (0x100, 0x100)
75
76 # This is used to prepare the option parser: each element is a tuple of
77 # strings, including the option name and the option default value.
78 option_list = (('symlink_root', DEFAULT_SYMLINK_ROOT),
79 ('pci_address', GPIO_DEVICE_PCI_ADDRESS),
80 ('acpi_root', ACPI_ROOT))
81
82 # This becomes the option object after the command line is parsed.
83 cmd_line_options = None
84
85 class GpioSetupError(Exception):
86 pass
87
88
89 class GpioChip(object):
90 """Represent GPIO chip available through sys fs.
91
92 Attributes:
93 pci_address: a string, PCI address of this GPIO device
94 base: a number, base global GPIO number of this device (mapped to pin zero
95 in the device range)
96 capacity: a number, shows the number of GPIO pins of this device.
97 description: a multiline string description of this device, initialized
98 after the device is attached. Can be used to dump device
99 information.
100 """
101
102 def __init__(self, pci_address):
103 self.pci_address = pci_address
104 self.base = 0
105 self.capacity = 0
106 self.description = 'not attached'
107
108 def Attach(self):
109 for f in glob.glob(GPIO_DEVICE_ROOT + '*/label'):
110 label = open(f).read().strip()
111 if label == self.pci_address:
112 break
113 else:
114 raise GpioSetupError(
115 'could not find GPIO PCI device %s' % self.pci_address)
116 directory = os.path.dirname(f)
117 self.base = int(open(directory + '/base').read())
118 self.capacity = int(open(directory + '/ngpio').read())
119 self.description = '\n'.join(['GPIO device at PCI address %s' %
120 self.pci_address,
121 'Base gpio pin %d' % self.base,
122 'Capacity %d' % self.capacity])
123
124 def EnablePin(self, pin):
125 """Enable a certain GPIO pin.
126
127 To enable the pin one needs to write its global GPIO number into
128 /sys/class/gpio/export, if this pin has not been enabled yet.
129
130 Inputs:
131 pin: a number, zero based pin number within this device's range.
132 """
133
134 if pin >= self.capacity:
135 raise GpioSetupError('pin %d exceeds capacity of %d' % (
136 pin, self.capacity))
137 global_gpio_number = self.base + pin
138 if not os.path.exists('%s/gpio%d' % (GPIO_ROOT, global_gpio_number)):
139 open(GPIO_ENABLE_FILE, 'w').write('%d' % (global_gpio_number))
140
141 def __str__(self):
142 return self.description
143
144
145 def ParseAcpiMappings():
146 """Scan ACPI information about GPIO and generate a mapping.
147
148 Returns: a list of tuples, each tuple consisting of a string representing
149 the GPIO pin name and a number, representing the GPIO pin within
150 the GPIO device space.
151 """
152 acpi_gpio_mapping = []
153 for d in glob.glob('%s/GPIO.[0-9]*' % cmd_line_options.acpi_root):
154 signal_type = int(open('%s/GPIO.%s' % (
155 d, GPIO_SIGNAL_TYPE_EXTENSION)).read())
156
157 pin_number = int(open('%s/GPIO.%s' % (
158 d, GPIO_PIN_NUMBER_EXTENSION)).read())
159
160 if signal_type in GPIO_SIGNAL_TYPES:
161 acpi_gpio_mapping.append((GPIO_SIGNAL_TYPES[signal_type], pin_number))
162 continue
163
164 # This is not a specific signal, could be a debug header pin.
165 debug_header = signal_type - GPIO_DEBUG_HEADER_RANGE[0]
166 if debug_header >= 0 and debug_header < GPIO_DEBUG_HEADER_RANGE[1]:
167 acpi_gpio_mapping.append(('debug_header_%d' % debug_header, pin_number))
168 continue
169
170 # Unrecognized mapping, could happen if BIOS version is ahead of this
171 # script.
172 print 'unknown signal type encoding %d in %d' % (signal_type, d)
173
174 if not acpi_gpio_mapping:
175 raise GpioSetupError('no gpio mapping found. Is ACPI driver installed?')
176
177 return acpi_gpio_mapping
178
179
180 def CreateGpioSymlinks(mappings, gpio, symlink_root):
181 if not os.path.exists(symlink_root):
182 raise GpioSetupError('%s does not exist' % symlink_root)
183
184 if not os.path.isdir(symlink_root):
185 raise GpioSetupError('%s is not a directory' % symlink_root)
186
187 if not os.access(symlink_root, os.W_OK):
188 raise GpioSetupError('%s is not writable' % symlink_root)
189
190 try:
191 os.chdir(symlink_root)
192 except OSError:
193 raise GpioSetupError('failed to change directory to %s' % symlink_root)
194
195 for (symlink, pin) in mappings:
196 gpio.EnablePin(pin)
197 source_file = '%s/gpio%d/value' % (GPIO_ROOT, pin + gpio.base)
198 if not os.path.exists(symlink):
199 os.symlink(source_file, symlink)
200 continue
201 if not os.path.islink(symlink):
202 raise GpioSetupError(
203 '%s exists but is not a symlink' % os.path.abspath(symlink))
204 if os.readlink(symlink) != source_file:
205 raise GpioSetupError(
206 '%s points to a wrong file' % os.path.abspath(symlink))
207
208
209 def ProcessOptions():
210 global cmd_line_options
211 parser = optparse.OptionParser()
212 for (name, default_value) in option_list:
213 parser.add_option('--' + name, dest=name, default=default_value)
214 (cmd_line_options, _) = parser.parse_args()
215
216
217 def main():
218 ProcessOptions()
219 gpioc = GpioChip(cmd_line_options.pci_address)
220 gpioc.Attach()
221 CreateGpioSymlinks(ParseAcpiMappings(), gpioc, cmd_line_options.symlink_root)
222
223
224 if __name__ == '__main__':
225 try:
226 main()
227 except GpioSetupError, e:
228 print >> sys.stderr, '%s: %s' % (sys.argv[0].split('/')[-1], e)
229 sys.exit(1)
230 sys.exit(0)
OLDNEW
« no previous file with comments | « gpio_setup.cc ('k') | reboot_mode.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698