svn commit: r351139 - in stable/12/sys: arm/mv arm64/conf conf dev/sdhci

Emmanuel Vadot manu at FreeBSD.org
Fri Aug 16 20:49:11 UTC 2019


Author: manu
Date: Fri Aug 16 20:49:10 2019
New Revision: 351139
URL: https://svnweb.freebsd.org/changeset/base/351139

Log:
  MFC r348880, r348882
  
  r348880 by loos:
  Add the GPIO driver for the North/South bridge in Marvell Armada 37x0.
  
  The A3700 has a different GPIO controller and thus, do not use the old (and
  shared) code for Marvell.
  
  The pinctrl driver, also part of the controller, is not supported yet (but
  the implementation should be straightforward).
  
  Sponsored by:	Rubicon Communications, LLC (Netgate)
  
  r348882 by loos:
  Add support for the GPIO SD Card VCC regulator/switch and the GPIO SD Card
  detection pins to the Marvell Xenon SDHCI controller.
  
  These features are enable by 'vqmmc-supply' and 'cd-gpios' properties in the
  DTS.
  
  This fixes the SD Card detection on espressobin.
  
  Sponsored by:	Rubicon Communications, LLC (Netgate)

Added:
  stable/12/sys/arm/mv/a37x0_gpio.c
     - copied unchanged from r348880, head/sys/arm/mv/a37x0_gpio.c
Modified:
  stable/12/sys/arm64/conf/GENERIC
  stable/12/sys/conf/files.arm64
  stable/12/sys/dev/sdhci/sdhci_xenon.c
Directory Properties:
  stable/12/   (props changed)

Copied: stable/12/sys/arm/mv/a37x0_gpio.c (from r348880, head/sys/arm/mv/a37x0_gpio.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/12/sys/arm/mv/a37x0_gpio.c	Fri Aug 16 20:49:10 2019	(r351139, copy of r348880, head/sys/arm/mv/a37x0_gpio.c)
@@ -0,0 +1,352 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018-2019, Rubicon Communications, LLC (Netgate)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+
+static struct resource_spec a37x0_gpio_res_spec[] = {
+	{ SYS_RES_MEMORY, 0, RF_ACTIVE },	/* Pinctl / GPIO */
+	{ SYS_RES_MEMORY, 1, RF_ACTIVE },	/* Interrupts control */
+	{ -1, 0, 0 }
+};
+
+struct a37x0_gpio_softc {
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh;
+	device_t		sc_busdev;
+	int			sc_type;
+	uint32_t		sc_max_pins;
+	uint32_t		sc_npins;
+	struct resource		*sc_mem_res[nitems(a37x0_gpio_res_spec) - 1];
+};
+
+/* Memory regions. */
+#define	A37X0_GPIO			0
+#define	A37X0_INTR			1
+
+/* North Bridge / South Bridge. */
+#define	A37X0_NB_GPIO			1
+#define	A37X0_SB_GPIO			2
+
+#define	A37X0_GPIO_WRITE(_sc, _off, _val)		\
+    bus_space_write_4((_sc)->sc_bst, (_sc)->sc_bsh, (_off), (_val))
+#define	A37X0_GPIO_READ(_sc, _off)			\
+    bus_space_read_4((_sc)->sc_bst, (_sc)->sc_bsh, (_off))
+
+#define	A37X0_GPIO_BIT(_p)		(1U << ((_p) % 32))
+#define	A37X0_GPIO_OUT_EN(_p)		(0x0 + ((_p) / 32) * 4)
+#define	A37X0_GPIO_LATCH(_p)		(0x8 + ((_p) / 32) * 4)
+#define	A37X0_GPIO_INPUT(_p)		(0x10 + ((_p) / 32) * 4)
+#define	A37X0_GPIO_OUTPUT(_p)		(0x18 + ((_p) / 32) * 4)
+#define	A37X0_GPIO_SEL			0x30
+
+
+static struct ofw_compat_data compat_data[] = {
+	{ "marvell,armada3710-nb-pinctrl",	A37X0_NB_GPIO },
+	{ "marvell,armada3710-sb-pinctrl",	A37X0_SB_GPIO },
+	{ NULL, 0 }
+};
+
+static phandle_t
+a37x0_gpio_get_node(device_t bus, device_t dev)
+{
+
+	return (ofw_bus_get_node(bus));
+}
+
+static device_t
+a37x0_gpio_get_bus(device_t dev)
+{
+	struct a37x0_gpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	return (sc->sc_busdev);
+}
+
+static int
+a37x0_gpio_pin_max(device_t dev, int *maxpin)
+{
+	struct a37x0_gpio_softc *sc;
+
+	sc = device_get_softc(dev);
+	*maxpin = sc->sc_npins - 1;
+
+	return (0);
+}
+
+static int
+a37x0_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+	struct a37x0_gpio_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (pin >= sc->sc_npins)
+		return (EINVAL);
+	snprintf(name, GPIOMAXNAME, "pin %d", pin);
+
+	return (0);
+}
+
+static int
+a37x0_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+	struct a37x0_gpio_softc *sc;
+
+	sc = device_get_softc(dev);
+	if (pin >= sc->sc_npins)
+		return (EINVAL);
+	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+
+	return (0);
+}
+
+static int
+a37x0_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+	struct a37x0_gpio_softc *sc;
+	uint32_t reg;
+
+	sc = device_get_softc(dev);
+	if (pin >= sc->sc_npins)
+		return (EINVAL);
+	reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin));
+	if ((reg & A37X0_GPIO_BIT(pin)) != 0)
+		*flags = GPIO_PIN_OUTPUT;
+	else
+		*flags = GPIO_PIN_INPUT;
+
+	return (0);
+}
+
+static int
+a37x0_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+	struct a37x0_gpio_softc *sc;
+	uint32_t reg;
+
+	sc = device_get_softc(dev);
+	if (pin >= sc->sc_npins)
+		return (EINVAL);
+
+	reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin));
+	if (flags & GPIO_PIN_OUTPUT)
+		reg |= A37X0_GPIO_BIT(pin);
+	else
+		reg &= ~A37X0_GPIO_BIT(pin);
+	A37X0_GPIO_WRITE(sc, A37X0_GPIO_OUT_EN(pin), reg);
+
+	return (0);
+}
+
+static int
+a37x0_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+	struct a37x0_gpio_softc *sc;
+	uint32_t reg;
+
+	sc = device_get_softc(dev);
+	if (pin >= sc->sc_npins)
+		return (EINVAL);
+
+	reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin));
+	if ((reg & A37X0_GPIO_BIT(pin)) != 0)
+		reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUTPUT(pin));
+	else
+		reg = A37X0_GPIO_READ(sc, A37X0_GPIO_INPUT(pin));
+	*val = ((reg & A37X0_GPIO_BIT(pin)) != 0) ? 1 : 0;
+
+	return (0);
+}
+
+static int
+a37x0_gpio_pin_set(device_t dev, uint32_t pin, unsigned int val)
+{
+	struct a37x0_gpio_softc *sc;
+	uint32_t reg;
+
+	sc = device_get_softc(dev);
+	if (pin >= sc->sc_npins)
+		return (EINVAL);
+
+	reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUTPUT(pin));
+	if (val != 0)
+		reg |= A37X0_GPIO_BIT(pin);
+	else
+		reg &= ~A37X0_GPIO_BIT(pin);
+	A37X0_GPIO_WRITE(sc, A37X0_GPIO_OUTPUT(pin), reg);
+
+	return (0);
+}
+
+static int
+a37x0_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+	struct a37x0_gpio_softc *sc;
+	uint32_t reg;
+
+	sc = device_get_softc(dev);
+	if (pin >= sc->sc_npins)
+		return (EINVAL);
+
+	reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUT_EN(pin));
+	if ((reg & A37X0_GPIO_BIT(pin)) == 0)
+		return (EINVAL);
+	reg = A37X0_GPIO_READ(sc, A37X0_GPIO_OUTPUT(pin));
+	reg ^= A37X0_GPIO_BIT(pin);
+	A37X0_GPIO_WRITE(sc, A37X0_GPIO_OUTPUT(pin), reg);
+
+	return (0);
+}
+
+static int
+a37x0_gpio_probe(device_t dev)
+{
+	const char *desc;
+	struct a37x0_gpio_softc *sc;
+
+	if (!OF_hasprop(ofw_bus_get_node(dev), "gpio-controller"))
+		return (ENXIO);
+
+	sc = device_get_softc(dev);
+	sc->sc_type = ofw_bus_search_compatible(
+	    device_get_parent(dev), compat_data)->ocd_data;
+	switch (sc->sc_type) {
+	case A37X0_NB_GPIO:
+		sc->sc_max_pins = 36;
+		desc = "Armada 37x0 North Bridge GPIO Controller";
+		break;
+	case A37X0_SB_GPIO:
+		sc->sc_max_pins = 30;
+		desc = "Armada 37x0 South Bridge GPIO Controller";
+		break;
+	default:
+		return (ENXIO);
+	}
+	device_set_desc(dev, desc);
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a37x0_gpio_attach(device_t dev)
+{
+	int err, ncells;
+	pcell_t *ranges;
+	struct a37x0_gpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	/* Read and verify the "gpio-ranges" property. */
+	ncells = OF_getencprop_alloc(ofw_bus_get_node(dev), "gpio-ranges",
+	    (void **)&ranges);
+	if (ncells == -1)
+		return (ENXIO);
+	if (ncells != sizeof(*ranges) * 4 || ranges[1] != 0 || ranges[2] != 0) {
+		OF_prop_free(ranges);
+		return (ENXIO);
+	}
+	sc->sc_npins = ranges[3];
+	OF_prop_free(ranges);
+
+	/* Check the number of pins in the DTS vs HW capabilities. */
+	if (sc->sc_npins > sc->sc_max_pins)
+		return (ENXIO);
+
+	err = bus_alloc_resources(dev, a37x0_gpio_res_spec, sc->sc_mem_res);
+	if (err != 0) {
+		device_printf(dev, "cannot allocate memory window\n");
+		return (ENXIO);
+	}
+	sc->sc_bst = rman_get_bustag(sc->sc_mem_res[A37X0_GPIO]);
+	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res[A37X0_GPIO]);
+
+	sc->sc_busdev = gpiobus_attach_bus(dev);
+	if (sc->sc_busdev == NULL)
+		return (ENXIO);
+
+	return (0);
+}
+
+static int
+a37x0_gpio_detach(device_t dev)
+{
+
+	return (EBUSY);
+}
+
+static device_method_t a37x0_gpio_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		a37x0_gpio_probe),
+	DEVMETHOD(device_attach,	a37x0_gpio_attach),
+	DEVMETHOD(device_detach,	a37x0_gpio_detach),
+
+	/* GPIO interface */
+	DEVMETHOD(gpio_get_bus,		a37x0_gpio_get_bus),
+	DEVMETHOD(gpio_pin_max,		a37x0_gpio_pin_max),
+	DEVMETHOD(gpio_pin_getname,	a37x0_gpio_pin_getname),
+	DEVMETHOD(gpio_pin_getcaps,	a37x0_gpio_pin_getcaps),
+	DEVMETHOD(gpio_pin_getflags,	a37x0_gpio_pin_getflags),
+	DEVMETHOD(gpio_pin_setflags,	a37x0_gpio_pin_setflags),
+	DEVMETHOD(gpio_pin_get,		a37x0_gpio_pin_get),
+	DEVMETHOD(gpio_pin_set,		a37x0_gpio_pin_set),
+	DEVMETHOD(gpio_pin_toggle,	a37x0_gpio_pin_toggle),
+
+	/* ofw_bus interface */
+	DEVMETHOD(ofw_bus_get_node,	a37x0_gpio_get_node),
+
+	DEVMETHOD_END
+};
+
+static devclass_t a37x0_gpio_devclass;
+static driver_t a37x0_gpio_driver = {
+	"gpio",
+	a37x0_gpio_methods,
+	sizeof(struct a37x0_gpio_softc),
+};
+
+EARLY_DRIVER_MODULE(a37x0_gpio, simple_mfd, a37x0_gpio_driver,
+    a37x0_gpio_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);

Modified: stable/12/sys/arm64/conf/GENERIC
==============================================================================
--- stable/12/sys/arm64/conf/GENERIC	Fri Aug 16 20:30:31 2019	(r351138)
+++ stable/12/sys/arm64/conf/GENERIC	Fri Aug 16 20:49:10 2019	(r351139)
@@ -200,6 +200,7 @@ device a10_codec
 device		a31_dmac
 
 # GPIO / PINCTRL
+device		a37x0_gpio	# Marvell Armada 37x0 GPIO controller
 device		aw_gpio		# Allwinner GPIO controller
 device		gpio
 device		gpioled

Modified: stable/12/sys/conf/files.arm64
==============================================================================
--- stable/12/sys/conf/files.arm64	Fri Aug 16 20:30:31 2019	(r351138)
+++ stable/12/sys/conf/files.arm64	Fri Aug 16 20:49:10 2019	(r351139)
@@ -95,6 +95,7 @@ arm/broadcom/bcm2835/bcm2835_vcio.c		optional soc_brcm
 arm/broadcom/bcm2835/bcm2835_wdog.c		optional soc_brcm_bcm2837 fdt
 arm/broadcom/bcm2835/bcm2836.c			optional soc_brcm_bcm2837 fdt
 arm/broadcom/bcm2835/bcm283x_dwc_fdt.c		optional dwcotg fdt soc_brcm_bcm2837
+arm/mv/a37x0_gpio.c				optional a37x0_gpio gpio fdt
 arm/mv/gpio.c					optional mv_gpio fdt
 arm/mv/mvebu_pinctrl.c				optional mvebu_pinctrl fdt
 arm/mv/mv_cp110_icu.c				optional mv_cp110_icu fdt

Modified: stable/12/sys/dev/sdhci/sdhci_xenon.c
==============================================================================
--- stable/12/sys/dev/sdhci/sdhci_xenon.c	Fri Aug 16 20:30:31 2019	(r351138)
+++ stable/12/sys/dev/sdhci/sdhci_xenon.c	Fri Aug 16 20:49:10 2019	(r351139)
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <machine/resource.h>
 
+#include <dev/extres/regulator/regulator.h>
 #include <dev/fdt/fdt_common.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
@@ -56,6 +57,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/mmc/mmcreg.h>
 
 #include <dev/sdhci/sdhci.h>
+#include <dev/sdhci/sdhci_fdt_gpio.h>
 #include <dev/sdhci/sdhci_xenon.h>
 
 #include "mmcbr_if.h"
@@ -84,10 +86,12 @@ struct sdhci_xenon_softc {
 	uint32_t	max_clk;	/* Max possible freq */
 	struct resource *irq_res;	/* IRQ resource */
 	void		*intrhand;	/* Interrupt handle */
+	struct sdhci_fdt_gpio *gpio;	/* GPIO pins for CD detection. */
 
 	struct sdhci_slot *slot;	/* SDHCI internal data */
 	struct resource	*mem_res;	/* Memory resource */
 
+	regulator_t	reg_vqmmc;	/* vqmmc-supply regulator */
 	uint8_t		znr;		/* PHY ZNR */
 	uint8_t		zpr;		/* PHY ZPR */
 	bool		no_18v;		/* No 1.8V support */
@@ -188,6 +192,14 @@ sdhci_xenon_get_ro(device_t bus, device_t dev)
 	return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted);
 }
 
+static bool
+sdhci_xenon_get_card_present(device_t dev, struct sdhci_slot *slot)
+{
+	struct sdhci_xenon_softc *sc = device_get_softc(dev);
+
+	return (sdhci_fdt_gpio_get_present(sc->gpio));
+}
+
 static int
 sdhci_xenon_phy_init(device_t brdev, struct mmc_ios *ios)
 {
@@ -337,6 +349,25 @@ sdhci_xenon_update_ios(device_t brdev, device_t reqdev
 	slot = device_get_ivars(reqdev);
  	ios = &slot->host.ios;
 
+	switch (ios->power_mode) {
+	case power_on:
+		break;
+	case power_off:
+		if (bootverbose)
+			device_printf(sc->dev, "Powering down sd/mmc\n");
+
+		if (sc->reg_vqmmc)
+			regulator_disable(sc->reg_vqmmc);
+		break;
+	case power_up:
+		if (bootverbose)
+			device_printf(sc->dev, "Powering up sd/mmc\n");
+
+		if (sc->reg_vqmmc)
+			regulator_enable(sc->reg_vqmmc);
+		break;
+	};
+
 	/* Update the PHY settings. */
 	if (ios->clock != 0)
 		sdhci_xenon_phy_set(brdev, ios);
@@ -352,6 +383,42 @@ sdhci_xenon_update_ios(device_t brdev, device_t reqdev
 }
 
 static int
+sdhci_xenon_switch_vccq(device_t brdev, device_t reqdev)
+{
+	struct sdhci_xenon_softc *sc;
+	struct sdhci_slot *slot;
+	int uvolt, err;
+
+	sc = device_get_softc(brdev);
+
+        if (sc->reg_vqmmc == NULL)
+		return EOPNOTSUPP;
+
+	slot = device_get_ivars(reqdev);
+	switch (slot->host.ios.vccq) {
+	case vccq_180:
+		uvolt = 1800000;
+		break;
+	case vccq_330:
+		uvolt = 3300000;
+		break;
+	default:
+		return EINVAL;
+	}
+
+	err = regulator_set_voltage(sc->reg_vqmmc, uvolt, uvolt);
+	if (err != 0) {
+		device_printf(sc->dev,
+		    "Cannot set vqmmc to %d<->%d\n",
+		    uvolt,
+		    uvolt);
+		return (err);
+	}
+
+	return (0);
+}
+
+static int
 sdhci_xenon_probe(device_t dev)
 {
 	struct sdhci_xenon_softc *sc = device_get_softc(dev);
@@ -389,6 +456,11 @@ sdhci_xenon_probe(device_t dev)
 	if ((OF_getencprop(sc->node, "marvell,xenon-phy-zpr", &cid,
 	    sizeof(cid))) > 0)
 		sc->zpr = cid & XENON_ZPR_MASK;
+	if (regulator_get_by_ofw_property(dev, 0, "vqmmc-supply",
+	    &sc->reg_vqmmc) == 0 && bootverbose) {
+		if (bootverbose)
+			device_printf(dev, "vqmmc-supply regulator found\n");
+	}
 
 	return (0);
 }
@@ -437,6 +509,12 @@ sdhci_xenon_attach(device_t dev)
 	slot->max_clk = sc->max_clk;
 	sc->slot = slot;
 
+	/*
+	 * Set up any gpio pin handling described in the FDT data. This cannot
+	 * fail; see comments in sdhci_fdt_gpio.h for details.
+	 */
+	sc->gpio = sdhci_fdt_gpio_setup(dev, slot);
+
 	if (sdhci_init_slot(dev, sc->slot, 0))
 		goto fail;
 
@@ -497,6 +575,9 @@ sdhci_xenon_detach(device_t dev)
 {
 	struct sdhci_xenon_softc *sc = device_get_softc(dev);
 
+	if (sc->gpio != NULL)
+		sdhci_fdt_gpio_teardown(sc->gpio);
+
 	bus_generic_detach(dev);
 	bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
 	bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res),
@@ -526,6 +607,7 @@ static device_method_t sdhci_xenon_methods[] = {
 	DEVMETHOD(mmcbr_get_ro,		sdhci_xenon_get_ro),
 	DEVMETHOD(mmcbr_acquire_host,	sdhci_generic_acquire_host),
 	DEVMETHOD(mmcbr_release_host,	sdhci_generic_release_host),
+	DEVMETHOD(mmcbr_switch_vccq,	sdhci_xenon_switch_vccq),
 
 	/* SDHCI registers accessors */
 	DEVMETHOD(sdhci_read_1,		sdhci_xenon_read_1),
@@ -536,6 +618,7 @@ static device_method_t sdhci_xenon_methods[] = {
 	DEVMETHOD(sdhci_write_2,	sdhci_xenon_write_2),
 	DEVMETHOD(sdhci_write_4,	sdhci_xenon_write_4),
 	DEVMETHOD(sdhci_write_multi_4,	sdhci_xenon_write_multi_4),
+	DEVMETHOD(sdhci_get_card_present,	sdhci_xenon_get_card_present),
 
 	DEVMETHOD_END
 };


More information about the svn-src-all mailing list