1/* 2 * Copyright 2011-2012 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck, kallisti5@unixzen.com 7 * Gordon Henderson, gordon@drogon.net 8 */ 9 10 11#include "gpio.h" 12 13 14// Define the shift up for the 3 bits per pin in each GPFSEL port 15static uint8_t 16kGPIOToShift[] = 17{ 18 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 19 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 20 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 21 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 22 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 23}; 24 25 26// Map a BCM_GPIO pin to it's control port. (GPFSEL 0-5) 27static uint8_t 28kGPIOToGPFSEL[] = 29{ 30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 32 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 35 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 36}; 37 38 39// (Word) offset to the GPIO Set registers for each GPIO pin 40static uint8_t 41kGPIOToGPSET[] = 42{ 43 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 44 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 45 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 46 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 47}; 48 49// (Word) offset to the GPIO Clear registers for each GPIO pin 50static uint8_t 51kGPIOToGPCLR[] = 52{ 53 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 54 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 55 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 56 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 57}; 58 59 60/*! 61 * At GPIO (base) (pin) state set (value) 62 */ 63void 64gpio_write(addr_t base, int pin, bool value) 65{ 66 volatile addr_t *gpio = (addr_t*)base; 67 68 if (value == 1) 69 *(gpio + kGPIOToGPSET[pin]) = 1 << pin; 70 else 71 *(gpio + kGPIOToGPCLR[pin]) = 1 << pin; 72} 73 74 75/*! 76 * At GPIO (base) (pin) set mode (mode) 77 */ 78void 79gpio_mode(addr_t base, int pin, int mode) 80{ 81 int sel = kGPIOToGPFSEL[pin]; 82 int shift = kGPIOToShift[pin]; 83 84 volatile addr_t *gpio = (addr_t*)base + sel; 85 86 if (mode == GPIO_IN) 87 *gpio = (*gpio & ~(7 << shift)); 88 else if (mode == GPIO_OUT) 89 *gpio = (*gpio & ~(7 << shift)) | (1 << shift); 90 else 91 *gpio = (*gpio & ~(7 << shift)) | (mode << shift); 92} 93 94 95void 96gpio_init() 97{ 98 // ** Take control of ok led, and general use pins 99 int pin = 0; 100 for (pin = 16; pin <= 25; pin++) 101 gpio_mode(GPIO_BASE, pin, GPIO_OUT); 102} 103