| /******************************************************************************** |
| * Marvell GPL License Option |
| * |
| * If you received this File from Marvell, you may opt to use, redistribute and/or |
| * modify this File in accordance with the terms and conditions of the General |
| * Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| * available along with the File in the license.txt file or by writing to the Free |
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| * on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| * |
| * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| * DISCLAIMED. The GPL License provides additional details about this warranty |
| * disclaimer. |
| ******************************************************************************/ |
| |
| #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 "com_type.h" |
| #include "apb_perf_base.h" |
| #include "galois_io.h" |
| #include "apb_gpio.h" |
| #include "global.h" |
| //#include "spi_master.h" |
| //#include "dv_iomapper.h" |
| #include "gpio.h" |
| #ifdef __LINUX_KERNEL__ |
| #include <linux/module.h> |
| #endif |
| |
| /**************************************************** |
| * FUNCTION: toggle GPIO port between high and low |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * value - 1: high; 0: low |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int GPIO_PortWrite(int port, int value) |
| { |
| unsigned reg = 0xf7e80400; //gpio base |
| if (value) { |
| *(volatile unsigned int*)reg |= 1 << port; |
| } else { |
| *(volatile unsigned int*)reg &= ~(1 << port); |
| } |
| |
| *(volatile unsigned int*)(reg + 4) |= 1 << port; // direction: 1 - output |
| // 0 - input |
| return 0; |
| } |
| /**************************************************** |
| * FUNCTION: read GPIO port status |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * *value - pointer to port status |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int GPIO_PortRead(int port, int *value) |
| { |
| int reg_ddr, reg_ext; |
| int ddr, ext; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = APB_GPIO_INST0_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ext = APB_GPIO_INST0_BASE + APB_GPIO_EXT_PORTA; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_ddr = APB_GPIO_INST1_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ext = APB_GPIO_INST1_BASE + APB_GPIO_EXT_PORTA; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_ddr = APB_GPIO_INST2_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ext = APB_GPIO_INST2_BASE + APB_GPIO_EXT_PORTA; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_ddr = APB_GPIO_INST3_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ext = APB_GPIO_INST3_BASE + APB_GPIO_EXT_PORTA; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* set port to input mode */ |
| GA_REG_WORD32_READ(reg_ddr, &ddr); |
| ddr &= ~(1<<port); |
| GA_REG_WORD32_WRITE(reg_ddr, ddr); |
| |
| /* get port value */ |
| GA_REG_WORD32_READ(reg_ext, &ext); |
| if (ext & (1<<port)) |
| *value = 1; |
| else |
| *value = 0; |
| |
| return 0; |
| } |
| |
| #if 0 |
| /**************************************************** |
| * FUNCTION: pinmux init for the pin of GPIO port |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * RETURN: 0 - succeed |
| * -1 - fail |
| * NOTE: Be sure that spi_master_init_iomapper is done. |
| ***************************************************/ |
| #ifdef BERLIN |
| int GPIO_PinmuxInit(int port) |
| { |
| T32Gbl_pinMux reg; |
| #if (BERLIN_CHIP_VERSION >= BERLIN_B_0) |
| T32Gbl_pinMux1 reg1; |
| #endif |
| |
| /* readout Galois pin mux */ |
| GA_REG_WORD32_READ((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux), &(reg.u32)); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_B_0) |
| GA_REG_WORD32_READ((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux1), &(reg1.u32)); |
| #endif |
| |
| /* setting Galois&IOmapper pin mux */ |
| switch (port) { |
| case 0: /* gp0:m1 */ |
| reg.upinMux_gp0 = Gbl_pinMux_gp0_MODE_1; |
| break; |
| case 1: /* gp1:m1 */ |
| reg.upinMux_gp1 = Gbl_pinMux_gp1_MODE_1; |
| break; |
| case 2: /* gp2:m0 */ |
| reg.upinMux_gp2 = Gbl_pinMux_gp2_MODE_0; |
| break; |
| case 3: /* gp3:m2 */ |
| reg.upinMux_gp3 = Gbl_pinMux_gp3_MODE_2; |
| break; |
| case 4: /* gp4:m1 */ |
| case 5: |
| case 6: |
| reg.upinMux_gp4 = Gbl_pinMux_gp4_MODE_1; |
| break; |
| case 7: /* gp5:m0 */ |
| case 8: |
| case 9: |
| case 10: |
| case 11: |
| reg.upinMux_gp5 = Gbl_pinMux_gp5_MODE_0; |
| break; |
| case 12: /* gp6:m0 */ |
| case 13: |
| case 14: |
| case 15: |
| case 16: |
| reg.upinMux_gp6 = Gbl_pinMux_gp6_MODE_0; |
| break; |
| case 17: /* gp7:m0 */ |
| reg.upinMux_gp7 = Gbl_pinMux_gp7_MODE_0; |
| break; |
| case 18: /* gp8:m0 */ |
| reg.upinMux_gp8 = Gbl_pinMux_gp8_MODE_0; |
| break; |
| case 19: /* gp9:m0 */ |
| case 20: |
| case 21: |
| case 22: |
| case 23: |
| reg.upinMux_gp9 = Gbl_pinMux_gp9_MODE_0; |
| break; |
| case 24: /* gp10:m2 */ |
| case 25: |
| reg.upinMux_gp10 = Gbl_pinMux_gp10_MODE_2; |
| break; |
| case 26: /* gp11:m2 */ |
| case 27: |
| reg.upinMux_gp11 = Gbl_pinMux_gp11_MODE_2; |
| break; |
| case 28: /* gp14:m0 */ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| reg1.upinMux_gp14 = Gbl_pinMux_gp14_MODE_0; |
| #else |
| reg.upinMux_gp14 = Gbl_pinMux_gp14_MODE_0; |
| #endif |
| break; |
| case 29: /* gp15:m0 */ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| reg1.upinMux_gp15 = Gbl_pinMux_gp15_MODE_0; |
| #else |
| reg.upinMux_gp15 = Gbl_pinMux_gp15_MODE_0; |
| #endif |
| break; |
| case 30: /* gp16:m7 */ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| reg1.upinMux_gp16 = Gbl_pinMux_gp16_MODE_7; |
| #else |
| reg.upinMux_gp16 = Gbl_pinMux_gp16_MODE_7; |
| #endif |
| break; |
| case 31: /* gp17:m7 */ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_B_0) |
| reg1.upinMux_gp17 = Gbl_pinMux_gp17_MODE_7; |
| #else |
| reg.upinMux_gp17 = Gbl_pinMux_gp17_MODE_7; |
| #endif |
| break; |
| default: |
| return -1; |
| } |
| |
| /* write Galois pin mux */ |
| GA_REG_WORD32_WRITE((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux), (reg.u32)); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_B_0) |
| GA_REG_WORD32_WRITE((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux1), (reg1.u32)); |
| #endif |
| |
| return 0; |
| } |
| |
| #else /* BERLIN */ |
| |
| int GPIO_PinmuxInit(int port) |
| { |
| T32Gbl_pinMux reg; |
| T32Gbl_pinMux1 reg1; |
| UNSG32 tmp_reg0, tmp_reg1, tmp_reg2, tmp_reg3; |
| iomapper_reg_0_t iomapper_reg0; |
| iomapper_reg_1_t iomapper_reg1; |
| iomapper_reg_2_t iomapper_reg2; |
| iomapper_reg_3_t iomapper_reg3; |
| |
| /* readout Galois pin mux */ |
| GA_REG_WORD32_READ((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux), &(reg.u32)); |
| GA_REG_WORD32_READ((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux1), &(reg1.u32)); |
| |
| /* readout IOmapper pin mux */ |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 1, IOMAPPER_REG_MAP_0, &tmp_reg0); |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 1, IOMAPPER_REG_MAP_1, &tmp_reg1); |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 1, IOMAPPER_REG_MAP_2, &tmp_reg2); |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 1, IOMAPPER_REG_MAP_3, &tmp_reg3); |
| iomapper_reg0.u16 = tmp_reg0 & 0xffff; |
| iomapper_reg1.u16 = tmp_reg1 & 0xffff; |
| iomapper_reg2.u16 = tmp_reg2 & 0xffff; |
| iomapper_reg3.u16 = tmp_reg3 & 0xffff; |
| |
| /* setting Galois&IOmapper pin mux */ |
| switch (port) { |
| case 0: |
| case 1: |
| reg.upinMux_gp4 = Gbl_pinMux_gp4_MODE_0; |
| iomapper_reg0.g4 = 0; |
| break; |
| case 2: |
| case 3: |
| reg.upinMux_gp9 = Gbl_pinMux_gp9_MODE_0; |
| iomapper_reg0.g9 = 0; |
| break; |
| case 4: |
| case 5: |
| reg.upinMux_gp10 = Gbl_pinMux_gp10_MODE_0; |
| iomapper_reg0.g10 = 0; |
| break; |
| case 6: |
| case 7: |
| reg.upinMux_gp11 = Gbl_pinMux_gp11_MODE_0; |
| iomapper_reg2.g11 = 0; |
| break; |
| case 8: |
| case 9: |
| reg.upinMux_gp12 = Gbl_pinMux_gp12_MODE_0; |
| iomapper_reg2.g12 = 0; |
| break; |
| case 10: |
| case 11: |
| case 12: |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| reg1.upinMux_gp13 = Gbl_pinMux_gp13_MODE_0; |
| #else |
| reg.upinMux_gp13 = Gbl_pinMux_gp13_MODE_0; |
| #endif |
| iomapper_reg2.g13 = 0; |
| break; |
| case 13: |
| reg1.upinMux_gp37 = Gbl_pinMux_gp37_MODE_0; /* reg1 */ |
| iomapper_reg1.g37 = 0; |
| break; |
| case 14: |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| reg1.upinMux_gp14 = Gbl_pinMux_gp14_MODE_0; |
| #else |
| reg.upinMux_gp14 = Gbl_pinMux_gp14_MODE_0; |
| #endif |
| iomapper_reg2.g14 = 0; |
| break; |
| case 15: |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| reg1.upinMux_gp15 = Gbl_pinMux_gp15_MODE_0; |
| #else |
| reg.upinMux_gp15 = Gbl_pinMux_gp15_MODE_0; |
| #endif |
| iomapper_reg2.g15 = 0; |
| break; |
| case 16: |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| reg1.upinMux_gp16 = Gbl_pinMux_gp16_MODE_0; |
| #else |
| reg.upinMux_gp16 = Gbl_pinMux_gp16_MODE_0; |
| #endif |
| iomapper_reg2.g16 = 0; |
| break; |
| case 17: |
| reg.upinMux_gp19 = Gbl_pinMux_gp19_MODE_0; |
| iomapper_reg2.g19 = 0; |
| break; |
| case 18: |
| reg.upinMux_gp20 = Gbl_pinMux_gp20_MODE_0; |
| iomapper_reg2.g20 = 0; |
| break; |
| /* reg1 starts from gp21 */ |
| case 19: |
| reg1.upinMux_gp23 = Gbl_pinMux_gp23_MODE_0; |
| iomapper_reg0.g23 = 0; |
| break; |
| case 20: |
| reg1.upinMux_gp24 = Gbl_pinMux_gp24_MODE_0; |
| iomapper_reg3.g24 = 0; |
| break; |
| case 21: |
| reg1.upinMux_gp25 = Gbl_pinMux_gp25_MODE_0; |
| iomapper_reg3.g25 = 0; |
| break; |
| case 22: |
| case 23: |
| reg1.upinMux_gp27 = Gbl_pinMux_gp27_MODE_0; |
| iomapper_reg3.g27 = 0; |
| break; |
| case 24: |
| case 25: |
| reg1.upinMux_gp28 = Gbl_pinMux_gp28_MODE_0; |
| iomapper_reg3.g28 = 0; |
| break; |
| case 26: |
| reg1.upinMux_gp31 = Gbl_pinMux_gp31_MODE_0; |
| iomapper_reg1.g31 = 0; |
| break; |
| case 27: |
| reg1.upinMux_gp32 = Gbl_pinMux_gp32_MODE_0; |
| iomapper_reg1.g32 = 0; |
| break; |
| case 28: |
| reg1.upinMux_gp33 = Gbl_pinMux_gp33_MODE_0; |
| iomapper_reg1.g33 = 0; |
| break; |
| case 29: |
| reg1.upinMux_gp34 = Gbl_pinMux_gp34_MODE_0; |
| iomapper_reg1.g34 = 0; |
| break; |
| case 30: |
| reg1.upinMux_gp35 = Gbl_pinMux_gp35_MODE_0; |
| iomapper_reg1.g35 = 0; |
| break; |
| case 31: |
| reg1.upinMux_gp36 = Gbl_pinMux_gp36_MODE_0; |
| iomapper_reg1.g36 = 0; |
| break; |
| default: |
| return -1; |
| } |
| |
| /* write Galois pin mux */ |
| GA_REG_WORD32_WRITE((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux), (reg.u32)); |
| GA_REG_WORD32_WRITE((MEMMAP_CHIP_CTRL_REG_BASE + RA_Gbl_pinMux1), (reg1.u32)); |
| |
| /* write IOmapper pin mux */ |
| tmp_reg0 = iomapper_reg0.u16; |
| tmp_reg1 = iomapper_reg1.u16; |
| tmp_reg2 = iomapper_reg2.u16; |
| tmp_reg3 = iomapper_reg3.u16; |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 0, IOMAPPER_REG_MAP_0, &tmp_reg0); |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 0, IOMAPPER_REG_MAP_1, &tmp_reg1); |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 0, IOMAPPER_REG_MAP_2, &tmp_reg2); |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, |
| 0, IOMAPPER_REG_MAP_3, &tmp_reg3); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Configure IOmapper for GPIO port |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * in - Set GPIO pin as IN or OUT |
| * RETURN: 0 - succeed |
| * -1 - fail |
| * NOTE: Be sure that spi_master_init_iomapper is done. |
| ***************************************************/ |
| int GPIO_IOmapperSetInOut(int port, int in) |
| { |
| int iomapper_reg; |
| UNSG32 value = 0; |
| |
| if ((port >= 0) && (port < 16)) { |
| iomapper_reg = IOMAPPER_REG_MAP_4; |
| } else if ((port >= 16) && (port < 32)) { |
| iomapper_reg = IOMAPPER_REG_MAP_5; |
| port -= 16; |
| } else |
| return -1; |
| |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, 1, iomapper_reg, &value); |
| if (in) |
| value |= (1 << port); |
| else |
| value &= ~(1 << port); |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, 0, iomapper_reg, &value); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Get the in/out status of GPIO pin at IOmapper |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * *inout - return PORT_DDR_IN or PORT_DDR_OUT |
| * RETURN: 0 - succeed |
| * -1 - fail |
| * NOTE: Be sure that spi_master_init_iomapper is done. |
| ***************************************************/ |
| int GPIO_IOmapperGetInOut(int port, int *inout) |
| { |
| int iomapper_reg; |
| |
| if ((port >= 0) && (port < 16)) { |
| iomapper_reg = IOMAPPER_REG_MAP_4; |
| } else if ((port >= 16) && (port < 32)) { |
| iomapper_reg = IOMAPPER_REG_MAP_5; |
| port -= 16; |
| } else |
| return -1; |
| |
| spi_master_rw_iomapper(IOMAPPER_SPI_MASTER, IOMAPPER_SPI_DEVID, 1, iomapper_reg, inout); |
| *inout = (*inout & (1 << port))? PORT_DDR_IN : PORT_DDR_OUT; |
| |
| return 0; |
| } |
| #endif /* BERLIN */ |
| #endif |
| /**************************************************** |
| * FUNCTION: Set Galois GPIO pin as in or out |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * in - 1: IN, 0: OUT |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int GPIO_PortSetInOut(int port, int in) |
| { |
| int reg_ddr, reg_ctl; |
| int ddr, ctl; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = APB_GPIO_INST0_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ctl = APB_GPIO_INST0_BASE + APB_GPIO_PORTA_CTL; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_ddr = APB_GPIO_INST1_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ctl = APB_GPIO_INST1_BASE + APB_GPIO_PORTA_CTL; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_ddr = APB_GPIO_INST2_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ctl = APB_GPIO_INST2_BASE + APB_GPIO_PORTA_CTL; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_ddr = APB_GPIO_INST3_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ctl = APB_GPIO_INST3_BASE + APB_GPIO_PORTA_CTL; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* software mode */ |
| GA_REG_WORD32_READ(reg_ctl, &ctl); |
| ctl &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_ctl, ctl); |
| |
| /* set port to output mode */ |
| GA_REG_WORD32_READ(reg_ddr, &ddr); |
| if (in) |
| ddr &= ~(1 << port); |
| else |
| ddr |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_ddr, ddr); |
| |
| return 0; |
| } |
| #if 0 |
| /**************************************************** |
| * FUNCTION: Get direction of Galois GPIO pin: in or out |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * *inout - PORT_DDR_IN: IN, PORT_DDR_OUT: OUT |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int GPIO_PortGetInOut(int port, int *inout) |
| { |
| int reg_ddr; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = APB_GPIO_INST0_BASE + APB_GPIO_SWPORTA_DDR; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_ddr = APB_GPIO_INST1_BASE + APB_GPIO_SWPORTA_DDR; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_ddr = APB_GPIO_INST2_BASE + APB_GPIO_SWPORTA_DDR; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_ddr = APB_GPIO_INST3_BASE + APB_GPIO_SWPORTA_DDR; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* set port to output mode */ |
| GA_REG_WORD32_READ(reg_ddr, inout); |
| *inout = (*inout & (1 << port))? PORT_DDR_OUT : PORT_DDR_IN; |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Get data of Galois GPIO pin |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * *data - the data in APB_GPIO_SWPORTA_DR |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int GPIO_PortGetData(int port, int *data) |
| { |
| int reg_dr; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_dr = APB_GPIO_INST0_BASE + APB_GPIO_SWPORTA_DR; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_dr = APB_GPIO_INST1_BASE + APB_GPIO_SWPORTA_DR; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_dr = APB_GPIO_INST2_BASE + APB_GPIO_SWPORTA_DR; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_dr = APB_GPIO_INST3_BASE + APB_GPIO_SWPORTA_DR; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* set port to output mode */ |
| GA_REG_WORD32_READ(reg_dr, data); |
| *data = (*data & (1 << port))? 1: 0; |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Init interrupt for Galois GPIO pin, and set |
| * interrupt level or edge, but keep interrupt closed. |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * int_edge - 1: edge triggered, 0: level triggered. |
| * int_polarity - 1: rise edge/high level triggered. |
| * 0: fall edge/low level triggered. |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int GPIO_PortInitIRQ(int port, int int_edge, int int_polarity) |
| { |
| int reg_ddr, reg_debounce, reg_edge, reg_polarity; |
| int reg_mask;//, reg_en, reg_eoi; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = APB_GPIO_INST0_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_mask = APB_GPIO_INST0_BASE + APB_GPIO_INTMASK; |
| //reg_en = APB_GPIO_INST0_BASE + APB_GPIO_INTEN; |
| //reg_eoi = APB_GPIO_INST0_BASE + APB_GPIO_PORTA_EOI; |
| reg_debounce = APB_GPIO_INST0_BASE + APB_GPIO_DEBOUNCE; |
| reg_edge = APB_GPIO_INST0_BASE + APB_GPIO_INTTYPE_LEVEL; |
| reg_polarity = APB_GPIO_INST0_BASE + APB_GPIO_INT_POLARITY; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_ddr = APB_GPIO_INST1_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_mask = APB_GPIO_INST1_BASE + APB_GPIO_INTMASK; |
| //reg_en = APB_GPIO_INST1_BASE + APB_GPIO_INTEN; |
| //reg_eoi = APB_GPIO_INST1_BASE + APB_GPIO_PORTA_EOI; |
| reg_debounce = APB_GPIO_INST1_BASE + APB_GPIO_DEBOUNCE; |
| reg_edge = APB_GPIO_INST1_BASE + APB_GPIO_INTTYPE_LEVEL; |
| reg_polarity = APB_GPIO_INST1_BASE + APB_GPIO_INT_POLARITY; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_ddr = APB_GPIO_INST2_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_mask = APB_GPIO_INST2_BASE + APB_GPIO_INTMASK; |
| //reg_en = APB_GPIO_INST2_BASE + APB_GPIO_INTEN; |
| //reg_eoi = APB_GPIO_INST2_BASE + APB_GPIO_PORTA_EOI; |
| reg_debounce = APB_GPIO_INST2_BASE + APB_GPIO_DEBOUNCE; |
| reg_edge = APB_GPIO_INST2_BASE + APB_GPIO_INTTYPE_LEVEL; |
| reg_polarity = APB_GPIO_INST2_BASE + APB_GPIO_INT_POLARITY; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_ddr = APB_GPIO_INST3_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_mask = APB_GPIO_INST3_BASE + APB_GPIO_INTMASK; |
| //reg_en = APB_GPIO_INST3_BASE + APB_GPIO_INTEN; |
| //reg_eoi = APB_GPIO_INST3_BASE + APB_GPIO_PORTA_EOI; |
| reg_debounce = APB_GPIO_INST3_BASE + APB_GPIO_DEBOUNCE; |
| reg_edge = APB_GPIO_INST3_BASE + APB_GPIO_INTTYPE_LEVEL; |
| reg_polarity = APB_GPIO_INST3_BASE + APB_GPIO_INT_POLARITY; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* Mask interrupt */ |
| GA_REG_WORD32_READ(reg_mask, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| /* Direction is input */ |
| GA_REG_WORD32_READ(reg_ddr, &value); |
| value &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_ddr, value); |
| |
| /* Enable debounce */ |
| GA_REG_WORD32_READ(reg_debounce, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_debounce, value); |
| |
| /* int_edge=1: Edge triggered interrupt */ |
| GA_REG_WORD32_READ(reg_edge, &value); |
| value |= (int_edge << port); |
| GA_REG_WORD32_WRITE(reg_edge, value); |
| |
| /* int_polarity=1: rise-edge triggered interrupt */ |
| GA_REG_WORD32_READ(reg_polarity, &value); |
| value |= (int_polarity << port); |
| GA_REG_WORD32_WRITE(reg_polarity, value); |
| |
| /* Enable interrupt */ |
| //GA_REG_WORD32_READ(reg_en, &value); |
| //value |= (1 << port); |
| //GA_REG_WORD32_WRITE(reg_en, value); |
| |
| /* Write-only, write 1 to clear interrupt */ |
| //value = (1 << port); |
| //GA_REG_WORD32_WRITE(reg_eoi, value); |
| |
| /* Unmask interrupt */ |
| //GA_REG_WORD32_READ(reg_mask, &value); |
| //value &= ~(1 << port); |
| //GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Enable interrupt for Galois GPIO pin |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * RETURN: 0 - succeed |
| * -1 - fail |
| * NOTE: You also need to enable GPIO interrupt in ICTL. |
| ***************************************************/ |
| int GPIO_PortEnableIRQ(int port) |
| { |
| int reg_mask, reg_en, reg_eoi; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_mask = APB_GPIO_INST0_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST0_BASE + APB_GPIO_INTEN; |
| reg_eoi = APB_GPIO_INST0_BASE + APB_GPIO_PORTA_EOI; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_mask = APB_GPIO_INST1_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST1_BASE + APB_GPIO_INTEN; |
| reg_eoi = APB_GPIO_INST1_BASE + APB_GPIO_PORTA_EOI; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_mask = APB_GPIO_INST2_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST2_BASE + APB_GPIO_INTEN; |
| reg_eoi = APB_GPIO_INST2_BASE + APB_GPIO_PORTA_EOI; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_mask = APB_GPIO_INST3_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST3_BASE + APB_GPIO_INTEN; |
| reg_eoi = APB_GPIO_INST3_BASE + APB_GPIO_PORTA_EOI; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* Enable interrupt */ |
| GA_REG_WORD32_READ(reg_en, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_en, value); |
| |
| /* Write-only, write 1 to clear interrupt */ |
| value = (1 << port); |
| GA_REG_WORD32_WRITE(reg_eoi, value); |
| |
| /* Unmask interrupt */ |
| GA_REG_WORD32_READ(reg_mask, &value); |
| value &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Disable interrupt for Galois GPIO pin |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int GPIO_PortDisableIRQ(int port) |
| { |
| int reg_mask, reg_en; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_mask = APB_GPIO_INST0_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST0_BASE + APB_GPIO_INTEN; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_mask = APB_GPIO_INST1_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST1_BASE + APB_GPIO_INTEN; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_mask = APB_GPIO_INST2_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST2_BASE + APB_GPIO_INTEN; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_mask = APB_GPIO_INST3_BASE + APB_GPIO_INTMASK; |
| reg_en = APB_GPIO_INST3_BASE + APB_GPIO_INTEN; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* Mask interrupt */ |
| GA_REG_WORD32_READ(reg_mask, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| /* Disable interrupt */ |
| GA_REG_WORD32_READ(reg_en, &value); |
| value &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_en, value); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Lookup if there's interrupt for Galois GPIO pin |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * RETURN: 1 - yes, there's interrupt pending. |
| * 0 - no, there's no interrupt pending. |
| * -1 - fail. |
| ***************************************************/ |
| int GPIO_PortHasInterrupt(int port) |
| { |
| int reg_status; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_status = APB_GPIO_INST0_BASE + APB_GPIO_INTSTATUS; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_status = APB_GPIO_INST1_BASE + APB_GPIO_INTSTATUS; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_status = APB_GPIO_INST2_BASE + APB_GPIO_INTSTATUS; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_status = APB_GPIO_INST3_BASE + APB_GPIO_INTSTATUS; |
| port -= 24; |
| } else |
| return -1; |
| |
| GA_REG_WORD32_READ(reg_status, &value); |
| if (value & (0x1 << port)) |
| return 1; |
| else |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Clear interrupt for Galois GPIO pin |
| * PARAMS: port - GPIO port # (0 ~ 31) |
| * RETURN: 0 - succeed. |
| * -1 - fail. |
| ***************************************************/ |
| int GPIO_PortClearInterrupt(int port) |
| { |
| int reg_eoi; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_eoi = APB_GPIO_INST0_BASE + APB_GPIO_PORTA_EOI; |
| } else if ((port >= 8) && (port < 16)){ |
| reg_eoi = APB_GPIO_INST1_BASE + APB_GPIO_PORTA_EOI; |
| port -= 8; |
| } else if ((port >= 16) && (port < 24)){ |
| reg_eoi = APB_GPIO_INST2_BASE + APB_GPIO_PORTA_EOI; |
| port -= 16; |
| } else if ((port >= 24) && (port < 32)){ |
| reg_eoi = APB_GPIO_INST3_BASE + APB_GPIO_PORTA_EOI; |
| port -= 24; |
| } else |
| return -1; |
| |
| /* see above, write 1 to clear interrupt */ |
| value = (1 << port); |
| GA_REG_WORD32_WRITE(reg_eoi, value); |
| return 0; |
| } |
| #endif |
| #if defined(BERLIN) |
| ////////////////////////////////////////////////////////// |
| // Only port 0-7 can support SM_GPIO interrupt |
| ////////////////////////////////////////////////////////// |
| |
| /**************************************************** |
| * FUNCTION: toggle SM_GPIO port between high and low |
| * PARAMS: port - SM_GPIO port # (0 ~ 11) |
| * value - 1: high; 0: low |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int SM_GPIO_PortWrite(int port, int value) |
| { |
| int reg_ddr, reg_dr, reg_ctl; |
| int ddr, dr, ctl; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_dr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTA_DR; |
| reg_ctl = SM_APB_GPIO_BASE + APB_GPIO_PORTA_CTL; |
| } else if ((port >= 8) && (port < 16)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_ddr = SM_APB_GPIO1_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_dr = SM_APB_GPIO1_BASE + APB_GPIO_SWPORTA_DR; |
| reg_ctl = SM_APB_GPIO1_BASE + APB_GPIO_PORTA_CTL; |
| #else |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTB_DDR; |
| reg_dr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTB_DR; |
| reg_ctl = SM_APB_GPIO_BASE + APB_GPIO_PORTB_CTL; |
| #endif |
| port -= 8; |
| } else |
| return -1; |
| |
| /* software mode */ |
| GA_REG_WORD32_READ(reg_ctl, &ctl); |
| ctl &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_ctl, ctl); |
| |
| /* set port to output mode */ |
| GA_REG_WORD32_READ(reg_ddr, &ddr); |
| ddr |= (1<<port); |
| GA_REG_WORD32_WRITE(reg_ddr, ddr); |
| |
| /* set port value */ |
| GA_REG_WORD32_READ(reg_dr, &dr); |
| if (value){ |
| dr |= (1<<port); |
| } else { |
| dr &= ~(1<<port); |
| } |
| GA_REG_WORD32_WRITE(reg_dr, dr); |
| return 0; |
| } |
| #if 0 |
| /**************************************************** |
| * FUNCTION: read SM_GPIO port status |
| * PARAMS: port - SM_GPIO port # (0 ~ 11) |
| * *value - pointer to port status |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int SM_GPIO_PortRead(int port, int *value) |
| { |
| int reg_ddr, reg_ext, reg_ctl; |
| int ddr, ext, ctl; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ext = SM_APB_GPIO_BASE + APB_GPIO_EXT_PORTA; |
| reg_ctl = SM_APB_GPIO_BASE + APB_GPIO_PORTA_CTL; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_ddr = SM_APB_GPIO1_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ext = SM_APB_GPIO1_BASE + APB_GPIO_EXT_PORTA; |
| reg_ctl = SM_APB_GPIO1_BASE + APB_GPIO_PORTA_CTL; |
| #else |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTB_DDR; |
| reg_ext = SM_APB_GPIO_BASE + APB_GPIO_EXT_PORTB; |
| reg_ctl = SM_APB_GPIO_BASE + APB_GPIO_PORTB_CTL; |
| #endif |
| port -= 8; |
| } else |
| return -1; |
| |
| /* software mode */ |
| GA_REG_WORD32_READ(reg_ctl, &ctl); |
| ctl &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_ctl, ctl); |
| |
| /* set port to input mode */ |
| GA_REG_WORD32_READ(reg_ddr, &ddr); |
| ddr &= ~(1<<port); |
| GA_REG_WORD32_WRITE(reg_ddr, ddr); |
| |
| /* get port value */ |
| GA_REG_WORD32_READ(reg_ext, &ext); |
| if (ext & (1<<port)) |
| *value = 1; |
| else |
| *value = 0; |
| |
| return 0; |
| } |
| |
| #endif |
| |
| /**************************************************** |
| * FUNCTION: Set Galois SM_GPIO pin as in or out |
| * PARAMS: port - SM_GPIO port # (0 ~ 11) |
| * in - 1: IN, 0: OUT |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int SM_GPIO_PortSetInOut(int port, int in) |
| { |
| int reg_ddr, reg_ctl; |
| int ddr, ctl; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ctl = SM_APB_GPIO_BASE + APB_GPIO_PORTA_CTL; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_ddr = SM_APB_GPIO1_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_ctl = SM_APB_GPIO1_BASE + APB_GPIO_PORTA_CTL; |
| #else |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTB_DDR; |
| reg_ctl = SM_APB_GPIO_BASE + APB_GPIO_PORTB_CTL; |
| #endif |
| port -= 8; |
| } else |
| return -1; |
| |
| /* software mode */ |
| GA_REG_WORD32_READ(reg_ctl, &ctl); |
| ctl &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_ctl, ctl); |
| |
| /* set port to output mode */ |
| GA_REG_WORD32_READ(reg_ddr, &ddr); |
| if (in) |
| ddr &= ~(1 << port); |
| else |
| ddr |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_ddr, ddr); |
| |
| return 0; |
| } |
| #if 0 |
| /**************************************************** |
| * FUNCTION: Get direction of Galois SM_GPIO pin: in or out |
| * PARAMS: port - SM_GPIO port # (0 ~ 11) |
| * *inout - PORT_DDR_IN: IN, PORT_DDR_OUT: OUT |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int SM_GPIO_PortGetInOut(int port, int *inout) |
| { |
| int reg_ddr; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTA_DDR; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_ddr = SM_APB_GPIO1_BASE + APB_GPIO_SWPORTA_DDR; |
| #else |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTB_DDR; |
| #endif |
| port -= 8; |
| } else |
| return -1; |
| |
| /* set port to output mode */ |
| GA_REG_WORD32_READ(reg_ddr, inout); |
| *inout = (*inout & (1 << port))? PORT_DDR_OUT : PORT_DDR_IN; |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Get data of Galois SM_GPIO pin |
| * PARAMS: port - SM_GPIO port # (0 ~ 11) |
| * *data - the data in APB_GPIO_SWPORTA_DR |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int SM_GPIO_PortGetData(int port, int *data) |
| { |
| int reg_dr; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_dr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTA_DR; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_dr = SM_APB_GPIO1_BASE + APB_GPIO_SWPORTA_DR; |
| #else |
| reg_dr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTB_DR; |
| #endif |
| port -= 8; |
| } else |
| return -1; |
| |
| /* set port to output mode */ |
| GA_REG_WORD32_READ(reg_dr, data); |
| *data = (*data & (1 << port))? 1: 0; |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Init interrupt for Galois SM_GPIO pin, and set |
| * interrupt level or edge, but keep interrupt closed. |
| * PARAMS: port - SM_GPIO port # (0 ~ 7) |
| * int_edge - 1: edge triggered, 0: level triggered. |
| * int_polarity - 1: rise edge/high level triggered. |
| * 0: fall edge/low level triggered. |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int SM_GPIO_PortInitIRQ(int port, int int_edge, int int_polarity) |
| { |
| int reg_ddr, reg_debounce, reg_edge, reg_polarity; |
| int reg_mask;//, reg_en, reg_eoi; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_ddr = SM_APB_GPIO_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_mask = SM_APB_GPIO_BASE + APB_GPIO_INTMASK; |
| //reg_en = SM_APB_GPIO_BASE + APB_GPIO_INTEN; |
| //reg_eoi = SM_APB_GPIO_BASE + APB_GPIO_PORTA_EOI; |
| reg_debounce = SM_APB_GPIO_BASE + APB_GPIO_DEBOUNCE; |
| reg_edge = SM_APB_GPIO_BASE + APB_GPIO_INTTYPE_LEVEL; |
| reg_polarity = SM_APB_GPIO_BASE + APB_GPIO_INT_POLARITY; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_ddr = SM_APB_GPIO1_BASE + APB_GPIO_SWPORTA_DDR; |
| reg_mask = SM_APB_GPIO1_BASE + APB_GPIO_INTMASK; |
| //reg_en = SM_APB_GPIO1_BASE + APB_GPIO_INTEN; |
| //reg_eoi = SM_APB_GPIO1_BASE + APB_GPIO_PORTA_EOI; |
| reg_debounce = SM_APB_GPIO1_BASE + APB_GPIO_DEBOUNCE; |
| reg_edge = SM_APB_GPIO1_BASE + APB_GPIO_INTTYPE_LEVEL; |
| reg_polarity = SM_APB_GPIO1_BASE + APB_GPIO_INT_POLARITY; |
| port -= 8; |
| #else |
| return -1; |
| #endif |
| } else { |
| return -1; |
| } |
| |
| /* Mask interrupt */ |
| GA_REG_WORD32_READ(reg_mask, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| /* Direction is input */ |
| GA_REG_WORD32_READ(reg_ddr, &value); |
| value &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_ddr, value); |
| |
| /* Enable debounce */ |
| GA_REG_WORD32_READ(reg_debounce, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_debounce, value); |
| |
| /* int_edge=1: Edge triggered interrupt */ |
| GA_REG_WORD32_READ(reg_edge, &value); |
| value |= (int_edge << port); |
| GA_REG_WORD32_WRITE(reg_edge, value); |
| |
| /* int_polarity=1: rise-edge triggered interrupt */ |
| GA_REG_WORD32_READ(reg_polarity, &value); |
| value |= (int_polarity << port); |
| GA_REG_WORD32_WRITE(reg_polarity, value); |
| |
| /* Enable interrupt */ |
| //GA_REG_WORD32_READ(reg_en, &value); |
| //value |= (1 << port); |
| //GA_REG_WORD32_WRITE(reg_en, value); |
| |
| /* Write-only, write 1 to clear interrupt */ |
| //value = (1 << port); |
| //GA_REG_WORD32_WRITE(reg_eoi, value); |
| |
| /* Unmask interrupt */ |
| //GA_REG_WORD32_READ(reg_mask, &value); |
| //value &= ~(1 << port); |
| //GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Enable interrupt for Galois SM_GPIO pin |
| * PARAMS: port - SM_GPIO port # (0 ~ 7) |
| * RETURN: 0 - succeed |
| * -1 - fail |
| * NOTE: You also need to enable SM_GPIO interrupt in ICTL. |
| ***************************************************/ |
| int SM_GPIO_PortEnableIRQ(int port) |
| { |
| int reg_mask, reg_en, reg_eoi; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_mask = SM_APB_GPIO_BASE + APB_GPIO_INTMASK; |
| reg_en = SM_APB_GPIO_BASE + APB_GPIO_INTEN; |
| reg_eoi = SM_APB_GPIO_BASE + APB_GPIO_PORTA_EOI; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_mask = SM_APB_GPIO1_BASE + APB_GPIO_INTMASK; |
| reg_en = SM_APB_GPIO1_BASE + APB_GPIO_INTEN; |
| reg_eoi = SM_APB_GPIO1_BASE + APB_GPIO_PORTA_EOI; |
| port -= 8; |
| #else |
| return -1; |
| #endif |
| } else { |
| return -1; |
| } |
| |
| /* Enable interrupt */ |
| GA_REG_WORD32_READ(reg_en, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_en, value); |
| |
| /* Write-only, write 1 to clear interrupt */ |
| value = (1 << port); |
| GA_REG_WORD32_WRITE(reg_eoi, value); |
| |
| /* Unmask interrupt */ |
| GA_REG_WORD32_READ(reg_mask, &value); |
| value &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Disable interrupt for Galois SM_GPIO pin |
| * PARAMS: port - SM_GPIO port # (0 ~ 7) |
| * RETURN: 0 - succeed |
| * -1 - fail |
| ***************************************************/ |
| int SM_GPIO_PortDisableIRQ(int port) |
| { |
| int reg_mask, reg_en; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_mask = SM_APB_GPIO_BASE + APB_GPIO_INTMASK; |
| reg_en = SM_APB_GPIO_BASE + APB_GPIO_INTEN; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_mask = SM_APB_GPIO1_BASE + APB_GPIO_INTMASK; |
| reg_en = SM_APB_GPIO1_BASE + APB_GPIO_INTEN; |
| port -= 8; |
| #else |
| return -1; |
| #endif |
| } else { |
| return -1; |
| } |
| |
| /* Mask interrupt */ |
| GA_REG_WORD32_READ(reg_mask, &value); |
| value |= (1 << port); |
| GA_REG_WORD32_WRITE(reg_mask, value); |
| |
| /* Disable interrupt */ |
| GA_REG_WORD32_READ(reg_en, &value); |
| value &= ~(1 << port); |
| GA_REG_WORD32_WRITE(reg_en, value); |
| |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Lookup if there's interrupt for Galois SM_GPIO pin |
| * PARAMS: port - SM_GPIO port # (0 ~ 7) |
| * RETURN: 1 - yes, there's interrupt pending. |
| * 0 - no, there's no interrupt pending. |
| * -1 - fail. |
| ***************************************************/ |
| int SM_GPIO_PortHasInterrupt(int port) |
| { |
| int reg_status; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_status = SM_APB_GPIO_BASE + APB_GPIO_INTSTATUS; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_status = SM_APB_GPIO1_BASE + APB_GPIO_INTSTATUS; |
| port -= 8; |
| #else |
| return -1; |
| #endif |
| } else { |
| return -1; |
| } |
| |
| GA_REG_WORD32_READ(reg_status, &value); |
| if (value & (0x1 << port)) |
| return 1; |
| else |
| return 0; |
| } |
| |
| /**************************************************** |
| * FUNCTION: Clear interrupt for Galois SM_GPIO pin |
| * PARAMS: port - SM_GPIO port # (0 ~ 7) |
| * RETURN: 0 - succeed. |
| * -1 - fail. |
| ***************************************************/ |
| int SM_GPIO_PortClearInterrupt(int port) |
| { |
| int reg_eoi; |
| int value; |
| |
| if((port >= 0) && (port < 8)){ |
| reg_eoi = SM_APB_GPIO_BASE + APB_GPIO_PORTA_EOI; |
| } else if ((port >= 8) && (port < 12)){ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_C_0) |
| reg_eoi = SM_APB_GPIO1_BASE + APB_GPIO_PORTA_EOI; |
| port -= 8; |
| #else |
| return -1; |
| #endif |
| } else { |
| return -1; |
| } |
| |
| /* see above, write 1 to clear interrupt */ |
| value = (1 << port); |
| GA_REG_WORD32_WRITE(reg_eoi, value); |
| return 0; |
| } |
| #endif /* BERLIN */ |
| #endif |
| /* |
| * the low-level GPIO api may be used by linux kernel driver. |
| * so it's exported. |
| */ |
| #ifdef __LINUX_KERNEL__ |
| EXPORT_SYMBOL(GPIO_PortWrite); |
| EXPORT_SYMBOL(GPIO_PortRead); |
| EXPORT_SYMBOL(GPIO_PinmuxInit); |
| EXPORT_SYMBOL(GPIO_PortSetInOut); |
| EXPORT_SYMBOL(GPIO_PortGetInOut); |
| EXPORT_SYMBOL(GPIO_PortGetData); |
| EXPORT_SYMBOL(GPIO_PortInitIRQ); |
| EXPORT_SYMBOL(GPIO_PortEnableIRQ); |
| EXPORT_SYMBOL(GPIO_PortDisableIRQ); |
| EXPORT_SYMBOL(GPIO_PortHasInterrupt); |
| EXPORT_SYMBOL(GPIO_PortClearInterrupt); |
| EXPORT_SYMBOL(SM_GPIO_PortWrite); |
| EXPORT_SYMBOL(SM_GPIO_PortRead); |
| EXPORT_SYMBOL(SM_GPIO_PortSetInOut); |
| EXPORT_SYMBOL(SM_GPIO_PortGetInOut); |
| EXPORT_SYMBOL(SM_GPIO_PortGetData); |
| EXPORT_SYMBOL(SM_GPIO_PortInitIRQ); |
| EXPORT_SYMBOL(SM_GPIO_PortEnableIRQ); |
| EXPORT_SYMBOL(SM_GPIO_PortDisableIRQ); |
| EXPORT_SYMBOL(SM_GPIO_PortHasInterrupt); |
| EXPORT_SYMBOL(SM_GPIO_PortClearInterrupt); |
| #endif /* __LINUX_KERNEL__ */ |