blob: 9993bd92f08da0875a58e5ebba25dc343977d858 [file] [log] [blame]
/*
* Copyright (C) 2018 Synaptics Incorporated. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND
* SYNAPTICS EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE, AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY
* INTELLECTUAL PROPERTY RIGHTS. IN NO EVENT SHALL SYNAPTICS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, OR
* CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION WITH THE USE
* OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED AND
* BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF
* COMPETENT JURISDICTION DOES NOT PERMIT THE DISCLAIMER OF DIRECT
* DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS' TOTAL CUMULATIVE LIABILITY
* TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S. DOLLARS.
*/
#define _GPIO_C_
/*
* Programming sample:
* 1. spi_master_init_iomapper(IOMAPPER_SPI_MASTER), init IOmapper
* 2. GPIO_PinmuxInit(port), setting both Galois and IOmapper pinmux
* 3.1 GPIO_IOmapperSetInOut(port, in), setting GPIO pin as in / out.
* 3.2 GPIO_PortSetInOut(port, in), setting GPIO pin as in /out.
* 4. GPIO_PortWrite, GPIOPortRead
*
* NOTE: GPIO_PinmuxInit shouldn't setup GPIO[13:10], it's SPI#0 for
* programming IOmapper. Galois GPIO in / out setting is done in
* GPIO_PortWrite / GPIOPortRead, just for campatible forward with Berlin.
*
* NOTE: for Berlin, #1.spi_master_init_iomapper and #3.1 is descarded.
*/
#include <stdlib.h>
#include <stdint.h>
#include "io.h"
#include "apb_perif_base.h"
#include "apb_gpio.h"
#include "global.h"
#include "gpio.h"
struct gpio_port_inst {
uint32_t base;
uint32_t reg_dr;
uint32_t reg_ddr;
uint32_t reg_ctl;
uint32_t reg_ext;
};
/****************************************************
* FUNCTION: find out SOC GPIO instance data according
to GPIO port number
* PARAMS: portnum - SoC GPIO port # (0 ~ 41)
* *inst - GPIO instance data
* *offset - offset in GPIO instance
* RETURN: 0 - succeed
* -1 - fail
***************************************************/
static int SOC_GPIO_GetPortInst(int portnum, struct gpio_port_inst *inst, uint32_t *offset)
{
if(inst == NULL)
return -1;
if(offset == NULL)
return -1;
if(portnum < 0) {
return -1;
} else if(portnum < 32){
inst->base = APB_GPIO0_BASE;
*offset = portnum;
}
else if(portnum < 64){
inst->base = APB_GPIO1_BASE;
*offset = portnum - 32;
}
else {
return -1;
}
inst->reg_dr = inst->base + APB_GPIO_SWPORTA_DR;
inst->reg_ddr = inst->base + APB_GPIO_SWPORTA_DDR;
inst->reg_ctl = inst->base + APB_GPIO_PORTA_CTL;
inst->reg_ext = inst->base + APB_GPIO_EXT_PORTA;
return 0;
}
/****************************************************
* FUNCTION: toggle GPIO port between high and low
* PARAMS: portnum - GPIO port # (0 ~ 41)
* value - 1: high; 0: low
* RETURN: 0 - succeed
* -1 - fail
***************************************************/
int GPIO_PortWrite(int portnum, int value)
{
struct gpio_port_inst inst;
uint32_t offset, ddr, dr;
if(SOC_GPIO_GetPortInst(portnum, &inst, &offset))
return -1;
/* set port value */
dr = readl(inst.reg_dr);
if (value){
dr |= (1<<offset);
} else {
dr &= ~(1<<offset);
}
writel(dr, inst.reg_dr);
/* set port to output mode */
ddr = readl(inst.reg_ddr);
ddr |= (1<<offset);
writel(ddr, inst.reg_ddr);
return 0;
}
/****************************************************
* FUNCTION: read GPIO port status
* PARAMS: portnum - GPIO port # (0 ~ 41)
* *value - pointer to port status
* RETURN: 0 - succeed
* -1 - fail
***************************************************/
int GPIO_PortRead(int portnum, int *value)
{
struct gpio_port_inst inst;
uint32_t offset, ddr, ext;
if(SOC_GPIO_GetPortInst(portnum, &inst, &offset))
return -1;
/* set port to input mode */
ddr = readl(inst.reg_ddr);
ddr &= ~(1<<offset);
writel(ddr, inst.reg_ddr);
/* get port value */
ext = readl(inst.reg_ext);
if (ext & (1<<offset))
*value = 1;
else
*value = 0;
return 0;
}
/****************************************************
* FUNCTION: Set Galois GPIO pin as in or out
* PARAMS: portnum - GPIO port # (0 ~ 31)
* in - 1: IN, 0: OUT
* RETURN: 0 - succeed
* -1 - fail
***************************************************/
int GPIO_PortSetInOut(int portnum, int in)
{
struct gpio_port_inst inst;
uint32_t offset, ddr, ctl;
if(SOC_GPIO_GetPortInst(portnum, &inst, &offset))
return -1;
/* software mode */
ctl = readl(inst.reg_ctl);
ctl &= ~(1 << offset);
writel(ctl, inst.reg_ctl);
/* set port to output mode */
ddr = readl(inst.reg_ddr);
if (in)
ddr &= ~(1 << offset);
else
ddr |= (1 << offset);
writel(ddr, inst.reg_ddr);
return 0;
}