From e184a4583be698d913d548ce0a91953cff84d071 Mon Sep 17 00:00:00 2001 From: jmcneill Date: Wed, 22 Oct 2014 00:24:52 +0000 Subject: [PATCH] Add support for GPIO configuration via "FEX" scripts, in an attempt to keep awin_device_register under control. Board configuration scripts can be found here: https://github.com/linux-sunxi/sunxi-boards/blob/master/sys_config You can compile them with the "fex2bin" tool found here: https://github.com/linux-sunxi/sunxi-tools To use, copy the compiled FEX to your MS-DOS partition, load it with U-Boot, and then tell the kernel where to find it with the "sysconfig=" boot option. For example, uEnv.txt on a Cubieboard2 might look like this: bootargs=root=ld0a sysconfig=0x43000000 uenvcmd=mmc dev 0; mmc rescan; fatload mmc 0:1 43000000 cubieboard2.bin; fatload mmc 0:1 82000000 netbsd.ub; bootm 82000000 --- sys/arch/evbarm/awin/awin_machdep.c | 76 +++++++++- sys/arch/evbarm/awin/awin_sysconfig.c | 197 ++++++++++++++++++++++++++ sys/arch/evbarm/awin/awin_sysconfig.h | 38 +++++ sys/arch/evbarm/conf/files.awin | 7 +- sys/arch/evbarm/conf/std.awin | 3 +- 5 files changed, 317 insertions(+), 4 deletions(-) create mode 100644 sys/arch/evbarm/awin/awin_sysconfig.c create mode 100644 sys/arch/evbarm/awin/awin_sysconfig.h diff --git a/sys/arch/evbarm/awin/awin_machdep.c b/sys/arch/evbarm/awin/awin_machdep.c index 6ceb2f4d8770..9f8487125f08 100644 --- a/sys/arch/evbarm/awin/awin_machdep.c +++ b/sys/arch/evbarm/awin/awin_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: awin_machdep.c,v 1.19 2014/10/19 22:37:08 jmcneill Exp $ */ +/* $NetBSD: awin_machdep.c,v 1.20 2014/10/22 00:24:52 jmcneill Exp $ */ /* * Machine dependent functions for kernel setup for TI OSK5912 board. @@ -125,7 +125,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.19 2014/10/19 22:37:08 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.20 2014/10/22 00:24:52 jmcneill Exp $"); #include "opt_machdep.h" #include "opt_ddb.h" @@ -182,6 +182,10 @@ __KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.19 2014/10/19 22:37:08 jmcneill E #include #include +#ifdef AWIN_SYSCONFIG +#include +#endif + #include #include @@ -201,6 +205,12 @@ bool cubietruck_p; #define cubietruck_p false #endif +#ifdef AWIN_SYSCONFIG +bool awin_sysconfig_p; +#else +#define awin_sysconfig_p false +#endif + /* * uboot_args are filled in by awin_start.S and must be in .data * and not .bss since .bss is cleared after uboot_args are filled in. @@ -236,6 +246,10 @@ static void kgdb_port_init(void); static void awin_device_register(device_t, void *); +#ifdef AWIN_SYSCONFIG +static void awin_gpio_sysconfig(prop_dictionary_t); +#endif + #if NCOM > 0 #include #include @@ -416,11 +430,18 @@ initarm(void *arg) (uboot_args[3] + KERNEL_BASE_VOFFSET); strlcpy(bootargs, args, sizeof(bootargs)); } + } boot_args = bootargs; parse_mi_bootargs(boot_args); +#ifdef AWIN_SYSCONFIG + if (mapallmem_p) { + awin_sysconfig_p = awin_sysconfig_init(); + } +#endif + /* we've a specific device_register routine */ evbarm_device_register = awin_device_register; @@ -586,6 +607,16 @@ awin_device_register(device_t self, void *aux) } if (device_is_a(self, "awingpio")) { +#ifdef AWIN_SYSCONFIG + /* + * Configure GPIOs using FEX script + */ + if (awin_sysconfig_p) { + awin_gpio_sysconfig(dict); + return; + } +#endif + /* * These are GPIOs being used for various functions. */ @@ -720,3 +751,44 @@ awin_device_register(device_t self, void *aux) return; } } + +#ifdef AWIN_SYSCONFIG +static void +awin_gpio_sysconfig(prop_dictionary_t dict) +{ + static const struct { + const char *prop; + const char *key; + const char *subkey; + } gpios[] = { + { "satapwren", "sata_para", "sata_power_en" }, + { "usb0drv", "usbc0", "usb_drv_vbus_gpio" }, + { "usb0iddet", "usbc0", "usb_id_gpio" }, + { "usb0vbusdet", "usbc0", "usb_det_vbus_gpio" }, + { "usb1drv", "usbc1", "usb_drv_vbus_gpio" }, + { "usb1iddet", "usbc1", "usb_id_gpio" }, + { "usb1vbusdet", "usbc1", "usb_det_vbus_gpio" }, + { "usb2drv", "usbc2", "usb_drv_vbus_gpio" }, + { "usb2iddet", "usbc2", "usb_id_gpio" }, + { "usb2vbusdet", "usbc2", "usb_det_vbus_gpio" }, + { "status-led1", "leds_para", "leds_pin_1" }, + { "status-led2", "leds_para", "leds_pin_2" }, + { "status-led3", "leds_para", "leds_pin_3" }, + { "status-led4", "leds_para", "leds_pin_4" }, + { "mmc0detect", "mmc0_para", "sdc_det" }, + { "audiopactrl", "audio_para", "audio_pa_ctrl" }, + }; + unsigned int n; + + aprint_normal(":"); + + for (n = 0; n < __arraycount(gpios); n++) { + const char *cfg = awin_sysconfig_get_gpio( + gpios[n].key, gpios[n].subkey); + if (cfg) { + aprint_normal(" [%s %s]", gpios[n].prop, cfg); + prop_dictionary_set_cstring(dict, gpios[n].prop, cfg); + } + } +} +#endif diff --git a/sys/arch/evbarm/awin/awin_sysconfig.c b/sys/arch/evbarm/awin/awin_sysconfig.c new file mode 100644 index 000000000000..f64d1d544cf6 --- /dev/null +++ b/sys/arch/evbarm/awin/awin_sysconfig.c @@ -0,0 +1,197 @@ +/* $NetBSD: awin_sysconfig.c,v 1.1 2014/10/22 00:24:52 jmcneill Exp $ */ + +/*- + * Copyright (c) 2014 Jared D. McNeill + * 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 "opt_allwinner.h" + +#include +__KERNEL_RCSID(0, "$NetBSD: awin_sysconfig.c,v 1.1 2014/10/22 00:24:52 jmcneill Exp $"); + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +static paddr_t awin_sysconfig_base = 0; +#define AWIN_SYSCONFIG_SIZE 0x10000 + +#define AWIN_SYSCONFIG_TYPE_UNKNOWN 0 +#define AWIN_SYSCONFIG_TYPE_SINGLE_WORD 1 +#define AWIN_SYSCONFIG_TYPE_STRING 2 +#define AWIN_SYSCONFIG_TYPE_MULTI_WORD 3 +#define AWIN_SYSCONFIG_TYPE_GPIO 4 + +static uint8_t awin_sysconfig[AWIN_SYSCONFIG_SIZE]; + +struct awin_sysconfig_head { + uint32_t count; + uint32_t version[3]; +} __packed; + +struct awin_sysconfig_main_key { + char name[32]; + uint32_t count; + uint32_t offset; +} __packed; + +struct awin_sysconfig_sub_key { + char name[32]; + uint32_t offset; + uint16_t count; + uint16_t type; +} __packed; + +struct awin_sysconfig_gpio { + char name[32]; + uint32_t port; + uint32_t port_num; + int32_t mul_sel; + int32_t pull; + int32_t drv_level; + int32_t data; +} __packed; + +static bool awin_sysconfig_parse(const char *, const char *, + struct awin_sysconfig_sub_key *); + +bool +awin_sysconfig_init(void) +{ + if (get_bootconf_option(boot_args, "sysconfig", + BOOTOPT_TYPE_HEXINT, &awin_sysconfig_base) == 0) { + return false; + } + if (awin_sysconfig_base == 0) { + return false; + } + + const uint8_t * const sysconfig = (const uint8_t *) + (awin_sysconfig_base + KERNEL_BASE_VOFFSET); + memcpy(awin_sysconfig, sysconfig, AWIN_SYSCONFIG_SIZE); + + return true; +} + +static bool +awin_sysconfig_parse(const char *key, const char *subkey, + struct awin_sysconfig_sub_key *value) +{ + struct awin_sysconfig_head head; + struct awin_sysconfig_main_key main_key; + struct awin_sysconfig_sub_key sub_key; + unsigned int off, n; + + KASSERT(awin_sysconfig_base != 0); + + memcpy(&head, &awin_sysconfig[0], sizeof(head)); + + for (n = 0, off = sizeof(head); n < head.count; + n++, off += sizeof(main_key)) { + memcpy(&main_key, &awin_sysconfig[off], sizeof(main_key)); + if (strcmp(key, main_key.name) == 0) { + break; + } + } + if (n == head.count) { + return false; + } + + for (n = 0, off = main_key.offset << 2; n < main_key.count; + n++, off += sizeof(sub_key)) { + memcpy(&sub_key, &awin_sysconfig[off], sizeof(sub_key)); + if (strcmp(subkey, sub_key.name) == 0) { + break; + } + } + if (n == main_key.count) { + return false; + } + + memcpy(value, &sub_key, sizeof(*value)); + + return true; +} + +int +awin_sysconfig_get_int(const char *key, const char *subkey) +{ + struct awin_sysconfig_sub_key value; + int ret; + + if (awin_sysconfig_parse(key, subkey, &value) == false) + return -1; + + KASSERT(value.type == AWIN_SYSCONFIG_TYPE_SINGLE_WORD); + + memcpy(&ret, &awin_sysconfig[value.offset << 2], sizeof(ret)); + + return ret; +} + +const char * +awin_sysconfig_get_string(const char *key, const char *subkey) +{ + struct awin_sysconfig_sub_key value; + + if (awin_sysconfig_parse(key, subkey, &value) == false) + return NULL; + + KASSERT(value.type == AWIN_SYSCONFIG_TYPE_STRING); + + return &awin_sysconfig[value.offset << 2]; +} + +const char * +awin_sysconfig_get_gpio(const char *key, const char *subkey) +{ + static char gpio_str[6]; + struct awin_sysconfig_sub_key value; + struct awin_sysconfig_gpio gpio; + + if (awin_sysconfig_parse(key, subkey, &value) == false) + return NULL; + + if (value.type != AWIN_SYSCONFIG_TYPE_GPIO) + return NULL; + + memcpy(&gpio, &awin_sysconfig[(value.offset << 2) - 32], sizeof(gpio)); + + snprintf(gpio_str, sizeof(gpio_str), "%cP%c%d", + gpio.mul_sel == 0 ? '<' : '>', + (gpio.port - 1) + 'A', gpio.port_num); + + return gpio_str; +} diff --git a/sys/arch/evbarm/awin/awin_sysconfig.h b/sys/arch/evbarm/awin/awin_sysconfig.h new file mode 100644 index 000000000000..60b3b774d827 --- /dev/null +++ b/sys/arch/evbarm/awin/awin_sysconfig.h @@ -0,0 +1,38 @@ +/* $NetBSD: awin_sysconfig.h,v 1.1 2014/10/22 00:24:52 jmcneill Exp $ */ + +/*- + * Copyright (c) 2014 Jared D. McNeill + * 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. + */ + +#ifndef _AWIN_SYSCONFIG_H +#define _AWIN_SYSCONFIG_H + +bool awin_sysconfig_init(void); + +int awin_sysconfig_get_int(const char *, const char *); +const char * awin_sysconfig_get_string(const char *, const char *); +const char * awin_sysconfig_get_gpio(const char *, const char *); + +#endif /* !_AWIN_SYSCONFIG_H */ diff --git a/sys/arch/evbarm/conf/files.awin b/sys/arch/evbarm/conf/files.awin index 5efe5e034ab2..2e8c634abf65 100644 --- a/sys/arch/evbarm/conf/files.awin +++ b/sys/arch/evbarm/conf/files.awin @@ -1,4 +1,4 @@ -# $NetBSD: files.awin,v 1.1 2014/08/31 19:13:01 matt Exp $ +# $NetBSD: files.awin,v 1.2 2014/10/22 00:24:52 jmcneill Exp $ # # Allwinner AXX evaluation board configuration info # @@ -8,5 +8,10 @@ file arch/evbarm/awin/awin_machdep.c # Kernel boot arguments defparam opt_machdep.h BOOT_ARGS +# System config +defopt opt_allwinner.h AWIN_SYSCONFIG + +file arch/evbarm/awin/awin_sysconfig.c awin_sysconfig + # CPU support and integrated peripherals include "arch/arm/allwinner/files.awin" diff --git a/sys/arch/evbarm/conf/std.awin b/sys/arch/evbarm/conf/std.awin index b6336300a0cd..4c0f384b05f7 100644 --- a/sys/arch/evbarm/conf/std.awin +++ b/sys/arch/evbarm/conf/std.awin @@ -1,4 +1,4 @@ -# $NetBSD: std.awin,v 1.4 2014/10/14 22:42:36 jmcneill Exp $ +# $NetBSD: std.awin,v 1.5 2014/10/22 00:24:52 jmcneill Exp $ # # standard NetBSD/evbarm for Allwinner based options @@ -21,6 +21,7 @@ options KERNEL_BASE_EXT=0x80000000 options FPU_VFP options GTTWSI_ALLWINNER options MOTG_ALLWINNER +options AWIN_SYSCONFIG makeoptions KERNEL_BASE_PHYS="0x40007800" makeoptions KERNEL_BASE_VIRT="0x80007800"