From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mario Six Date: Wed, 25 May 2016 15:15:22 +0200 Subject: [U-Boot] [PATCH v5 3/4] dm: gpio: Implement open drain for MPC85XX GPIO In-Reply-To: <1464182123-14160-1-git-send-email-mario.six@gdsys.cc> References: <1464182123-14160-1-git-send-email-mario.six@gdsys.cc> Message-ID: <1464182123-14160-4-git-send-email-mario.six@gdsys.cc> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: "mario.six@gdsys.cc" This patch implements the open-drain setting feature for the MPC85XX GPIO controller. Signed-off-by: Mario Six --- v5: None v4: - Added forgotten mpc85xx_gpio_{get,set}_open_drain functions v3: - Added comments v2: - Added missing commit message - Fixed white space issues in function headers --- drivers/gpio/Kconfig | 6 +++--- drivers/gpio/mpc85xx_gpio.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b674a47..8595e2e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -193,9 +193,9 @@ config MPC85XX_GPIO configurable to match the actual GPIO count of the SoC (e.g. the 32/32/23 banks of the P1022 SoC). - The standard functions of input/output mode, and output value setting - are supported; the open-drain capability of the controller is not - supported yet. + Aside from the standard functions of input/output mode, and output + value setting, the open-drain feature, which can configure individual + GPIOs to work as open-drain outputs, is supported. The driver has been tested on MPC85XX, but it is likely that other PowerQUICC III devices will work as well. diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c index 17755df..04773e2 100644 --- a/drivers/gpio/mpc85xx_gpio.c +++ b/drivers/gpio/mpc85xx_gpio.c @@ -73,6 +73,25 @@ static inline void mpc85xx_gpio_set_high(struct ccsr_gpio *base, u32 gpios) setbits_be32(&base->gpdir, gpios); } +static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask) +{ + return in_be32(&base->gpodr) & mask; +} + +static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio *base, u32 + gpios) +{ + /* GPODR register 1 -> open drain on */ + setbits_be32(&base->gpodr, gpios); +} + +static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio *base, + u32 gpios) +{ + /* GPODR register 0 -> open drain off (actively driven) */ + clrbits_be32(&base->gpodr, gpios); +} + static int mpc85xx_gpio_direction_input(struct udevice *dev, unsigned gpio) { struct mpc85xx_gpio_data *data = dev_get_priv(dev); @@ -115,6 +134,26 @@ static int mpc85xx_gpio_get_value(struct udevice *dev, unsigned gpio) } } +static int mpc85xx_gpio_get_open_drain(struct udevice *dev, unsigned gpio) +{ + struct mpc85xx_gpio_data *data = dev_get_priv(dev); + + return !!mpc85xx_gpio_open_drain_val(data->base, gpio_mask(gpio)); +} + +static int mpc85xx_gpio_set_open_drain(struct udevice *dev, unsigned gpio, + int value) +{ + struct mpc85xx_gpio_data *data = dev_get_priv(dev); + + if (value) { + mpc85xx_gpio_open_drain_on(data->base, gpio_mask(gpio)); + } else { + mpc85xx_gpio_open_drain_off(data->base, gpio_mask(gpio)); + } + return 0; +} + static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio) { struct mpc85xx_gpio_data *data = dev_get_priv(dev); @@ -168,6 +207,8 @@ static const struct dm_gpio_ops gpio_mpc85xx_ops = { .direction_output = mpc85xx_gpio_direction_output, .get_value = mpc85xx_gpio_get_value, .set_value = mpc85xx_gpio_set_value, + .get_open_drain = mpc85xx_gpio_get_open_drain, + .set_open_drain = mpc85xx_gpio_set_open_drain, .get_function = mpc85xx_gpio_get_function, }; -- 2.7.0.GIT