summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLee Campbell <leecam@google.com>2016-05-03 02:45:39 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-05-03 02:45:39 +0000
commit38d47130db72823f90d17b07ccc1e29513e49221 (patch)
treef941cf2c603e0746727f6b9044439770cc3e58b3
parent00129e9bc0561963432626bed82766fb7f36a738 (diff)
parent17b4001e01d43e7d554d52ff54453128299592eb (diff)
downloadedison-38d47130db72823f90d17b07ccc1e29513e49221.tar.gz
PeripheralIO - Edison PIO HAL am: 9b390fdb19
am: 17b4001e01 * commit '17b4001e01d43e7d554d52ff54453128299592eb': PeripheralIO - Edison PIO HAL Change-Id: I87f4c5893978601d44ed97b753e33bf4dd09c394
-rw-r--r--BoardConfig.mk2
-rw-r--r--pio_hal/Android.mk30
-rw-r--r--pio_hal/pio_hal.cc309
3 files changed, 341 insertions, 0 deletions
diff --git a/BoardConfig.mk b/BoardConfig.mk
index 3d2f8ae..1dfae99 100644
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -63,5 +63,7 @@ BRILLO_VENDOR_PARTITIONS := \
$(vendor_partition_directory)/uboot_firmware:u-boot-edison.bin \
$(vendor_partition_directory)/uboot_firmware:gpt.bin
+DEVICE_PACKAGES += peripheral_io.$(TARGET_DEVICE)
+
# Must defined at the end of the file
$(call add_device_packages)
diff --git a/pio_hal/Android.mk b/pio_hal/Android.mk
new file mode 100644
index 0000000..33ea923
--- /dev/null
+++ b/pio_hal/Android.mk
@@ -0,0 +1,30 @@
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ifeq ($(TARGET_DEVICE), edison)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := pio_hal.cc
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SHARED_LIBRARIES := liblog libchrome
+LOCAL_STATIC_LIBRARIES := peripheral_manager_hal_headers
+LOCAL_MODULE := peripheral_io.$(TARGET_DEVICE)
+LOCAL_CFLAGS := -fexceptions
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif \ No newline at end of file
diff --git a/pio_hal/pio_hal.cc b/pio_hal/pio_hal.cc
new file mode 100644
index 0000000..21784ba
--- /dev/null
+++ b/pio_hal/pio_hal.cc
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <map>
+#include <string>
+
+#include <base/logging.h>
+#include <hardware/hardware.h>
+#include <hardware/peripheral_io.h>
+
+// Path to sysfd gpio.
+const char kSysfsGpioPathPrefix[] = "/sys/class/gpio/gpio";
+
+// Path to export file.
+const char kSysfsGpioExportPath[] = "/sys/class/gpio/export";
+
+// Direction filename.
+const char kDirection[] = "direction";
+
+// Value filename.
+const char kValue[] = "value";
+
+static bool write_to_file(const std::string& path, const std::string& val) {
+ int fd = open(path.c_str(), O_WRONLY);
+ if (fd < 0)
+ return false;
+ ssize_t bytes = write(fd, val.c_str(), val.size());
+ close(fd);
+ if (bytes < 0)
+ return false;
+ if ((size_t)bytes != val.size())
+ return false;
+ return true;
+}
+
+static bool export_gpio(uint32_t index) {
+ std::string path = kSysfsGpioPathPrefix + std::to_string(index);
+ struct stat stat_buf;
+ if (!stat(path.c_str(), &stat_buf))
+ return true;
+
+ return write_to_file(kSysfsGpioExportPath, std::to_string(index));
+}
+
+static bool set_pin_direction(uint32_t index, const std::string& val) {
+ export_gpio(index);
+ std::string path =
+ kSysfsGpioPathPrefix + std::to_string(index) + "/direction";
+ return write_to_file(path, val);
+}
+
+static bool set_pin_val(uint32_t index, int val) {
+ export_gpio(index);
+ set_pin_direction(index, "out");
+ std::string path = kSysfsGpioPathPrefix + std::to_string(index) + "/value";
+ return write_to_file(path, std::to_string(val));
+}
+
+static bool set_output_buffer(uint32_t index, int val) {
+ export_gpio(index);
+ std::string path = kSysfsGpioPathPrefix + std::to_string(index) + "/value";
+ return write_to_file(path, std::to_string(val));
+}
+
+static bool set_mux_pin(uint32_t index, int val) {
+ set_pin_val(index, val);
+ return true;
+}
+
+static bool set_mode(uint32_t index, int val) {
+ export_gpio(index);
+ std::string path = kSysfsGpioPathPrefix + std::to_string(index) + "/pinmux";
+ return write_to_file(path, std::to_string(val));
+}
+
+struct EdisonPin {
+ uint32_t index;
+ uint32_t output_buffer;
+};
+
+std::map<std::string, EdisonPin> board_pins = {
+ {"IO0", {130, 248}}, {"IO1", {131, 249}}, {"IO2", {128, 250}},
+ {"IO3", {12, 251}}, {"IO4", {129, 252}}, {"IO5", {13, 253}},
+ {"IO6", {182, 254}}, {"IO7", {48, 255}}, {"IO8", {49, 256}},
+ {"IO9", {183, 257}}, {"IO10", {41, 258}}, {"IO11", {43, 259}},
+ {"IO12", {42, 260}}, {"IO13", {40, 261}}, {"IO14", {44, 232}},
+ {"IO15", {45, 233}}, {"IO16", {46, 234}}, {"IO17", {47, 235}},
+ {"IO18", {14, 236}}, {"IO19", {165, 237}},
+};
+
+static int pin_mux(const char* pin, const char* source) {
+ LOG(INFO) << "pin_mux1 " << pin << " ";
+ std::string pin_name(pin);
+
+ // If source is NULL, PIO is requesting GPIO.
+ if (!source) {
+ if (!board_pins.count(pin_name)) {
+ LOG(ERROR) << "PIO HAL: Unknown GPIO pin " << pin_name;
+ return false;
+ }
+
+ // Pin mode is always 0 for gpio.
+ set_mode(board_pins[pin_name].index, 0);
+ // Default to output buffer to input
+ set_output_buffer(board_pins[pin_name].output_buffer, 0);
+
+ // The following pins have an extra mux to set
+ if (pin_name == "IO10") {
+ set_mux_pin(263, 1);
+ set_mux_pin(240, 0);
+ set_mode(111, 0);
+ } else if (pin_name == "IO11") {
+ set_mux_pin(262, 1);
+ set_mux_pin(241, 0);
+ set_mode(115, 0);
+ } else if (pin_name == "IO12") {
+ set_mux_pin(242, 0);
+ set_mode(114, 0);
+ } else if (pin_name == "IO13") {
+ set_mux_pin(243, 0);
+ set_mode(109, 0);
+ } else if (pin_name == "IO14") {
+ set_mux_pin(200, 0);
+ } else if (pin_name == "IO15") {
+ set_mux_pin(201, 0);
+ } else if (pin_name == "IO16") {
+ set_mux_pin(202, 0);
+ } else if (pin_name == "IO17") {
+ set_mux_pin(203, 0);
+ } else if (pin_name == "IO18") {
+ set_mux_pin(204, 0);
+ } else if (pin_name == "IO19") {
+ set_mux_pin(205, 0);
+ }
+ return true;
+ }
+
+ std::string s = source;
+
+ // Configure SPI2
+ if (s == "SPI") {
+ LOG(INFO) << "SPI PIN " << pin_name;
+ if (pin_name == "IO10") {
+ set_pin_direction(226, "in");
+ set_mode(111, 1);
+ set_mux_pin(263, 1);
+ set_mux_pin(240, 1);
+ set_output_buffer(258, 1);
+ return true;
+ }
+ if (pin_name == "IO11") {
+ set_pin_direction(227, "in");
+ set_mode(115, 1);
+ set_mux_pin(262, 1);
+ set_mux_pin(241, 1);
+ set_output_buffer(259, 1);
+ return true;
+ }
+ if (pin_name == "IO12") {
+ set_pin_direction(228, "in");
+ set_output_buffer(260, 0);
+ set_mode(114, 1);
+ set_mux_pin(242, 1);
+ return true;
+ }
+ if (pin_name == "IO13") {
+ set_output_buffer(261, 0);
+ set_pin_direction(229, "in");
+ set_mode(109, 1);
+ set_mode(40, 1);
+ set_mux_pin(243, 1);
+ set_output_buffer(261, 1);
+ return true;
+ }
+ LOG(ERROR) << "PIO HAL: Unknown SPI pin " << pin_name;
+ return false;
+ }
+
+ // Configure I2C
+ if (s == "I2C") {
+ LOG(INFO) << "PIO HAL I2C pin " << pin_name;
+ if (pin_name == "IO18") {
+ set_pin_direction(212, "in");
+ set_pin_direction(14, "in");
+ set_mode(28, 1);
+ set_mode(14, 1);
+ set_mux_pin(204, 0);
+ set_output_buffer(236, 0);
+ return true;
+ }
+ if (pin_name == "IO19") {
+ set_pin_direction(213, "in");
+ set_pin_direction(165, "in");
+ set_mode(165, 1);
+ set_mode(27, 1);
+ set_mux_pin(205, 0);
+ set_output_buffer(237, 0);
+ return true;
+ }
+ LOG(ERROR) << "PIO HAL: Unknown I2C pin " << pin_name;
+ }
+
+ if (s == "UART") {
+ LOG(INFO) << "PIO HAL UART pin" << pin_name;
+
+ if (pin_name == "IO0") {
+ set_pin_direction(248, "out");
+ set_pin_direction(216, "out");
+ set_output_buffer(248, 0);
+ set_output_buffer(216, 0);
+ set_mode(130, 1);
+ } else if(pin_name == "IO1") {
+ set_pin_direction(249, "out");
+ set_pin_direction(217, "in");
+ set_output_buffer(249, 1);
+ set_mode(131, 1);
+ }
+ }
+
+ return false;
+}
+
+static int pin_mux_directon(const char* pin, int dir) {
+ LOG(INFO) << "pin_mux_directon1 " << pin << " " << dir;
+ std::string pin_name(pin);
+
+ if (!board_pins.count(pin_name)) {
+ LOG(ERROR) << "PIO HAL: Unknown GPIO pin " << pin_name;
+ return false;
+ }
+ set_output_buffer(board_pins[pin_name].output_buffer, dir);
+
+ return true;
+}
+
+static int register_device(const peripheral_io_module_t* dev,
+ const peripheral_registration_cb_t* callbacks) {
+ LOG(INFO) << "register_device";
+ (void)dev;
+ // Set up pin muxing and register GPIO pins.
+ for (auto& pin : board_pins) {
+ callbacks->register_pin(pin.first.c_str(), true,
+ {pin_mux, pin_mux_directon});
+ callbacks->register_gpio_sysfs(pin.first.c_str(), pin.second.index);
+ callbacks->set_gpio_pin_mux(pin.first.c_str(), pin.first.c_str());
+ set_pin_direction(pin.second.output_buffer, "low");
+ }
+ const char* spi_pins[4] = {"IO10", "IO11", "IO12", "IO13"};
+ callbacks->register_simple_source("SPI", spi_pins, 4);
+
+ // Register the SPI bus
+ callbacks->register_spi_dev_bus("SPI2", 5, 1);
+ callbacks->set_spi_pin_mux("SPI2", "SPI");
+
+ const char* i2c_pins[2] = {"IO18", "IO19"};
+ callbacks->register_simple_source("I2C", i2c_pins, 2);
+
+ // Register the I2C bus
+ callbacks->register_i2c_dev_bus("I2C6", 6);
+ callbacks->set_i2c_pin_mux("I2C6", "I2C");
+
+ const char* uart_pins[2] = {"IO0", "IO1"};
+ callbacks->register_simple_source("UART", uart_pins, 2);
+
+ // TODO(leecam): Add UART back in once UART code lands
+ //callbacks->register_uart_bus("UART1", "/dev/ttyMFD1");
+ //callbacks->set_uart_pin_mux("UART1", "UART");
+
+ // Enable the Tri-State
+ set_pin_direction(214, "out");
+ set_pin_val(214, 1);
+
+ return 0;
+}
+
+static struct hw_module_methods_t hal_module_methods = {};
+
+peripheral_io_module_t HAL_MODULE_INFO_SYM = {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = 0,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = PERIPHERAL_IO_HARDWARE_MODULE_ID,
+ .name = "periperal IO HAL",
+ .author = "The Android Open Source Project",
+ .methods = &hal_module_methods,
+ },
+ .register_devices = register_device,
+};