Date: Fri, 1 Aug 2014 06:20:25 +0000 (UTC) From: Ruslan Bukin <br@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269369 - in head/sys: arm/conf arm/samsung/exynos boot/fdt/dts/arm Message-ID: <201408010620.s716KPuM095202@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: br Date: Fri Aug 1 06:20:25 2014 New Revision: 269369 URL: http://svnweb.freebsd.org/changeset/base/269369 Log: Add support for Chromebook2 -- next-generation 8-core (4 in operation), 4GB ram (3.5 usable) ARM machine. Support covers device drivers for: - Serial Peripheral Interface (SPI) - Chrome Embedded Controller (EC) - SPI-based version - XHCI and USB 3.0 dual-role device PHY Also: - Add support for Exynos5420 in Pad module - Move power-related functions to separate driver -- Power Management Unit (PMU) - Enable XHCI for Chromebook1 Special thanks to grehan@ for hardware, and to hselasky@ for r269139. Added: head/sys/arm/conf/CHROMEBOOK-PEACH-PIT (contents, props changed) head/sys/arm/conf/CHROMEBOOK-PEACH-PIT.hints (contents, props changed) head/sys/arm/samsung/exynos/chrome_ec_spi.c (contents, props changed) head/sys/arm/samsung/exynos/exynos5_pmu.c (contents, props changed) head/sys/arm/samsung/exynos/exynos5_pmu.h (contents, props changed) head/sys/arm/samsung/exynos/exynos5_spi.c (contents, props changed) head/sys/arm/samsung/exynos/exynos5_usb_phy.c (contents, props changed) head/sys/arm/samsung/exynos/exynos5_xhci.c (contents, props changed) head/sys/boot/fdt/dts/arm/exynos5420-peach-pit.dts (contents, props changed) Modified: head/sys/arm/conf/CHROMEBOOK head/sys/arm/conf/EXYNOS5.common head/sys/arm/samsung/exynos/chrome_ec.c head/sys/arm/samsung/exynos/chrome_ec.h head/sys/arm/samsung/exynos/exynos5_combiner.c head/sys/arm/samsung/exynos/exynos5_ehci.c head/sys/arm/samsung/exynos/exynos5_pad.c head/sys/arm/samsung/exynos/files.exynos5 head/sys/boot/fdt/dts/arm/exynos5.dtsi head/sys/boot/fdt/dts/arm/exynos5250-chromebook-snow.dts head/sys/boot/fdt/dts/arm/exynos5250.dtsi head/sys/boot/fdt/dts/arm/exynos5420-arndale-octa.dts head/sys/boot/fdt/dts/arm/exynos5420.dtsi Modified: head/sys/arm/conf/CHROMEBOOK ============================================================================== --- head/sys/arm/conf/CHROMEBOOK Fri Aug 1 04:53:35 2014 (r269368) +++ head/sys/arm/conf/CHROMEBOOK Fri Aug 1 06:20:25 2014 (r269369) @@ -22,7 +22,7 @@ ident CHROMEBOOK hints "CHROMEBOOK.hints" -device chrome_ec # Chrome Embedded Controller +device chrome_ec_i2c # Chrome Embedded Controller device chrome_kb # Chrome Keyboard # Framebuffer Added: head/sys/arm/conf/CHROMEBOOK-PEACH-PIT ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/conf/CHROMEBOOK-PEACH-PIT Fri Aug 1 06:20:25 2014 (r269369) @@ -0,0 +1,47 @@ +# Kernel configuration for Chromebook2 (Exynos5 Octa machine). +# +# For more information on this file, please read the config(5) manual page, +# and/or the handbook section on Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +#NO_UNIVERSE + +include "EXYNOS5420" +ident CHROMEBOOK-PEACH-PIT + +hints "CHROMEBOOK-PEACH-PIT.hints" + +device chrome_ec_spi # Chrome Embedded Controller +device chrome_kb # Chrome Keyboard + +# Framebuffer +device vt +device kbdmux +device ukbd + +# Uncomment this for NFS root +#options NFS_ROOT # NFS usable as /, requires NFSCL +#options BOOTP_NFSROOT +#options BOOTP_COMPAT +#options BOOTP +#options BOOTP_NFSV3 +#options BOOTP_WIRED_TO=ue0 +#options ROOTDEVNAME=\"nfs:10.5.0.1:/tftpboot/root\" + +#FDT +options FDT +options FDT_DTB_STATIC +makeoptions FDT_DTS_FILE=exynos5420-peach-pit.dts Added: head/sys/arm/conf/CHROMEBOOK-PEACH-PIT.hints ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/conf/CHROMEBOOK-PEACH-PIT.hints Fri Aug 1 06:20:25 2014 (r269369) @@ -0,0 +1,5 @@ +# $FreeBSD$ + +# Chrome Embedded Controller +hint.chrome_ec.0.at="spibus0" +hint.chrome_ec.0.addr=0x00 Modified: head/sys/arm/conf/EXYNOS5.common ============================================================================== --- head/sys/arm/conf/EXYNOS5.common Fri Aug 1 04:53:35 2014 (r269368) +++ head/sys/arm/conf/EXYNOS5.common Fri Aug 1 06:20:25 2014 (r269369) @@ -101,6 +101,7 @@ options USB_DEBUG #device musb device ehci #device ohci +device xhci device umass device scbus # SCSI bus (required for SCSI) @@ -119,6 +120,10 @@ device uart device iic device iicbus +# SPI +device spibus +device exynos_spi + # Ethernet device ether device mii Modified: head/sys/arm/samsung/exynos/chrome_ec.c ============================================================================== --- head/sys/arm/samsung/exynos/chrome_ec.c Fri Aug 1 04:53:35 2014 (r269368) +++ head/sys/arm/samsung/exynos/chrome_ec.c Fri Aug 1 06:20:25 2014 (r269369) @@ -95,7 +95,7 @@ bus_claim(struct ec_softc *sc) /* Say we want the bus */ GPIO_PIN_SET(gpio_dev, sc->our_gpio, GPIO_PIN_LOW); - /* TODO(imax): insert a delay to allow EC to react. */ + /* TODO: insert a delay to allow EC to react. */ /* Check EC decision */ GPIO_PIN_GET(gpio_dev, sc->ec_gpio, &status); @@ -214,7 +214,7 @@ int ec_hello(void) data_in[2] = 0x20; data_in[3] = 0x10; - ec_command(EC_CMD_MKBP_STATE, data_in, 4, + ec_command(EC_CMD_HELLO, data_in, 4, data_out, 4); return (0); @@ -225,7 +225,7 @@ configure_i2c_arbitrator(struct ec_softc { phandle_t arbitrator; - /* TODO(imax): look for compatible entry instead of hard-coded path */ + /* TODO: look for compatible entry instead of hard-coded path */ arbitrator = OF_finddevice("/i2c-arbitrator"); if (arbitrator > 0 && OF_hasprop(arbitrator, "freebsd,our-gpio") && Modified: head/sys/arm/samsung/exynos/chrome_ec.h ============================================================================== --- head/sys/arm/samsung/exynos/chrome_ec.h Fri Aug 1 04:53:35 2014 (r269368) +++ head/sys/arm/samsung/exynos/chrome_ec.h Fri Aug 1 06:20:25 2014 (r269369) @@ -30,6 +30,8 @@ #define EC_CMD_GET_VERSION 0x02 #define EC_CMD_MKBP_STATE 0x60 #define EC_CMD_VERSION0 0xdc +#define EC_CMD_RESEND_RESPONSE 0xdb +#define EC_CMD_GET_COMMS_STATUS 0x09 int ec_command(uint8_t cmd, uint8_t *dout, uint8_t dout_len, uint8_t *dinp, uint8_t dinp_len); Added: head/sys/arm/samsung/exynos/chrome_ec_spi.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/samsung/exynos/chrome_ec_spi.c Fri Aug 1 06:20:25 2014 (r269369) @@ -0,0 +1,230 @@ +/*- + * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com> + * 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 AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPREC OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNEC FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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 BUSINEC 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. + */ + +/* + * Samsung Chromebook Embedded Controller (EC) + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/rman.h> +#include <sys/timeet.h> +#include <sys/timetc.h> +#include <sys/watchdog.h> +#include <sys/gpio.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <machine/bus.h> +#include <machine/fdt.h> +#include <machine/cpu.h> +#include <machine/intr.h> + +#include <dev/spibus/spi.h> +#include <dev/spibus/spibusvar.h> + +#include "spibus_if.h" +#include "gpio_if.h" + +#include <arm/samsung/exynos/chrome_ec.h> + +struct ec_softc { + device_t dev; + device_t dev_gpio; +}; + +struct ec_softc *ec_sc; + +#define EC_SPI_CS 200 + +static int +assert_cs(struct ec_softc *sc, int enable) +{ + /* Get the GPIO device */ + sc->dev_gpio = devclass_get_device(devclass_find("gpio"), 0); + if (sc->dev_gpio == NULL) { + device_printf(sc->dev, "Error: failed to get the GPIO dev\n"); + return (1); + } + + GPIO_PIN_SETFLAGS(sc->dev_gpio, EC_SPI_CS, GPIO_PIN_OUTPUT); + + if (enable) { + GPIO_PIN_SET(sc->dev_gpio, EC_SPI_CS, GPIO_PIN_LOW); + } else { + GPIO_PIN_SET(sc->dev_gpio, EC_SPI_CS, GPIO_PIN_HIGH); + } + + return (0); +} + +static int +ec_probe(device_t dev) +{ + + device_set_desc(dev, "Chromebook Embedded Controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +fill_checksum(uint8_t *data_out, int len) +{ + int res; + int i; + + res = 0; + for (i = 0; i < len; i++) { + res += data_out[i]; + } + + data_out[len] = (res & 0xff); + + return (0); +} + +int +ec_command(uint8_t cmd, uint8_t *dout, uint8_t dout_len, + uint8_t *dinp, uint8_t dinp_len) +{ + struct spi_command spi_cmd; + struct ec_softc *sc; + uint8_t *msg_dout; + uint8_t *msg_dinp; + int ret; + int i; + + memset(&spi_cmd, 0, sizeof(spi_cmd)); + + msg_dout = malloc(dout_len + 4, M_DEVBUF, M_NOWAIT | M_ZERO); + msg_dinp = malloc(dinp_len + 4, M_DEVBUF, M_NOWAIT | M_ZERO); + + spi_cmd.tx_cmd = msg_dout; + spi_cmd.rx_cmd = msg_dinp; + + if (ec_sc == NULL) + return (-1); + + sc = ec_sc; + + msg_dout[0] = EC_CMD_VERSION0; + msg_dout[1] = cmd; + msg_dout[2] = dout_len; + + for (i = 0; i < dout_len; i++) { + msg_dout[i + 3] = dout[i]; + }; + + fill_checksum(msg_dout, dout_len + 3); + + assert_cs(sc, 1); + spi_cmd.rx_cmd_sz = spi_cmd.tx_cmd_sz = dout_len + 4; + ret = SPIBUS_TRANSFER(device_get_parent(sc->dev), sc->dev, &spi_cmd); + + /* Wait 0xec */ + for (i = 0; i < 1000; i++) { + DELAY(10); + msg_dout[0] = 0xff; + spi_cmd.rx_cmd_sz = spi_cmd.tx_cmd_sz = 1; + SPIBUS_TRANSFER(device_get_parent(sc->dev), sc->dev, &spi_cmd); + if (msg_dinp[0] == 0xec) + break; + } + + /* Get the rest */ + for (i = 0; i < (dout_len + 4); i++) + msg_dout[i] = 0xff; + spi_cmd.rx_cmd_sz = spi_cmd.tx_cmd_sz = dout_len + 4 - 1; + ret = SPIBUS_TRANSFER(device_get_parent(sc->dev), sc->dev, &spi_cmd); + assert_cs(sc, 0); + + if (ret != 0) { + device_printf(sc->dev, "spibus_transfer returned %d\n", ret); + free(msg_dout, M_DEVBUF); + free(msg_dinp, M_DEVBUF); + return (-1); + } + + for (i = 0; i < dinp_len; i++) { + dinp[i] = msg_dinp[i + 2]; + }; + + free(msg_dout, M_DEVBUF); + free(msg_dinp, M_DEVBUF); + + return (0); +} + +static int +ec_attach(device_t dev) +{ + struct ec_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + + ec_sc = sc; + + return (0); +} + +static int +ec_detach(device_t dev) +{ + struct ec_softc *sc; + + sc = device_get_softc(dev); + + return (0); +} + +static device_method_t ec_methods[] = { + DEVMETHOD(device_probe, ec_probe), + DEVMETHOD(device_attach, ec_attach), + DEVMETHOD(device_detach, ec_detach), + { 0, 0 } +}; + +static driver_t ec_driver = { + "chrome_ec", + ec_methods, + sizeof(struct ec_softc), +}; + +static devclass_t ec_devclass; + +DRIVER_MODULE(chrome_ec, spibus, ec_driver, ec_devclass, 0, 0); +MODULE_VERSION(chrome_ec, 1); +MODULE_DEPEND(chrome_ec, spibus, 1, 1, 1); Modified: head/sys/arm/samsung/exynos/exynos5_combiner.c ============================================================================== --- head/sys/arm/samsung/exynos/exynos5_combiner.c Fri Aug 1 04:53:35 2014 (r269368) +++ head/sys/arm/samsung/exynos/exynos5_combiner.c Fri Aug 1 06:20:25 2014 (r269369) @@ -353,6 +353,9 @@ static int combiner_probe(device_t dev) { + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + if (!ofw_bus_is_compatible(dev, "exynos,combiner")) return (ENXIO); Modified: head/sys/arm/samsung/exynos/exynos5_ehci.c ============================================================================== --- head/sys/arm/samsung/exynos/exynos5_ehci.c Fri Aug 1 04:53:35 2014 (r269368) +++ head/sys/arm/samsung/exynos/exynos5_ehci.c Fri Aug 1 06:20:25 2014 (r269369) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2013 Ruslan Bukin <br@bsdpad.com> + * Copyright (c) 2013-2014 Ruslan Bukin <br@bsdpad.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,6 +55,9 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <machine/resource.h> +#include <arm/samsung/exynos/exynos5_common.h> +#include <arm/samsung/exynos/exynos5_pmu.h> + #include "gpio_if.h" #include "opt_platform.h" @@ -64,11 +67,6 @@ __FBSDID("$FreeBSD$"); #define GPIO_INPUT 0 #define PIN_USB 161 -/* PWR control */ -#define EXYNOS5_PWR_USBHOST_PHY 0x708 -#define PHY_POWER_ON 1 -#define PHY_POWER_OFF 0 - /* SYSREG */ #define EXYNOS5_SYSREG_USB2_PHY 0x0 #define USB2_MODE_HOST 0x1 @@ -91,12 +89,10 @@ static int exynos_ehci_probe(device_t de struct exynos_ehci_softc { device_t dev; ehci_softc_t base; - struct resource *res[5]; + struct resource *res[4]; bus_space_tag_t host_bst; - bus_space_tag_t pwr_bst; bus_space_tag_t sysreg_bst; bus_space_handle_t host_bsh; - bus_space_handle_t pwr_bsh; bus_space_handle_t sysreg_bsh; }; @@ -105,7 +101,6 @@ static struct resource_spec exynos_ehci_ { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_MEMORY, 1, RF_ACTIVE }, { SYS_RES_MEMORY, 2, RF_ACTIVE }, - { SYS_RES_MEMORY, 3, RF_ACTIVE }, { SYS_RES_IRQ, 0, RF_ACTIVE }, { -1, 0 } }; @@ -185,10 +180,8 @@ reset_hsic_hub(struct exynos_ehci_softc device_t gpio_dev; pcell_t pin; - /* TODO(imax): check that hub is compatible with "smsc,usb3503" */ + /* TODO: check that hub is compatible with "smsc,usb3503" */ if (!OF_hasprop(hub, "freebsd,reset-gpio")) { - device_printf(esc->dev, - "cannot detect reset GPIO pin for HSIC hub\n"); return (1); } @@ -201,7 +194,7 @@ reset_hsic_hub(struct exynos_ehci_softc /* Get the GPIO device, we need this to give power to USB */ gpio_dev = devclass_get_device(devclass_find("gpio"), 0); if (gpio_dev == NULL) { - device_printf(esc->dev, "cant find gpio_dev\n"); + device_printf(esc->dev, "Cant find gpio device\n"); return (1); } @@ -225,8 +218,7 @@ phy_init(struct exynos_ehci_softc *esc) EXYNOS5_SYSREG_USB2_PHY, USB2_MODE_HOST); /* Power ON phy */ - bus_space_write_4(esc->pwr_bst, esc->pwr_bsh, - EXYNOS5_PWR_USBHOST_PHY, PHY_POWER_ON); + usb2_phy_power_on(); reg = bus_space_read_4(esc->host_bst, esc->host_bsh, 0x0); reg &= ~(HOST_CTRL_CLK_MASK | @@ -284,13 +276,9 @@ exynos_ehci_attach(device_t dev) esc->host_bst = rman_get_bustag(esc->res[1]); esc->host_bsh = rman_get_bushandle(esc->res[1]); - /* PWR registers */ - esc->pwr_bst = rman_get_bustag(esc->res[2]); - esc->pwr_bsh = rman_get_bushandle(esc->res[2]); - /* SYSREG */ - esc->sysreg_bst = rman_get_bustag(esc->res[3]); - esc->sysreg_bsh = rman_get_bushandle(esc->res[3]); + esc->sysreg_bst = rman_get_bustag(esc->res[2]); + esc->sysreg_bsh = rman_get_bushandle(esc->res[2]); /* get all DMA memory */ if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev), @@ -309,7 +297,7 @@ exynos_ehci_attach(device_t dev) phy_init(esc); /* Setup interrupt handler */ - err = bus_setup_intr(dev, esc->res[4], INTR_TYPE_BIO | INTR_MPSAFE, + err = bus_setup_intr(dev, esc->res[3], INTR_TYPE_BIO | INTR_MPSAFE, NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); if (err) { @@ -322,7 +310,7 @@ exynos_ehci_attach(device_t dev) sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); if (!sc->sc_bus.bdev) { device_printf(dev, "Could not add USB device\n"); - err = bus_teardown_intr(dev, esc->res[4], + err = bus_teardown_intr(dev, esc->res[3], sc->sc_intr_hdl); if (err) device_printf(dev, "Could not tear down irq," @@ -343,7 +331,7 @@ exynos_ehci_attach(device_t dev) device_delete_child(dev, sc->sc_bus.bdev); sc->sc_bus.bdev = NULL; - err = bus_teardown_intr(dev, esc->res[4], + err = bus_teardown_intr(dev, esc->res[3], sc->sc_intr_hdl); if (err) device_printf(dev, "Could not tear down irq," @@ -382,8 +370,8 @@ exynos_ehci_detach(device_t dev) bus_space_write_4(sc->sc_io_tag, sc->sc_io_hdl, EHCI_USBINTR, 0); - if (esc->res[4] && sc->sc_intr_hdl) { - err = bus_teardown_intr(dev, esc->res[4], + if (esc->res[3] && sc->sc_intr_hdl) { + err = bus_teardown_intr(dev, esc->res[3], sc->sc_intr_hdl); if (err) { device_printf(dev, "Could not tear down irq," Modified: head/sys/arm/samsung/exynos/exynos5_pad.c ============================================================================== --- head/sys/arm/samsung/exynos/exynos5_pad.c Fri Aug 1 04:53:35 2014 (r269368) +++ head/sys/arm/samsung/exynos/exynos5_pad.c Fri Aug 1 06:20:25 2014 (r269369) @@ -65,10 +65,13 @@ __FBSDID("$FreeBSD$"); #define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) -#define NPORTS 4 -#define NGRP 40 -#define NGPIO 253 -#define NINTS 16 +#define MAX_PORTS 5 +#define MAX_NGPIO 253 + +#define N_EXT_INTS 16 + +#define EXYNOS5250 1 +#define EXYNOS5420 2 #define PIN_IN 0 #define PIN_OUT 1 @@ -90,20 +93,36 @@ static int pad_pin_set(device_t, uint32_ static int pad_pin_get(device_t, uint32_t, unsigned int *); static int pad_pin_toggle(device_t, uint32_t pin); +struct gpio_bank { + char *name; + uint32_t port; + uint32_t con; + uint32_t ngpio; + uint32_t ext_con; + uint32_t ext_flt_con; + uint32_t mask; + uint32_t pend; +}; + struct pad_softc { - struct resource *res[NPORTS+4]; - bus_space_tag_t bst[NPORTS]; - bus_space_handle_t bsh[NPORTS]; + struct resource *res[MAX_PORTS * 2]; + bus_space_tag_t bst[MAX_PORTS]; + bus_space_handle_t bsh[MAX_PORTS]; struct mtx sc_mtx; int gpio_npins; - struct gpio_pin gpio_pins[NGPIO]; - void *gpio_ih[NPORTS+4]; + struct gpio_pin gpio_pins[MAX_NGPIO]; + void *gpio_ih[MAX_PORTS]; device_t dev; + int model; + struct resource_spec *pad_spec; + struct gpio_bank *gpio_map; + struct interrupt_entry *interrupt_table; + int nports; }; struct pad_softc *gpio_sc; -static struct resource_spec pad_spec[] = { +static struct resource_spec pad_spec_5250[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, { SYS_RES_MEMORY, 1, RF_ACTIVE }, { SYS_RES_MEMORY, 2, RF_ACTIVE }, @@ -115,20 +134,40 @@ static struct resource_spec pad_spec[] = { -1, 0 } }; +static struct resource_spec pad_spec_5420[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_MEMORY, 1, RF_ACTIVE }, + { SYS_RES_MEMORY, 2, RF_ACTIVE }, + { SYS_RES_MEMORY, 3, RF_ACTIVE }, + { SYS_RES_MEMORY, 4, RF_ACTIVE }, + { SYS_RES_IRQ, 0, RF_ACTIVE }, + { SYS_RES_IRQ, 1, RF_ACTIVE }, + { SYS_RES_IRQ, 2, RF_ACTIVE }, + { SYS_RES_IRQ, 3, RF_ACTIVE }, + { SYS_RES_IRQ, 4, RF_ACTIVE }, + { -1, 0 } +}; + +static struct ofw_compat_data compat_data[] = { + {"samsung,exynos5420-padctrl", EXYNOS5420}, + {"samsung,exynos5250-padctrl", EXYNOS5250}, + {NULL, 0} +}; + struct pad_intr { uint32_t enabled; void (*ih) (void *); void *ih_user; }; -static struct pad_intr intr_map[NGPIO]; +static struct pad_intr intr_map[MAX_NGPIO]; struct interrupt_entry { int gpio_number; char *combiner_source_name; }; -struct interrupt_entry interrupt_table[NINTS] = { +struct interrupt_entry interrupt_table_5250[N_EXT_INTS] = { { 147, "EINT[15]" }, { 146, "EINT[14]" }, { 145, "EINT[13]" }, @@ -147,84 +186,144 @@ struct interrupt_entry interrupt_table[N { 132, "EINT[0]" }, }; -struct gpio_bank { - char *name; - uint32_t port; - uint32_t con; - uint32_t ngpio; - uint32_t ext_int_grp; - uint32_t ext_con; - uint32_t ext_flt_con; - uint32_t mask; - uint32_t pend; +struct interrupt_entry interrupt_table_5420[N_EXT_INTS] = { + { 23, "EINT[15]" }, + { 22, "EINT[14]" }, + { 21, "EINT[13]" }, + { 20, "EINT[12]" }, + { 19, "EINT[11]" }, + { 18, "EINT[10]" }, + { 17, "EINT[9]" }, + { 16, "EINT[8]" }, + { 15, "EINT[7]" }, + { 14, "EINT[6]" }, + { 13, "EINT[5]" }, + { 12, "EINT[4]" }, + { 11, "EINT[3]" }, + { 10, "EINT[2]" }, + { 9, "EINT[1]" }, + { 8, "EINT[0]" }, }; /* * 253 multi-functional input/output ports */ -static struct gpio_bank gpio_map[] = { +static struct gpio_bank gpio_map_5250[] = { /* first 132 gpio */ - { "gpa0", 0, 0x000, 8, 1, 0x700, 0x800, 0x900, 0xA00 }, - { "gpa1", 0, 0x020, 6, 2, 0x704, 0x808, 0x904, 0xA04 }, - { "gpa2", 0, 0x040, 8, 3, 0x708, 0x810, 0x908, 0xA08 }, - { "gpb0", 0, 0x060, 5, 4, 0x70C, 0x818, 0x90C, 0xA0C }, - { "gpb1", 0, 0x080, 5, 5, 0x710, 0x820, 0x910, 0xA10 }, - { "gpb2", 0, 0x0A0, 4, 6, 0x714, 0x828, 0x914, 0xA14 }, - { "gpb3", 0, 0x0C0, 4, 7, 0x718, 0x830, 0x918, 0xA18 }, - { "gpc0", 0, 0x0E0, 7, 8, 0x71C, 0x838, 0x91C, 0xA1C }, - { "gpc1", 0, 0x100, 4, 9, 0x720, 0x840, 0x920, 0xA20 }, - { "gpc2", 0, 0x120, 7, 10, 0x724, 0x848, 0x924, 0xA24 }, - { "gpc3", 0, 0x140, 7, 11, 0x728, 0x850, 0x928, 0xA28 }, - { "gpd0", 0, 0x160, 4, 12, 0x72C, 0x858, 0x92C, 0xA2C }, - { "gpd1", 0, 0x180, 8, 13, 0x730, 0x860, 0x930, 0xA30 }, - { "gpy0", 0, 0x1A0, 6, 0, 0, 0, 0, 0 }, - { "gpy1", 0, 0x1C0, 4, 0, 0, 0, 0, 0 }, - { "gpy2", 0, 0x1E0, 6, 0, 0, 0, 0, 0 }, - { "gpy3", 0, 0x200, 8, 0, 0, 0, 0, 0 }, - { "gpy4", 0, 0x220, 8, 0, 0, 0, 0, 0 }, - { "gpy5", 0, 0x240, 8, 0, 0, 0, 0, 0 }, - { "gpy6", 0, 0x260, 8, 0, 0, 0, 0, 0 }, - { "gpc4", 0, 0x2E0, 7, 30, 0x734, 0x868, 0x934, 0xA34 }, + { "gpa0", 0, 0x000, 8, 0x700, 0x800, 0x900, 0xA00 }, + { "gpa1", 0, 0x020, 6, 0x704, 0x808, 0x904, 0xA04 }, + { "gpa2", 0, 0x040, 8, 0x708, 0x810, 0x908, 0xA08 }, + { "gpb0", 0, 0x060, 5, 0x70C, 0x818, 0x90C, 0xA0C }, + { "gpb1", 0, 0x080, 5, 0x710, 0x820, 0x910, 0xA10 }, + { "gpb2", 0, 0x0A0, 4, 0x714, 0x828, 0x914, 0xA14 }, + { "gpb3", 0, 0x0C0, 4, 0x718, 0x830, 0x918, 0xA18 }, + { "gpc0", 0, 0x0E0, 7, 0x71C, 0x838, 0x91C, 0xA1C }, + { "gpc1", 0, 0x100, 4, 0x720, 0x840, 0x920, 0xA20 }, + { "gpc2", 0, 0x120, 7, 0x724, 0x848, 0x924, 0xA24 }, + { "gpc3", 0, 0x140, 7, 0x728, 0x850, 0x928, 0xA28 }, + { "gpd0", 0, 0x160, 4, 0x72C, 0x858, 0x92C, 0xA2C }, + { "gpd1", 0, 0x180, 8, 0x730, 0x860, 0x930, 0xA30 }, + { "gpy0", 0, 0x1A0, 6, 0, 0, 0, 0 }, + { "gpy1", 0, 0x1C0, 4, 0, 0, 0, 0 }, + { "gpy2", 0, 0x1E0, 6, 0, 0, 0, 0 }, + { "gpy3", 0, 0x200, 8, 0, 0, 0, 0 }, + { "gpy4", 0, 0x220, 8, 0, 0, 0, 0 }, + { "gpy5", 0, 0x240, 8, 0, 0, 0, 0 }, + { "gpy6", 0, 0x260, 8, 0, 0, 0, 0 }, + { "gpc4", 0, 0x2E0, 7, 0x734, 0x868, 0x934, 0xA34 }, /* next 32 */ - { "gpx0", 0, 0xC00, 8, 40, 0xE00, 0xE80, 0xF00, 0xF40 }, - { "gpx1", 0, 0xC20, 8, 41, 0xE04, 0xE88, 0xF04, 0xF44 }, - { "gpx2", 0, 0xC40, 8, 42, 0xE08, 0xE90, 0xF08, 0xF48 }, - { "gpx3", 0, 0xC60, 8, 43, 0xE0C, 0xE98, 0xF0C, 0xF4C }, - - { "gpe0", 1, 0x000, 8, 14, 0x700, 0x800, 0x900, 0xA00 }, - { "gpe1", 1, 0x020, 2, 15, 0x704, 0x808, 0x904, 0xA04 }, - { "gpf0", 1, 0x040, 4, 16, 0x708, 0x810, 0x908, 0xA08 }, - { "gpf1", 1, 0x060, 4, 17, 0x70C, 0x818, 0x90C, 0xA0C }, - { "gpg0", 1, 0x080, 8, 18, 0x710, 0x820, 0x910, 0xA10 }, - { "gpg1", 1, 0x0A0, 8, 19, 0x714, 0x828, 0x914, 0xA14 }, - { "gpg2", 1, 0x0C0, 2, 20, 0x718, 0x830, 0x918, 0xA18 }, - { "gph0", 1, 0x0E0, 4, 21, 0x71C, 0x838, 0x91C, 0xA1C }, - { "gph1", 1, 0x100, 8, 22, 0x720, 0x840, 0x920, 0xA20 }, - - { "gpv0", 2, 0x000, 8, 60, 0x700, 0x800, 0x900, 0xA00 }, - { "gpv1", 2, 0x020, 8, 61, 0x704, 0x808, 0x904, 0xA04 }, - { "gpv2", 2, 0x060, 8, 62, 0x708, 0x810, 0x908, 0xA08 }, - { "gpv3", 2, 0x080, 8, 63, 0x70C, 0x818, 0x90C, 0xA0C }, - { "gpv4", 2, 0x0C0, 2, 64, 0x710, 0x820, 0x910, 0xA10 }, + { "gpx0", 0, 0xC00, 8, 0xE00, 0xE80, 0xF00, 0xF40 }, + { "gpx1", 0, 0xC20, 8, 0xE04, 0xE88, 0xF04, 0xF44 }, + { "gpx2", 0, 0xC40, 8, 0xE08, 0xE90, 0xF08, 0xF48 }, + { "gpx3", 0, 0xC60, 8, 0xE0C, 0xE98, 0xF0C, 0xF4C }, + + { "gpe0", 1, 0x000, 8, 0x700, 0x800, 0x900, 0xA00 }, + { "gpe1", 1, 0x020, 2, 0x704, 0x808, 0x904, 0xA04 }, + { "gpf0", 1, 0x040, 4, 0x708, 0x810, 0x908, 0xA08 }, + { "gpf1", 1, 0x060, 4, 0x70C, 0x818, 0x90C, 0xA0C }, + { "gpg0", 1, 0x080, 8, 0x710, 0x820, 0x910, 0xA10 }, + { "gpg1", 1, 0x0A0, 8, 0x714, 0x828, 0x914, 0xA14 }, + { "gpg2", 1, 0x0C0, 2, 0x718, 0x830, 0x918, 0xA18 }, + { "gph0", 1, 0x0E0, 4, 0x71C, 0x838, 0x91C, 0xA1C }, + { "gph1", 1, 0x100, 8, 0x720, 0x840, 0x920, 0xA20 }, + + { "gpv0", 2, 0x000, 8, 0x700, 0x800, 0x900, 0xA00 }, + { "gpv1", 2, 0x020, 8, 0x704, 0x808, 0x904, 0xA04 }, + { "gpv2", 2, 0x060, 8, 0x708, 0x810, 0x908, 0xA08 }, + { "gpv3", 2, 0x080, 8, 0x70C, 0x818, 0x90C, 0xA0C }, + { "gpv4", 2, 0x0C0, 2, 0x710, 0x820, 0x910, 0xA10 }, + + { "gpz", 3, 0x000, 7, 0x700, 0x800, 0x900, 0xA00 }, + + { NULL, -1, -1, -1, -1, -1, -1, -1 }, +}; + +static struct gpio_bank gpio_map_5420[] = { + /* First 40 */ + { "gpy7", 0, 0x000, 8, 0x700, 0x800, 0x900, 0xA00 }, + { "gpx0", 0, 0xC00, 8, 0x704, 0xE80, 0xF00, 0xF40 }, + { "gpx1", 0, 0xC20, 8, 0x708, 0xE88, 0xF04, 0xF44 }, + { "gpx2", 0, 0xC40, 8, 0x70C, 0xE90, 0xF08, 0xF48 }, + { "gpx3", 0, 0xC60, 8, 0x710, 0xE98, 0xF0C, 0xF4C }, + + /* Next 85 */ + { "gpc0", 1, 0x000, 8, 0x700, 0x800, 0x900, 0xA00 }, + { "gpc1", 1, 0x020, 8, 0x704, 0x808, 0x904, 0xA04 }, + { "gpc2", 1, 0x040, 7, 0x708, 0x810, 0x908, 0xA08 }, + { "gpc3", 1, 0x060, 4, 0x70C, 0x818, 0x90C, 0xA0C }, + { "gpc4", 1, 0x080, 2, 0x710, 0x820, 0x910, 0xA10 }, + { "gpd1", 1, 0x0A0, 8, 0x714, 0x828, 0x914, 0xA14 }, + { "gpy0", 1, 0x0C0, 6, 0x718, 0x830, 0x918, 0xA18 }, + { "gpy1", 1, 0x0E0, 4, 0x71C, 0x838, 0x91C, 0xA1C }, + { "gpy2", 1, 0x100, 6, 0x720, 0x840, 0x920, 0xA20 }, + { "gpy3", 1, 0x120, 8, 0x724, 0x848, 0x924, 0xA24 }, + { "gpy4", 1, 0x140, 8, 0x728, 0x850, 0x928, 0xA28 }, + { "gpy5", 1, 0x160, 8, 0x72C, 0x858, 0x92C, 0xA2C }, + { "gpy6", 1, 0x180, 8, 0x730, 0x860, 0x930, 0xA30 }, + + /* Next 46 */ + { "gpe0", 2, 0x000, 8, 0x700, 0x800, 0x900, 0xA00 }, + { "gpe1", 2, 0x020, 2, 0x704, 0x808, 0x904, 0xA04 }, + { "gpf0", 2, 0x040, 6, 0x708, 0x810, 0x908, 0xA08 }, + { "gpf1", 2, 0x060, 8, 0x70C, 0x818, 0x90C, 0xA0C }, + { "gpg0", 2, 0x080, 8, 0x710, 0x820, 0x910, 0xA10 }, + { "gpg1", 2, 0x0A0, 8, 0x714, 0x828, 0x914, 0xA14 }, + { "gpg2", 2, 0x0C0, 2, 0x718, 0x830, 0x918, 0xA18 }, + { "gpj4", 2, 0x0E0, 4, 0x71C, 0x838, 0x91C, 0xA1C }, + + /* Next 54 */ + { "gpa0", 3, 0x000, 8, 0x700, 0x800, 0x900, 0xA00 }, + { "gpa1", 3, 0x020, 6, 0x704, 0x808, 0x904, 0xA04 }, + { "gpa2", 3, 0x040, 8, 0x708, 0x810, 0x908, 0xA08 }, + { "gpb0", 3, 0x060, 5, 0x70C, 0x818, 0x90C, 0xA0C }, + { "gpb1", 3, 0x080, 5, 0x710, 0x820, 0x910, 0xA10 }, + { "gpb2", 3, 0x0A0, 4, 0x714, 0x828, 0x914, 0xA14 }, + { "gpb3", 3, 0x0C0, 8, 0x718, 0x830, 0x918, 0xA18 }, + { "gpb4", 3, 0x0E0, 2, 0x71C, 0x838, 0x91C, 0xA1C }, + { "gph0", 3, 0x100, 8, 0x720, 0x840, 0x920, 0xA20 }, + + /* Last 7 */ + { "gpz", 4, 0x000, 7, 0x700, 0x800, 0x900, 0xA00 }, - { "gpz", 3, 0x000, 7, 50, 0x700, 0x800, 0x900, 0xA00 }, + { NULL, -1, -1, -1, -1, -1, -1, -1 }, }; static int -get_bank(int gpio_number, struct gpio_bank *bank, int *pin_shift) +get_bank(struct pad_softc *sc, int gpio_number, + struct gpio_bank *bank, int *pin_shift) { int ngpio; int i; int n; n = 0; - for (i = 0; i < NGRP; i++) { - ngpio = gpio_map[i].ngpio; + for (i = 0; sc->gpio_map[i].ngpio != -1; i++) { + ngpio = sc->gpio_map[i].ngpio; if ((n + ngpio) > gpio_number) { - *bank = gpio_map[i]; + *bank = sc->gpio_map[i]; *pin_shift = (gpio_number - n); return (0); }; @@ -260,16 +359,16 @@ ext_intr(void *arg) sc = arg; n = 0; - for (i = 0; i < NGRP; i++) { + for (i = 0; sc->gpio_map[i].ngpio != -1; i++) { found = 0; - ngpio = gpio_map[i].ngpio; + ngpio = sc->gpio_map[i].ngpio; - if (gpio_map[i].pend == 0) { + if (sc->gpio_map[i].pend == 0) { n += ngpio; continue; } - reg = READ4(sc, gpio_map[i].port, gpio_map[i].pend); + reg = READ4(sc, sc->gpio_map[i].port, sc->gpio_map[i].pend); for (j = 0; j < ngpio; j++) { if (reg & (1 << j)) { @@ -286,7 +385,7 @@ ext_intr(void *arg) if (found) { /* ACK */ - WRITE4(sc, gpio_map[i].port, gpio_map[i].pend, reg); + WRITE4(sc, sc->gpio_map[i].port, sc->gpio_map[i].pend, reg); } n += ngpio; @@ -311,13 +410,13 @@ pad_setup_intr(int gpio_number, void (*i return (-1); } - if (get_bank(gpio_number, &bank, &pin_shift) != 0) + if (get_bank(sc, gpio_number, &bank, &pin_shift) != 0) return (-1); entry = NULL; - for (i = 0; i < NINTS; i++) - if (interrupt_table[i].gpio_number == gpio_number) - entry = &interrupt_table[i]; + for (i = 0; i < N_EXT_INTS; i++) + if (sc->interrupt_table[i].gpio_number == gpio_number) + entry = &(sc->interrupt_table[i]); if (entry == NULL) { device_printf(sc->dev, "Cant find interrupt source for %d\n", @@ -374,11 +473,12 @@ pad_probe(device_t dev) if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (!ofw_bus_is_compatible(dev, "exynos,pad")) - return (ENXIO); + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { + device_set_desc(dev, "Exynos Pad Control"); + return (BUS_PROBE_DEFAULT); + } - device_set_desc(dev, "Exynos Pad Control"); - return (BUS_PROBE_DEFAULT); + return (ENXIO); } static int @@ -391,27 +491,47 @@ pad_attach(device_t dev) int i; sc = device_get_softc(dev); + mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); - if (bus_alloc_resources(dev, pad_spec, sc->res)) { + sc->model = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + switch (sc->model) { + case EXYNOS5250: + sc->pad_spec = pad_spec_5250; + sc->gpio_map = gpio_map_5250; + sc->interrupt_table = interrupt_table_5250; + sc->gpio_npins = 253; + sc->nports = 4; + break; + case EXYNOS5420: + sc->pad_spec = pad_spec_5420; + sc->gpio_map = gpio_map_5420; + sc->interrupt_table = interrupt_table_5420; + sc->gpio_npins = 232; + sc->nports = 5; + break; + default: + return (-1); + }; + + if (bus_alloc_resources(dev, sc->pad_spec, sc->res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } /* Memory interface */ - for (i = 0; i < NPORTS; i++) { + for (i = 0; i < sc->nports; i++) { sc->bst[i] = rman_get_bustag(sc->res[i]); sc->bsh[i] = rman_get_bushandle(sc->res[i]); }; sc->dev = dev; - sc->gpio_npins = NGPIO; gpio_sc = sc; - for (i = 0; i < NPORTS; i++) { - if ((bus_setup_intr(dev, sc->res[NPORTS + i], + for (i = 0; i < sc->nports; i++) { + if ((bus_setup_intr(dev, sc->res[sc->nports + i], INTR_TYPE_BIO | INTR_MPSAFE, port_intr, NULL, sc, &sc->gpio_ih[i]))) { device_printf(dev, @@ -424,7 +544,7 @@ pad_attach(device_t dev) sc->gpio_pins[i].gp_pin = i; sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; - if (get_bank(i, &bank, &pin_shift) != 0) + if (get_bank(sc, i, &bank, &pin_shift) != 0) continue; pin_shift *= 4; @@ -450,8 +570,11 @@ pad_attach(device_t dev) static int pad_pin_max(device_t dev, int *maxpin) { + struct pad_softc *sc; + + sc = device_get_softc(dev); - *maxpin = NGPIO - 1; + *maxpin = sc->gpio_npins - 1; return (0); } @@ -538,7 +661,7 @@ pad_pin_get(device_t dev, uint32_t pin, if (i >= sc->gpio_npins) return (EINVAL); - if (get_bank(pin, &bank, &pin_shift) != 0) + if (get_bank(sc, pin, &bank, &pin_shift) != 0) return (EINVAL); GPIO_LOCK(sc); @@ -569,7 +692,7 @@ pad_pin_toggle(device_t dev, uint32_t pi if (i >= sc->gpio_npins) return (EINVAL); - if (get_bank(pin, &bank, &pin_shift) != 0) + if (get_bank(sc, pin, &bank, &pin_shift) != 0) return (EINVAL); GPIO_LOCK(sc); @@ -601,7 +724,7 @@ pad_pin_configure(struct pad_softc *sc, if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); - if (get_bank(pin->gp_pin, &bank, &pin_shift) != 0) + if (get_bank(sc, pin->gp_pin, &bank, &pin_shift) != 0) return; pin_shift *= 4; @@ -675,7 +798,7 @@ pad_pin_set(device_t dev, uint32_t pin, if (i >= sc->gpio_npins) return (EINVAL); - if (get_bank(pin, &bank, &pin_shift) != 0) + if (get_bank(sc, pin, &bank, &pin_shift) != 0) return (EINVAL); GPIO_LOCK(sc); Added: head/sys/arm/samsung/exynos/exynos5_pmu.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/arm/samsung/exynos/exynos5_pmu.c Fri Aug 1 06:20:25 2014 (r269369) @@ -0,0 +1,181 @@ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408010620.s716KPuM095202>