From: Georgi Vlaev <gvlaev@xxxxxxxxxxx> The driver allows access to the BootFPGA logic of the I2CS FPGA @0xfed5000 from the LPC bus. The driver exports debugfs entries for manipulating registers and device attrs for reading board and FPGA IDs and switching the active BIOS flash. The client devices created by the MFD driver depend on the PCB and FPGA version numbers. PTX1K (etch1) RE boards support only watchdog clients. Warn on using engineering releases (FPGA version = 0xEE) and disable clients on revisions known to cause problems. - watchdog - jnx_ptx1kbf_wdt - mtd - jnx_ptx1kbf_mtd (etch2) - hwmon - jnx_ptx1kbf_hwmon (etch2) Signed-off-by: Georgi Vlaev <gvlaev@xxxxxxxxxxx> Signed-off-by: Guenter Roeck <groeck@xxxxxxxxxxx> Signed-off-by: JawaharBalaji Thirumalaisamy <jawaharb@xxxxxxxxxxx> [Ported from Juniper kernel] Signed-off-by: Pantelis Antoniou <pantelis.antoniou@xxxxxxxxxxxx> --- drivers/mfd/Kconfig | 11 + drivers/mfd/Makefile | 1 + drivers/mfd/ptx1k-bootfpga.c | 462 +++++++++++++++++++++++++++++++++++++ include/linux/mfd/ptx1k-bootfpga.h | 93 ++++++++ 4 files changed, 567 insertions(+) create mode 100644 drivers/mfd/ptx1k-bootfpga.c create mode 100644 include/linux/mfd/ptx1k-bootfpga.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 82493d5..a2564ba 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1417,6 +1417,17 @@ config MFD_JUNIPER_I2CS This driver can be built as a module. If built as a module it will be called "jnx_i2cs" +config MFD_JUNIPER_PTX1KBF + tristate "Juniper PTX1K RCB I2CS BootFPGA" + depends on JNX_PTX1K_RCB + select MFD_CORE + help + Select this to enable the I2CS Boot FPGA multi-function kernel driver. + This FPGA is present on the PTX1K RCB. + + This driver can be built as a module. If built as a module it will be + called "ptx1k-bootfpga" + config MFD_TWL4030_AUDIO bool "TI TWL4030 Audio" depends on TWL4030_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 215d9cf..1661b82 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -153,6 +153,7 @@ obj-$(CONFIG_MFD_JUNIPER_SAM) += sam-core.o obj-$(CONFIG_MFD_JUNIPER_EXT_CPLD) += ptxpmb-ext-cpld-core.o obj-$(CONFIG_MFD_JUNIPER_CBC) += cbc-core.o obj-$(CONFIG_MFD_JUNIPER_I2CS) += jnx-i2cs-core.o +obj-$(CONFIG_MFD_JUNIPER_PTX1KBF) += ptx1k-bootfpga.o obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o # ab8500-core need to come after db8500-prcmu (which provides the channel) obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o diff --git a/drivers/mfd/ptx1k-bootfpga.c b/drivers/mfd/ptx1k-bootfpga.c new file mode 100644 index 0000000..5ab2ed2 --- /dev/null +++ b/drivers/mfd/ptx1k-bootfpga.c @@ -0,0 +1,462 @@ +/* + * Juniper Networks PTX1K RCB I2CS Boot FPGA multi-function core driver + * + * Copyright (C) 2014 Juniper Networks. All rights reserved. + * Author: Georgi Vlaev <gvlaev@xxxxxxxxxxx> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 <linux/device.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/acpi.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/mfd/core.h> +#include <linux/mfd/ptx1k-bootfpga.h> + +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/string.h> +#include <linux/ctype.h> +#endif + +struct ptx1kbf_core { + struct device *dev; + void __iomem *base; +#ifdef CONFIG_DEBUG_FS + struct dentry *dir; + u8 addr; /* any register offsset */ + struct debugfs_blob_wrapper blob; /* regspace page blob */ +#endif +}; + +static struct resource ptx1kbf_resources[] = { + { + .start = 0, + .end = 0xff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct mfd_cell ptx1kbf_cells[] = { + { + .name = "jnx-ptx1kbf-wdt", + .num_resources = ARRAY_SIZE(ptx1kbf_resources), + .resources = ptx1kbf_resources, + .of_compatible = "jnx,ptx1kbf-wdt", + }, { + .name = "jnx-ptx1kbf-mtd", + .num_resources = ARRAY_SIZE(ptx1kbf_resources), + .resources = ptx1kbf_resources, + .of_compatible = "jnx,ptx1kbf-mtd", + }, { + .name = "jnx-ptx1kbf-hwmon", + .num_resources = ARRAY_SIZE(ptx1kbf_resources), + .resources = ptx1kbf_resources, + .of_compatible = "jnx,ptx1kbf-hwmon", + }, +}; + +/* ptx1k-bootfpga debugfs */ +#ifdef CONFIG_DEBUG_FS +/* debugfs: set/get register offset */ +static int bf_debugfs_addr_print(struct seq_file *s, void *p) +{ + struct ptx1kbf_core *bf = (struct ptx1kbf_core *)s->private; + + seq_printf(s, "0x%02X\n", bf->addr); + + return 0; +} + +static int bf_debugfs_addr_open(struct inode *inode, struct file *file) +{ + return single_open(file, bf_debugfs_addr_print, inode->i_private); +} + +static ssize_t bf_debugfs_addr_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct ptx1kbf_core *bf = + ((struct seq_file *)(file->private_data))->private; + unsigned long addr; + int err; + + err = kstrtoul_from_user(user_buf, count, 0, &addr); + if (err) + return err; + + if (addr > ptx1kbf_resources[0].end) { + dev_err(bf->dev, "register offset out of range\n"); + return -EINVAL; + } + bf->addr = addr; + + return count; +} + +static const struct file_operations bf_debugfs_addr_fops = { + .open = bf_debugfs_addr_open, + .write = bf_debugfs_addr_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +/* debugfs: set/get register value */ +static int bf_debugfs_val_print(struct seq_file *s, void *p) +{ + struct ptx1kbf_core *bf = (struct ptx1kbf_core *)s->private; + + seq_printf(s, "0x%02X\n", ioread8(bf->base + bf->addr)); + + return 0; +} + +static int bf_debugfs_val_open(struct inode *inode, struct file *file) +{ + return single_open(file, bf_debugfs_val_print, inode->i_private); +} + +static ssize_t bf_debugfs_val_write(struct file *file, + const char __user *user_buf, size_t count, loff_t *ppos) +{ + struct ptx1kbf_core *bf = + ((struct seq_file *)(file->private_data))->private; + unsigned long value; + int err; + + err = kstrtoul_from_user(user_buf, count, 0, &value); + if (err) + return err; + + iowrite8(value & 0xff, bf->base + bf->addr); + + return count; +} + +static const struct file_operations bf_debugfs_val_fops = { + .open = bf_debugfs_val_open, + .write = bf_debugfs_val_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int bf_debugfs_init(struct ptx1kbf_core *bf) +{ + struct dentry *file; + + bf->dir = debugfs_create_dir("ptx1k-bootfpga", NULL); + if (!bf->dir) + return -ENOMEM; + +/* Register dump */ + bf->blob.size = resource_size(&ptx1kbf_resources[0]); + bf->blob.data = bf->base; + + file = debugfs_create_blob("reg-dump", S_IFREG | S_IRUSR, bf->dir, + &bf->blob); + if (!file) + goto err; + +/* Any register @base */ + file = debugfs_create_file("reg-address", (S_IRUGO | S_IWUSR), + bf->dir, bf, &bf_debugfs_addr_fops); + if (!file) + goto err; + + file = debugfs_create_file("reg-value", (S_IRUGO | S_IWUSR), + bf->dir, bf, &bf_debugfs_val_fops); + if (!file) + goto err; + + return 0; +err: + debugfs_remove_recursive(bf->dir); + dev_err(bf->dev, "failed to create debugfs entries.\n"); + + return -ENOMEM; +} + +static void bf_debugfs_remove(struct ptx1kbf_core *bf) +{ + debugfs_remove_recursive(bf->dir); +} +#endif /* CONFIG_DEBUG_FS */ + +/* Export FPGA board revisions and status as device attrs */ +static ssize_t bf_reg_show(struct device *dev, char *buf, u8 reg) +{ + struct ptx1kbf_core *bf = dev_get_drvdata(dev); + + return sprintf(buf, "%02x\n", ioread8(bf->base + reg)); +} + +static ssize_t bf_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return bf_reg_show(dev, buf, BOOT_FPGA_VERSION); +} + +static ssize_t bf_board_id_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return bf_reg_show(dev, buf, BOOT_FPGA_BOARD_ID); +} + +static ssize_t bf_jspec_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return bf_reg_show(dev, buf, BOOT_FPGA_JSPEC_VERSION); +} + +static ssize_t bf_pcb_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return bf_reg_show(dev, buf, BOOT_FPGA_PCB_VERSION); +} + +static ssize_t bf_chassis_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return bf_reg_show(dev, buf, BOOT_FPGA_CHASSIS_TYPE); +} + +/* active_flash: (BIOS) Switch bethween FlashA and FlashB */ +static ssize_t bf_active_flash_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ptx1kbf_core *bf = dev_get_drvdata(dev); + u8 reg = ioread8(bf->base + BOOT_FPGA_BOOT_CONTROL); + + return sprintf(buf, "%u\n", (u8)(reg & BC_FLASH_SELECT) >> 4); +} + +static ssize_t bf_active_flash_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ptx1kbf_core *bf = dev_get_drvdata(dev); + unsigned long val; + int err; + u8 reg; + + err = kstrtoul(buf, 10, &val); + if (err) + return err; + + if (val > 1) + return -EINVAL; + + reg = ioread8(bf->base + BOOT_FPGA_BOOT_CONTROL); + reg &= ~BC_FLASH_SELECT; + reg |= (u8)((val << 4) & BC_FLASH_SELECT); + iowrite8(reg, bf->base + BOOT_FPGA_BOOT_CONTROL); + + return count; +} + +static DEVICE_ATTR(version, S_IRUGO, bf_version_show, NULL); +static DEVICE_ATTR(board_id, S_IRUGO, bf_board_id_show, NULL); +static DEVICE_ATTR(jspec_version, S_IRUGO, bf_jspec_version_show, NULL); +static DEVICE_ATTR(pcb_version, S_IRUGO, bf_pcb_version_show, NULL); +static DEVICE_ATTR(chassis_type, S_IRUGO, bf_chassis_type_show, NULL); +static DEVICE_ATTR(active_flash, S_IRUGO | S_IWUSR, bf_active_flash_show, + bf_active_flash_store); + +static struct attribute *bf_attrs[] = { + &dev_attr_version.attr, + &dev_attr_board_id.attr, + &dev_attr_jspec_version.attr, + &dev_attr_pcb_version.attr, + &dev_attr_chassis_type.attr, + &dev_attr_active_flash.attr, + NULL, +}; + +static struct attribute_group bf_attr_group = { + .attrs = bf_attrs, +}; + +/* Check if scratch regs are usable */ +static int bf_scratch_test(struct ptx1kbf_core *bf) +{ + u8 i, ii; + + for (i = 0; i < 0xff; i++) { + iowrite8(i, bf->base + BOOT_FPGA_SCRATCH1); + ii = ioread8(bf->base + BOOT_FPGA_SCRATCH1); + if (ii != i) { + dev_err(bf->dev, "Scratch(1) write failed: %02x->%02x", + i, ii); + return -EIO; + } + } + + for (i = 0; i < 0xff; i++) { + iowrite8(i, bf->base + BOOT_FPGA_SCRATCH2); + ii = ioread8(bf->base + BOOT_FPGA_SCRATCH2); + if (ii != i) { + dev_err(bf->dev, "Scratch(2) write failed: %02x->%02x", + i, ii); + return -EIO; + } + } + + iowrite8(0, bf->base + BOOT_FPGA_SCRATCH1); + iowrite8(0, bf->base + BOOT_FPGA_SCRATCH2); + + return 0; +} + +static int ptx1kbf_probe(struct platform_device *pdev) +{ + static struct ptx1kbf_core *bf; + struct device *dev = &pdev->dev; + struct resource *res; + int err, ncells = 0; + u8 pcb_version, fpga_version; + + bf = devm_kzalloc(dev, sizeof(struct ptx1kbf_core), GFP_KERNEL); + if (!bf) + return -ENOMEM; + + bf->dev = dev; + dev_set_drvdata(dev, bf); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + bf->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); + if (IS_ERR(bf->base)) + return -EADDRNOTAVAIL; + + /* Get the FPGA & PCB versions to filter supported features */ + fpga_version = ioread8(bf->base + BOOT_FPGA_VERSION), + pcb_version = ioread8(bf->base + BOOT_FPGA_PCB_VERSION); + + dev_info(dev, "FPGA version: 0x%02X, PCB version: 0x%02X\n", + fpga_version, pcb_version); + + /* Exit if scratch loop fails */ + err = bf_scratch_test(bf); + if (err) + return err; + + /* + * Support matrix. + * PCB version #0 (ETCH1) = Spartan XC3S400AN + * PCB version #1 (ETCH2) = Spartan XC3S700AN + * + * PCB version #0 supported devices + * - watchdog (FPGA version >= 0x0E) + * - hwmon & mtd unsupported due to FPGA limitations + * + * PCB version #1 supported devices + * - watchdog (FPGA version >= 0x0E) + * - mtd devices (FPGA version > 0x0E) + * - hwmon (FPGA version > 0x0F ?) + * + * FPGA version 0xEE is "engineering release", warn on usage. + * FPGA version 0xC0 and < 0x0E are unsupported. + */ + + /* Engineering release - allow it to run for testing/debug */ + if (fpga_version == 0xEE) { + dev_warn(dev, + "0x%02X is engineering release, consider FPGA update", + fpga_version); + } + + if (fpga_version != 0xC0 && fpga_version >= 0x0E) { + /* wdt - any pcb, fpga >= 0x0E && !0xC0 */ + ncells = 1; + + /* mtd - pcb > 0, fpga >= 0x0F + * Versions bellow 0x0F may cause damage of the flash (!) + */ + if (pcb_version > 0 && fpga_version > 0x0E) + ncells = 2; + + /* hwmon - pcb > 0, fpga > 0x0F (assumption) */ + if (pcb_version > 0 && fpga_version > 0x0F) + ncells = 3; + + err = mfd_add_devices(dev, pdev->id, ptx1kbf_cells, + ncells, res, 0, NULL); + if (err) + return err; + } else { + /* Unsupported - known to cause problems: 0xC0, < 0x0E */ + dev_err(dev, + "0x%02X is unsupported version, consider FPGA update", + fpga_version); + } + + err = sysfs_create_group(&dev->kobj, &bf_attr_group); + if (err) { + sysfs_remove_group(&dev->kobj, &bf_attr_group); + goto err_mfd; + } + +#ifdef CONFIG_DEBUG_FS + bf_debugfs_init(bf); +#endif + + return 0; + +err_mfd: + mfd_remove_devices(&pdev->dev); + + return err; +} + +static int ptx1kbf_remove(struct platform_device *pdev) +{ +#ifdef CONFIG_DEBUG_FS + struct ptx1kbf_core *bf = dev_get_drvdata(&pdev->dev); + + bf_debugfs_remove(bf); +#endif + sysfs_remove_group(&pdev->dev.kobj, &bf_attr_group); + mfd_remove_devices(&pdev->dev); + return 0; +} + +static const struct of_device_id ptx1kbf_of_ids[] = { + { .compatible = "jnx,ptx1k-bootfpga" }, + { } +}; +MODULE_DEVICE_TABLE(of, ptx1kbf_of_ids); + +static struct platform_driver ptx1kbf_driver = { + .driver = { + .name = "ptx1k-bootfpga", + .of_match_table = ptx1kbf_of_ids, + .owner = THIS_MODULE, + }, + .probe = ptx1kbf_probe, + .remove = ptx1kbf_remove, +}; + +module_platform_driver(ptx1kbf_driver); + +MODULE_DESCRIPTION("Juniper Networks PTX1K RCB I2CS Boot FPGA Driver"); +MODULE_AUTHOR("Georgi Vlaev <gvlaev@xxxxxxxxxxx>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:ptx1k-bootfpga"); diff --git a/include/linux/mfd/ptx1k-bootfpga.h b/include/linux/mfd/ptx1k-bootfpga.h new file mode 100644 index 0000000..6a40c95 --- /dev/null +++ b/include/linux/mfd/ptx1k-bootfpga.h @@ -0,0 +1,93 @@ +/* + * PTX1K I2CS Boot FPGA registers + * + * Copyright (C) 2014 Juniper Networks. All rights reserved. + * Author: Georgi Vlaev <gvlaev@xxxxxxxxxxx> + * + * 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; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __PTX1K_BOOTFPGA_H__ +#define __PTX1K_BOOTFPGA_H__ + +#include <linux/bitops.h> + +#define BOOT_FPGA_SCRATCH1 0x00 +#define BOOT_FPGA_SCRATCH2 0x01 +#define BOOT_FPGA_VERSION 0x02 +#define BOOT_FPGA_JSPEC_VERSION 0x03 +#define BOOT_FPGA_PCB_VERSION 0x04 +#define BOOT_FPGA_BOARD_ID 0x05 +#define BOOT_FPGA_RESET_REASON1 0x06 +#define BOOT_FPGA_RESET_REASON2 0x07 +#define BOOT_FPGA_RESET_CONTROL_AND_STATUS1 0x08 +#define BOOT_FPGA_RESET_CONTROL_AND_STATUS2 0x09 +#define BOOT_FPGA_RESET_CONTROL_AND_STATUS3 0x0a +#define BOOT_FPGA_BOOT_CONTROL 0x0b +#define BOOT_FPGA_WATCHDOG_TIMER_THRESHOLD 0x0c +#define BOOT_FPGA_ERROR_STATUS1 0x0d +#define BOOT_FPGA_ERROR_STATUS2 0x0e +#define BOOT_FPGA_ERROR_STATUS3 0x0f +#define BOOT_FPGA_IRQ_ENABLE1 0x10 +#define BOOT_FPGA_IRQ_STATUS1 0x11 +#define BOOT_FPGA_IRQ_ENABLE2 0x12 +#define BOOT_FPGA_IRQ_STATUS2 0x13 +#define BOOT_FPGA_CHASSIS_TYPE 0x14 +#define BOOT_FPGA_POST_CODE 0x15 +#define BOOT_FPGA_MISC_CONTROL 0x16 +#define BOOT_FPGA_MISC_STATUS 0x17 +#define BOOT_FPGA_CPU_TEMP_MSB 0x18 +#define BOOT_FPGA_CPU_TEMP_LSB 0x19 +#define BOOT_FPGA_PCH_TEMP_MSB 0x1a +#define BOOT_FPGA_PCH_TEMP_LSB 0x1b +#define BOOT_FPGA_DIMM1_TEMP_MSB 0x1c +#define BOOT_FPGA_DIMM1_TEMP_LSB 0x1d +#define BOOT_FPGA_DIMM2_TEMP_MSB 0x1e +#define BOOT_FPGA_DIMM2_TEMP_LSB 0x1f + +#define BOOT_FPGA_SFPP_USB_SSD_PWR_CONTROL 0x20 +#define BOOT_FPGA_FPGA_ID 0x21 +#define BOOT_FPGA_SPI_FLASH_CONTROL_AND_STATUS 0x22 +#define BOOT_FPGA_PCH_NMI_SLEEP_RT_STATUS 0x23 +#define BOOT_FPGA_PCH_NMI_SLEEP_LATCHED_STATUS 0x24 + +#define BOOT_FPGA_FLASH_IF_ADDR(a) (0xe0 + (a)) +#define BOOT_FPGA_FLASH_IF_BYTE_COUNT(a) (0xe4 + (a)) +#define BOOT_FPGA_FLASH_IF_CONTROL(a) (0xe8 + (a)) +#define BOOT_FPGA_FLASH_IF_STATUS(a) (0xec + (a)) +#define BOOT_FPGA_FLASH_IF_WRITE_BUF_ADDR_MSB 0xf0 +#define BOOT_FPGA_FLASH_IF_WRITE_BUF_ADDR_LSB 0xf1 +#define BOOT_FPGA_FLASH_IF_WRITE_BUF_DATA 0xf2 +#define BOOT_FPGA_FLASH_IF_READ_BUF_ADDR_MSB 0xf3 +#define BOOT_FPGA_FLASH_IF_READ_BUF_ADDR_LSB 0xf4 +#define BOOT_FPGA_FLASH_IF_READ_BUF_DATA 0xf5 + +#define BOOT_FPGA_RU_CONFIG_CONTROL_STATUS 0xf6 +#define BOOT_FPGA_RU_CONFIG_STATUS_DATA_MSB 0xf7 +#define BOOT_FPGA_RU_CONFIG_STATUS_DATA_LSB 0xf8 +#define BOOT_FPGA_RU_CONFIG_ADDR_23_DOWNTO_16 0xf9 +#define BOOT_FPGA_RU_CONFIG_ADDR_15_DOWNTO_8 0xfa +#define BOOT_FPGA_RU_CONFIG_ADDR_7_DOWNTO_0 0xfb + +#define RR1_SW BIT(7) /* SW initiated reset */ +#define RR1_WDOG BIT(6) /* Watchdog induced reset */ +#define RR1_MSTR BIT(5) /* System host (Master RE) initiated reset */ +#define RR1_BUTTON BIT(4) /* Front panel button reset */ +#define RR1_POWER_CYCLE BIT(3) /* Natural power cycle */ +#define RR1_POWER_FAIL BIT(2) /* Power fail */ +#define RR1_THERM_TRIP BIT(1) /* CPU thermal trip */ +#define RR1_PCH BIT(0) /* PCH initiated reset, e.g TCO timer expiry */ + +#define RR2_MSMI_FATAL BIT(3) /* CPU MSMI# fatal reset */ +#define RR2_CATERR_IERR BIT(2) /* CPU CATERR_IERR# induced reset */ +#define RR2_XDP BIT(1) /* XDP request reset */ +#define RR2_AUTO_POWER_OFF BIT(0) /* Auto power off */ + +#define BC_WDT_ENA BIT(6) /* Watchdog timer enable */ +#define BC_FLASH_SELECT BIT(4) /* Flash select enable/status */ +#define WTT_THRESHOLD_MASK 0x3f + +#endif /*__PTX1K_BOOTFPGA_H__*/ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html