mbed-os
Fork of mbed-os by
targets/TARGET_ONSEMI/TARGET_NCS36510/gpio_api.c
- Committer:
- elessair
- Date:
- 2016-10-23
- Revision:
- 0:f269e3021894
File content as of revision 0:f269e3021894:
/** ****************************************************************************** * @file gpio_api.c * @brief Implementation of a GPIO driver * @internal * @author ON Semiconductor * $Rev: * $Date: 2015-11-04 $ ****************************************************************************** * Copyright 2016 Semiconductor Components Industries LLC (d/b/a ON Semiconductor). * All rights reserved. This software and/or documentation is licensed by ON Semiconductor * under limited terms and conditions. The terms and conditions pertaining to the software * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf * (ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software) and * if applicable the software license agreement. Do not use this software and/or * documentation unless you have carefully read and you agree to the limited terms and * conditions. By using this software and/or documentation, you agree to the limited * terms and conditions. * * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. * @endinternal * * @ingroup gpio * * @details * * @internal * <h1> Reference document(s) </h1> * <p> * Reference document: IPC7203 APB GPIO Design Specification v1.2</a> * </p> * @endinternal * * <h1> Functional description (internal) </h1> * <p> * Each GPIO line can be independently programmed as an input or an output. Separate Set * and Clear registers are provided since it is likely that different software tasks may be * servicing different I/O signals. Inputs are synchronized to the system clock * through a pair of flip-flops. Each input can be programmed * to cause an interrupt to be generated. The interrupt can be programmed to be level-sensitive * or edge-sensitive and the level (high or low) or edge (rising, falling or either) that causes * the interrupt can be selected. Interrupts can be individually enabled or disabled. * Level-sensitive interrupts stay asserted until the interrupting condition is cleared. * Edge-triggered interrupts are cleared by writing to the GPIO interrupt clear register. * </p> * * <h1> Use of GPIO driver in SW </h1> * <p> * The user of the GPIO driver should set the pin as GPIO, using crossbar. * Init the GPIO and configure the mode and direction.This will return a device pointer. One device controls all GPIO's. It is not * needed nor supported to create a device per GPIO. * Next, the user should call the fGpioOpen function with the device and options as paramter. * </p> * <p> * Use the device driver fGpioIoctl function to change the behavior of the GPIO's and to register an * interrupt handler for each IO that has an interrupt enabled. There is one interrupt for all GPIO's. * The GPIO driver will look up what IO caused the interrupt and call the respective interrupt handler. * </p> */ #include "gpio.h" /* Include from the mbed-hal layer */ #include "gpio_api.h" #include "pinmap.h" /** Set the given pin as GPIO * * @param pin The pin to be set as GPIO * @return The GPIO port mask for this pin **/ uint32_t gpio_set(PinName pin) { if (pin != NC) { /* Configure to GPIO using pin function API*/ pin_function(pin, CONFIGURE_AS_GPIO); return ((uint32_t) 0x1 << pin); } return(0x00000000); } /** Initialize the GPIO pin * * @param obj The GPIO object to initialize * @param pin The GPIO pin to initialize */ void gpio_init(gpio_t *obj, PinName pin) { /* Initialize the GPIO membase */ obj->GPIOMEMBASE = GPIOREG; /* Initialize the pin to be GPIO */ obj->gpioPin = pin; obj->gpioMask = gpio_set(pin); /* Enable the GPIO clock */ CLOCK_ENABLE(CLOCK_GPIO); /* Set the drive strength of the pin to 1 by default */ /** - Get PAD IO register address for the PAD number */ PadReg_t *PadRegOffset = (PadReg_t*)(PADREG_BASE + (pin * PAD_REG_ADRS_BYTE_SIZE)); /* - Disable the GPIO clock */ CLOCK_DISABLE(CLOCK_GPIO); /** - Enable the clock for PAD peripheral device */ CLOCK_ENABLE(CLOCK_PAD); /** - Set drive type, pulltype & drive strength */ PadRegOffset->PADIO0.BITS.POWER = 1; /** - Disable the clock for PAD peripheral device */ CLOCK_DISABLE(CLOCK_PAD); } /** Set the input pin mode * * @param obj The GPIO object * @param mode The pin mode to be set */ void gpio_mode(gpio_t *obj, PinMode mode) { uint32_t pin = obj->gpioPin; /* Set the mode for the pin */ pin_mode((PinName)pin, mode); } /** Set the pin direction * * @param obj The GPIO object * @param direction The pin direction to be set */ void gpio_dir(gpio_t *obj, PinDirection direction) { /* Enable the GPIO clock */ CLOCK_ENABLE(CLOCK_GPIO); if (direction == PIN_INPUT) { obj->GPIOMEMBASE->W_IN = obj->gpioMask; } else if (direction == PIN_OUTPUT) { obj->GPIOMEMBASE->W_OUT = obj->gpioMask; } /* - Disable the GPIO clock */ CLOCK_DISABLE(CLOCK_GPIO); } /** Set the output value * * @param obj The GPIO object * @param value The value to be set */ void gpio_write(gpio_t *obj, int value) { /* Enable the GPIO clock */ CLOCK_ENABLE(CLOCK_GPIO); /* Set the GPIO based on value */ if (value) { obj->GPIOMEMBASE->R_STATE_W_SET = obj->gpioMask; } else { obj->GPIOMEMBASE->R_IRQ_W_CLEAR = obj->gpioMask; } /* - Disable the GPIO clock */ CLOCK_DISABLE(CLOCK_GPIO); } /** Read the input value * * @param obj The GPIO object * @return An integer value 1 or 0 */ int gpio_read(gpio_t *obj) { int ret; /* Enable the GPIO clock */ CLOCK_ENABLE(CLOCK_GPIO); ret = (obj->GPIOMEMBASE->R_STATE_W_SET & obj->gpioMask) ? 1: 0; /* - Disable the GPIO clock */ CLOCK_DISABLE(CLOCK_GPIO); return ret; }