/* * This file is part of the coreboot project. * * Copyright 2015 Marvell Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #define MV_GPIO_MAX_NUM 59 #define MV_GPP_IN 0xFFFFFFFF /* GPP input */ #define MV_GPP_OUT 0 /* GPP output */ #define MV_GPP_REGS_BASE(unit) (0x18100 + ((unit)*0x40)) #define GPP_DATA_OUT_EN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x04) #define GPP_DATA_IN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x10) #define GPP_DATA_OUT_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x00) static void gpp_reg_set(u32 group, u32 reg_offs, u32 mask, u32 value); static int mv_gpp_type_set(u32 group, u32 mask, u32 value); static u32 mv_gpp_value_get(u32 group, u32 mask); static int mv_gpp_value_set(u32 group, u32 mask, u32 value); void gpp_reg_set(u32 group, u32 reg_offs, u32 mask, u32 value) { u32 gpp_data; gpp_data = mrvl_reg_read(reg_offs); gpp_data &= ~mask; gpp_data |= (value & mask); mrvl_reg_write(reg_offs, gpp_data); } int mv_gpp_type_set(u32 group, u32 mask, u32 value) { gpp_reg_set(group, GPP_DATA_OUT_EN_REG(group), mask, value); return MV_OK; } u32 mv_gpp_value_get(u32 group, u32 mask) { u32 gpp_data; gpp_data = mrvl_reg_read(GPP_DATA_IN_REG(group)); gpp_data &= mask; return gpp_data; } int mv_gpp_value_set(u32 group, u32 mask, u32 value) { u32 out_enable; /* verify that the gpp pin is configured as output*/ /* Note that in the register out enabled -> bit = '0'.*/ out_enable = ~(mrvl_reg_read(GPP_DATA_OUT_EN_REG(group))); if ((out_enable & mask) != mask) { printk(BIOS_ERR, "Mask and out_enable mismatch(mask:0x%x, out_enable:0x%x).\n", mask, (out_enable & mask)); return MV_ERROR; } gpp_reg_set(group, GPP_DATA_OUT_REG(group), mask, value); return MV_OK; } static inline int gpio_not_valid(gpio_t gpio) { return (gpio > MV_GPIO_MAX_NUM); } int gpio_get(gpio_t gpio) { u32 group = 0; u32 gpp_data; if (gpio_not_valid(gpio)) return MV_BAD_PARAM; if (gpio >= 32) { group = 1; gpio -= 32; } mv_gpp_type_set(group, (1 << gpio), MV_GPP_IN & (1 << gpio)); gpp_data = mv_gpp_value_get(group, (1 << gpio)); return (gpp_data != 0); } void gpio_set(gpio_t gpio, int value) { u32 group = 0; if (gpio_not_valid(gpio)) return; if (gpio >= 32) { group = 1; gpio -= 32; } mv_gpp_type_set(group, (1 << gpio), MV_GPP_OUT & (1 << gpio)); mv_gpp_value_set(group, (1 << gpio), (value ? (1 << gpio) : 0)); }