Index: stable/11/sys/arm/conf/TEGRA124 =================================================================== --- stable/11/sys/arm/conf/TEGRA124 (revision 332009) +++ stable/11/sys/arm/conf/TEGRA124 (revision 332010) @@ -1,140 +1,141 @@ # # Kernel configuration for NVIDIA Tegra124 based boards. # # 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$ include "std.armv6" include "../nvidia/tegra124/std.tegra124" ident TEGRA124 options SCHED_ULE # ULE scheduler options PLATFORM # Platform based SoC options PLATFORM_SMP options MULTIDELAY options SMP # Enable multiple cores options LINUX_BOOT_ABI # Interrupt controller device gic # ARM Generic Timer device generic_timer # EXT_RESOURCES pseudo devices options EXT_RESOURCES device clk device phy device hwreset device regulator # Pseudo devices. device loop # Network loopback device random # Entropy device device vlan # 802.1Q VLAN support #device tun # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling -#device firmware # firmware assist module +device firmware # firmware assist module device ether # Ethernet support device miibus # Required for ethernet device bpf # Berkeley packet filter (required for DHCP) # General-purpose input/output device gpio #device gpioled # I2C support device iic device iicbus device icee # Serial (COM) ports device uart # Multi-uart driver device uart_ns8250 # MMC/SD/SDIO Card slot support device sdhci # SD controller device mmc # SD/MMC protocol device mmcsd # SDCard disk device # ATA controllers device ahci # AHCI-compatible SATA controllers # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) # USB support options USB_HOST_ALIGN=64 # Align usb buffers to cache line size. device ehci # EHCI USB interface +device xhci # XHCI USB interface +device tegra124_xusb_fw # Tegra XUSB firmware device usb # USB Bus (required) device umass # Disks/Mass storage - Requires scbus and da device uhid # "Human Interface Devices" #device u3g # USB modems device ukbd # Allow keyboard like HIDs to control console device ums # USB mouse # USB Ethernet, requires miibus #device aue # ADMtek USB Ethernet #device axe # ASIX Electronics USB Ethernet #device cdce # Generic USB over Ethernet #device cue # CATC USB Ethernet #device kue # Kawasaki LSI USB Ethernet #device rue # RealTek RTL8150 USB Ethernet #device udav # Davicom DM9601E USB # USB Wireless #device rum # Ralink Technology RT2501USB wireless NICs # Wireless NIC cards #device wlan # 802.11 support #device wlan_wep # 802.11 WEP support #device wlan_ccmp # 802.11 CCMP support #device wlan_tkip # 802.11 TKIP support #device wlan_amrr # AMRR transmit rate control algorithm # PCI options NEW_PCIB device pci # PCI Ethernet NICs that use the common MII bus controller code. # NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! device re # RealTek 8139C+/8169/8169S/8110S # DRM2 -#device fbd -#device vt -#device splash -#device kbdmux -#device drm2 +device fbd +device vt +device kbdmux +device drm2 # Sound #device sound #device snd_hda # Flattened Device Tree options FDT # Configure using FDT/DTB data device fdt_pinctrl # SoC-specific devices #device hwpmc Index: stable/11/sys/arm/nvidia/drm2/hdmi.c =================================================================== --- stable/11/sys/arm/nvidia/drm2/hdmi.c (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/hdmi.c (revision 332010) @@ -0,0 +1,1229 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include + +#define EXPORT_SYMBOL(x) +#ifndef BIT +#define BIT(x) (1U << (x)) +#endif +#define hdmi_log(fmt, ...) printf(fmt, ##__VA_ARGS__) + +static uint8_t hdmi_infoframe_checksum(uint8_t *ptr, size_t size) +{ + uint8_t csum = 0; + size_t i; + + /* compute checksum */ + for (i = 0; i < size; i++) + csum += ptr[i]; + + return 256 - csum; +} + +static void hdmi_infoframe_set_checksum(void *buffer, size_t size) +{ + uint8_t *ptr = buffer; + + ptr[3] = hdmi_infoframe_checksum(buffer, size); +} + +/** + * hdmi_avi_infoframe_init() - initialize an HDMI AVI infoframe + * @frame: HDMI AVI infoframe + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame) +{ + memset(frame, 0, sizeof(*frame)); + + frame->type = HDMI_INFOFRAME_TYPE_AVI; + frame->version = 2; + frame->length = HDMI_AVI_INFOFRAME_SIZE; + + return 0; +} +EXPORT_SYMBOL(hdmi_avi_infoframe_init); + +/** + * hdmi_avi_infoframe_pack() - write HDMI AVI infoframe to binary buffer + * @frame: HDMI AVI infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Packs the information contained in the @frame structure into a binary + * representation that can be written into the corresponding controller + * registers. Also computes the checksum as required by section 5.3.5 of + * the HDMI 1.4 specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer, + size_t size) +{ + uint8_t *ptr = buffer; + size_t length; + + length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; + + if (size < length) + return -ENOSPC; + + memset(buffer, 0, size); + + ptr[0] = frame->type; + ptr[1] = frame->version; + ptr[2] = frame->length; + ptr[3] = 0; /* checksum */ + + /* start infoframe payload */ + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + ptr[0] = ((frame->colorspace & 0x3) << 5) | (frame->scan_mode & 0x3); + + /* + * Data byte 1, bit 4 has to be set if we provide the active format + * aspect ratio + */ + if (frame->active_aspect & 0xf) + ptr[0] |= BIT(4); + + /* Bit 3 and 2 indicate if we transmit horizontal/vertical bar data */ + if (frame->top_bar || frame->bottom_bar) + ptr[0] |= BIT(3); + + if (frame->left_bar || frame->right_bar) + ptr[0] |= BIT(2); + + ptr[1] = ((frame->colorimetry & 0x3) << 6) | + ((frame->picture_aspect & 0x3) << 4) | + (frame->active_aspect & 0xf); + + ptr[2] = ((frame->extended_colorimetry & 0x7) << 4) | + ((frame->quantization_range & 0x3) << 2) | + (frame->nups & 0x3); + + if (frame->itc) + ptr[2] |= BIT(7); + + ptr[3] = frame->video_code & 0x7f; + + ptr[4] = ((frame->ycc_quantization_range & 0x3) << 6) | + ((frame->content_type & 0x3) << 4) | + (frame->pixel_repeat & 0xf); + + ptr[5] = frame->top_bar & 0xff; + ptr[6] = (frame->top_bar >> 8) & 0xff; + ptr[7] = frame->bottom_bar & 0xff; + ptr[8] = (frame->bottom_bar >> 8) & 0xff; + ptr[9] = frame->left_bar & 0xff; + ptr[10] = (frame->left_bar >> 8) & 0xff; + ptr[11] = frame->right_bar & 0xff; + ptr[12] = (frame->right_bar >> 8) & 0xff; + + hdmi_infoframe_set_checksum(buffer, length); + + return length; +} +EXPORT_SYMBOL(hdmi_avi_infoframe_pack); + +/** + * hdmi_spd_infoframe_init() - initialize an HDMI SPD infoframe + * @frame: HDMI SPD infoframe + * @vendor: vendor string + * @product: product string + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame, + const char *vendor, const char *product) +{ + memset(frame, 0, sizeof(*frame)); + + frame->type = HDMI_INFOFRAME_TYPE_SPD; + frame->version = 1; + frame->length = HDMI_SPD_INFOFRAME_SIZE; + + strncpy(frame->vendor, vendor, sizeof(frame->vendor)); + strncpy(frame->product, product, sizeof(frame->product)); + + return 0; +} +EXPORT_SYMBOL(hdmi_spd_infoframe_init); + +/** + * hdmi_spd_infoframe_pack() - write HDMI SPD infoframe to binary buffer + * @frame: HDMI SPD infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Packs the information contained in the @frame structure into a binary + * representation that can be written into the corresponding controller + * registers. Also computes the checksum as required by section 5.3.5 of + * the HDMI 1.4 specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer, + size_t size) +{ + uint8_t *ptr = buffer; + size_t length; + + length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; + + if (size < length) + return -ENOSPC; + + memset(buffer, 0, size); + + ptr[0] = frame->type; + ptr[1] = frame->version; + ptr[2] = frame->length; + ptr[3] = 0; /* checksum */ + + /* start infoframe payload */ + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + memcpy(ptr, frame->vendor, sizeof(frame->vendor)); + memcpy(ptr + 8, frame->product, sizeof(frame->product)); + + ptr[24] = frame->sdi; + + hdmi_infoframe_set_checksum(buffer, length); + + return length; +} +EXPORT_SYMBOL(hdmi_spd_infoframe_pack); + +/** + * hdmi_audio_infoframe_init() - initialize an HDMI audio infoframe + * @frame: HDMI audio infoframe + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame) +{ + memset(frame, 0, sizeof(*frame)); + + frame->type = HDMI_INFOFRAME_TYPE_AUDIO; + frame->version = 1; + frame->length = HDMI_AUDIO_INFOFRAME_SIZE; + + return 0; +} +EXPORT_SYMBOL(hdmi_audio_infoframe_init); + +/** + * hdmi_audio_infoframe_pack() - write HDMI audio infoframe to binary buffer + * @frame: HDMI audio infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Packs the information contained in the @frame structure into a binary + * representation that can be written into the corresponding controller + * registers. Also computes the checksum as required by section 5.3.5 of + * the HDMI 1.4 specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, + void *buffer, size_t size) +{ + unsigned char channels; + uint8_t *ptr = buffer; + size_t length; + + length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; + + if (size < length) + return -ENOSPC; + + memset(buffer, 0, size); + + if (frame->channels >= 2) + channels = frame->channels - 1; + else + channels = 0; + + ptr[0] = frame->type; + ptr[1] = frame->version; + ptr[2] = frame->length; + ptr[3] = 0; /* checksum */ + + /* start infoframe payload */ + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7); + ptr[1] = ((frame->sample_frequency & 0x7) << 2) | + (frame->sample_size & 0x3); + ptr[2] = frame->coding_type_ext & 0x1f; + ptr[3] = frame->channel_allocation; + ptr[4] = (frame->level_shift_value & 0xf) << 3; + + if (frame->downmix_inhibit) + ptr[4] |= BIT(7); + + hdmi_infoframe_set_checksum(buffer, length); + + return length; +} +EXPORT_SYMBOL(hdmi_audio_infoframe_pack); + +/** + * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe + * @frame: HDMI vendor infoframe + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame) +{ + memset(frame, 0, sizeof(*frame)); + + frame->type = HDMI_INFOFRAME_TYPE_VENDOR; + frame->version = 1; + + frame->oui = HDMI_IEEE_OUI; + + /* + * 0 is a valid value for s3d_struct, so we use a special "not set" + * value + */ + frame->s3d_struct = HDMI_3D_STRUCTURE_INVALID; + + return 0; +} +EXPORT_SYMBOL(hdmi_vendor_infoframe_init); + +/** + * hdmi_vendor_infoframe_pack() - write a HDMI vendor infoframe to binary buffer + * @frame: HDMI infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Packs the information contained in the @frame structure into a binary + * representation that can be written into the corresponding controller + * registers. Also computes the checksum as required by section 5.3.5 of + * the HDMI 1.4 specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, + void *buffer, size_t size) +{ + uint8_t *ptr = buffer; + size_t length; + + /* empty info frame */ + if (frame->vic == 0 && frame->s3d_struct == HDMI_3D_STRUCTURE_INVALID) + return -EINVAL; + + /* only one of those can be supplied */ + if (frame->vic != 0 && frame->s3d_struct != HDMI_3D_STRUCTURE_INVALID) + return -EINVAL; + + /* for side by side (half) we also need to provide 3D_Ext_Data */ + if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) + frame->length = 6; + else + frame->length = 5; + + length = HDMI_INFOFRAME_HEADER_SIZE + frame->length; + + if (size < length) + return -ENOSPC; + + memset(buffer, 0, size); + + ptr[0] = frame->type; + ptr[1] = frame->version; + ptr[2] = frame->length; + ptr[3] = 0; /* checksum */ + + /* HDMI OUI */ + ptr[4] = 0x03; + ptr[5] = 0x0c; + ptr[6] = 0x00; + + if (frame->vic) { + ptr[7] = 0x1 << 5; /* video format */ + ptr[8] = frame->vic; + } else { + ptr[7] = 0x2 << 5; /* video format */ + ptr[8] = (frame->s3d_struct & 0xf) << 4; + if (frame->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) + ptr[9] = (frame->s3d_ext_data & 0xf) << 4; + } + + hdmi_infoframe_set_checksum(buffer, length); + + return length; +} +EXPORT_SYMBOL(hdmi_vendor_infoframe_pack); + +/* + * hdmi_vendor_any_infoframe_pack() - write a vendor infoframe to binary buffer + */ +static ssize_t +hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame, + void *buffer, size_t size) +{ + /* we only know about HDMI vendor infoframes */ + if (frame->any.oui != HDMI_IEEE_OUI) + return -EINVAL; + + return hdmi_vendor_infoframe_pack(&frame->hdmi, buffer, size); +} + +/** + * hdmi_infoframe_pack() - write a HDMI infoframe to binary buffer + * @frame: HDMI infoframe + * @buffer: destination buffer + * @size: size of buffer + * + * Packs the information contained in the @frame structure into a binary + * representation that can be written into the corresponding controller + * registers. Also computes the checksum as required by section 5.3.5 of + * the HDMI 1.4 specification. + * + * Returns the number of bytes packed into the binary buffer or a negative + * error code on failure. + */ +ssize_t +hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size) +{ + ssize_t length; + + switch (frame->any.type) { + case HDMI_INFOFRAME_TYPE_AVI: + length = hdmi_avi_infoframe_pack(&frame->avi, buffer, size); + break; + case HDMI_INFOFRAME_TYPE_SPD: + length = hdmi_spd_infoframe_pack(&frame->spd, buffer, size); + break; + case HDMI_INFOFRAME_TYPE_AUDIO: + length = hdmi_audio_infoframe_pack(&frame->audio, buffer, size); + break; + case HDMI_INFOFRAME_TYPE_VENDOR: + length = hdmi_vendor_any_infoframe_pack(&frame->vendor, + buffer, size); + break; + default: + printf("Bad infoframe type %d\n", frame->any.type); + length = -EINVAL; + } + + return length; +} +EXPORT_SYMBOL(hdmi_infoframe_pack); + +static const char *hdmi_infoframe_type_get_name(enum hdmi_infoframe_type type) +{ + if (type < 0x80 || type > 0x9f) + return "Invalid"; + switch (type) { + case HDMI_INFOFRAME_TYPE_VENDOR: + return "Vendor"; + case HDMI_INFOFRAME_TYPE_AVI: + return "Auxiliary Video Information (AVI)"; + case HDMI_INFOFRAME_TYPE_SPD: + return "Source Product Description (SPD)"; + case HDMI_INFOFRAME_TYPE_AUDIO: + return "Audio"; + } + return "Reserved"; +} + +static void hdmi_infoframe_log_header(struct hdmi_any_infoframe *frame) +{ + hdmi_log("HDMI infoframe: %s, version %u, length %u\n", + hdmi_infoframe_type_get_name(frame->type), + frame->version, frame->length); +} + +static const char *hdmi_colorspace_get_name(enum hdmi_colorspace colorspace) +{ + switch (colorspace) { + case HDMI_COLORSPACE_RGB: + return "RGB"; + case HDMI_COLORSPACE_YUV422: + return "YCbCr 4:2:2"; + case HDMI_COLORSPACE_YUV444: + return "YCbCr 4:4:4"; + case HDMI_COLORSPACE_YUV420: + return "YCbCr 4:2:0"; + case HDMI_COLORSPACE_RESERVED4: + return "Reserved (4)"; + case HDMI_COLORSPACE_RESERVED5: + return "Reserved (5)"; + case HDMI_COLORSPACE_RESERVED6: + return "Reserved (6)"; + case HDMI_COLORSPACE_IDO_DEFINED: + return "IDO Defined"; + } + return "Invalid"; +} + +static const char *hdmi_scan_mode_get_name(enum hdmi_scan_mode scan_mode) +{ + switch (scan_mode) { + case HDMI_SCAN_MODE_NONE: + return "No Data"; + case HDMI_SCAN_MODE_OVERSCAN: + return "Overscan"; + case HDMI_SCAN_MODE_UNDERSCAN: + return "Underscan"; + case HDMI_SCAN_MODE_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char *hdmi_colorimetry_get_name(enum hdmi_colorimetry colorimetry) +{ + switch (colorimetry) { + case HDMI_COLORIMETRY_NONE: + return "No Data"; + case HDMI_COLORIMETRY_ITU_601: + return "ITU601"; + case HDMI_COLORIMETRY_ITU_709: + return "ITU709"; + case HDMI_COLORIMETRY_EXTENDED: + return "Extended"; + } + return "Invalid"; +} + +static const char * +hdmi_picture_aspect_get_name(enum hdmi_picture_aspect picture_aspect) +{ + switch (picture_aspect) { + case HDMI_PICTURE_ASPECT_NONE: + return "No Data"; + case HDMI_PICTURE_ASPECT_4_3: + return "4:3"; + case HDMI_PICTURE_ASPECT_16_9: + return "16:9"; + case HDMI_PICTURE_ASPECT_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char * +hdmi_active_aspect_get_name(enum hdmi_active_aspect active_aspect) +{ + if (active_aspect > 0xf) + return "Invalid"; + + switch (active_aspect) { + case HDMI_ACTIVE_ASPECT_16_9_TOP: + return "16:9 Top"; + case HDMI_ACTIVE_ASPECT_14_9_TOP: + return "14:9 Top"; + case HDMI_ACTIVE_ASPECT_16_9_CENTER: + return "16:9 Center"; + case HDMI_ACTIVE_ASPECT_PICTURE: + return "Same as Picture"; + case HDMI_ACTIVE_ASPECT_4_3: + return "4:3"; + case HDMI_ACTIVE_ASPECT_16_9: + return "16:9"; + case HDMI_ACTIVE_ASPECT_14_9: + return "14:9"; + case HDMI_ACTIVE_ASPECT_4_3_SP_14_9: + return "4:3 SP 14:9"; + case HDMI_ACTIVE_ASPECT_16_9_SP_14_9: + return "16:9 SP 14:9"; + case HDMI_ACTIVE_ASPECT_16_9_SP_4_3: + return "16:9 SP 4:3"; + } + return "Reserved"; +} + +static const char * +hdmi_extended_colorimetry_get_name(enum hdmi_extended_colorimetry ext_col) +{ + switch (ext_col) { + case HDMI_EXTENDED_COLORIMETRY_XV_YCC_601: + return "xvYCC 601"; + case HDMI_EXTENDED_COLORIMETRY_XV_YCC_709: + return "xvYCC 709"; + case HDMI_EXTENDED_COLORIMETRY_S_YCC_601: + return "sYCC 601"; + case HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601: + return "Adobe YCC 601"; + case HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB: + return "Adobe RGB"; + case HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM: + return "BT.2020 Constant Luminance"; + case HDMI_EXTENDED_COLORIMETRY_BT2020: + return "BT.2020"; + case HDMI_EXTENDED_COLORIMETRY_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char * +hdmi_quantization_range_get_name(enum hdmi_quantization_range qrange) +{ + switch (qrange) { + case HDMI_QUANTIZATION_RANGE_DEFAULT: + return "Default"; + case HDMI_QUANTIZATION_RANGE_LIMITED: + return "Limited"; + case HDMI_QUANTIZATION_RANGE_FULL: + return "Full"; + case HDMI_QUANTIZATION_RANGE_RESERVED: + return "Reserved"; + } + return "Invalid"; +} + +static const char *hdmi_nups_get_name(enum hdmi_nups nups) +{ + switch (nups) { + case HDMI_NUPS_UNKNOWN: + return "Unknown Non-uniform Scaling"; + case HDMI_NUPS_HORIZONTAL: + return "Horizontally Scaled"; + case HDMI_NUPS_VERTICAL: + return "Vertically Scaled"; + case HDMI_NUPS_BOTH: + return "Horizontally and Vertically Scaled"; + } + return "Invalid"; +} + +static const char * +hdmi_ycc_quantization_range_get_name(enum hdmi_ycc_quantization_range qrange) +{ + switch (qrange) { + case HDMI_YCC_QUANTIZATION_RANGE_LIMITED: + return "Limited"; + case HDMI_YCC_QUANTIZATION_RANGE_FULL: + return "Full"; + } + return "Invalid"; +} + +static const char * +hdmi_content_type_get_name(enum hdmi_content_type content_type) +{ + switch (content_type) { + case HDMI_CONTENT_TYPE_GRAPHICS: + return "Graphics"; + case HDMI_CONTENT_TYPE_PHOTO: + return "Photo"; + case HDMI_CONTENT_TYPE_CINEMA: + return "Cinema"; + case HDMI_CONTENT_TYPE_GAME: + return "Game"; + } + return "Invalid"; +} + +/** + * hdmi_avi_infoframe_log() - log info of HDMI AVI infoframe + * @level: logging level + * @dev: device + * @frame: HDMI AVI infoframe + */ +static void hdmi_avi_infoframe_log(struct hdmi_avi_infoframe *frame) +{ + hdmi_infoframe_log_header((struct hdmi_any_infoframe *)frame); + + hdmi_log(" colorspace: %s\n", + hdmi_colorspace_get_name(frame->colorspace)); + hdmi_log(" scan mode: %s\n", + hdmi_scan_mode_get_name(frame->scan_mode)); + hdmi_log(" colorimetry: %s\n", + hdmi_colorimetry_get_name(frame->colorimetry)); + hdmi_log(" picture aspect: %s\n", + hdmi_picture_aspect_get_name(frame->picture_aspect)); + hdmi_log(" active aspect: %s\n", + hdmi_active_aspect_get_name(frame->active_aspect)); + hdmi_log(" itc: %s\n", frame->itc ? "IT Content" : "No Data"); + hdmi_log(" extended colorimetry: %s\n", + hdmi_extended_colorimetry_get_name(frame->extended_colorimetry)); + hdmi_log(" quantization range: %s\n", + hdmi_quantization_range_get_name(frame->quantization_range)); + hdmi_log(" nups: %s\n", hdmi_nups_get_name(frame->nups)); + hdmi_log(" video code: %u\n", frame->video_code); + hdmi_log(" ycc quantization range: %s\n", + hdmi_ycc_quantization_range_get_name(frame->ycc_quantization_range)); + hdmi_log(" hdmi content type: %s\n", + hdmi_content_type_get_name(frame->content_type)); + hdmi_log(" pixel repeat: %u\n", frame->pixel_repeat); + hdmi_log(" bar top %u, bottom %u, left %u, right %u\n", + frame->top_bar, frame->bottom_bar, + frame->left_bar, frame->right_bar); +} + +static const char *hdmi_spd_sdi_get_name(enum hdmi_spd_sdi sdi) +{ +; + switch (sdi) { + case HDMI_SPD_SDI_UNKNOWN: + return "Unknown"; + case HDMI_SPD_SDI_DSTB: + return "Digital STB"; + case HDMI_SPD_SDI_DVDP: + return "DVD Player"; + case HDMI_SPD_SDI_DVHS: + return "D-VHS"; + case HDMI_SPD_SDI_HDDVR: + return "HDD Videorecorder"; + case HDMI_SPD_SDI_DVC: + return "DVC"; + case HDMI_SPD_SDI_DSC: + return "DSC"; + case HDMI_SPD_SDI_VCD: + return "Video CD"; + case HDMI_SPD_SDI_GAME: + return "Game"; + case HDMI_SPD_SDI_PC: + return "PC General"; + case HDMI_SPD_SDI_BD: + return "Blu-Ray Disc (BD)"; + case HDMI_SPD_SDI_SACD: + return "Super Audio CD"; + case HDMI_SPD_SDI_HDDVD: + return "HD DVD"; + case HDMI_SPD_SDI_PMP: + return "PMP"; + } + return "Reserved"; +} + +/** + * hdmi_spd_infoframe_log() - log info of HDMI SPD infoframe + * @level: logging level + * @dev: device + * @frame: HDMI SPD infoframe + */ +static void hdmi_spd_infoframe_log(struct hdmi_spd_infoframe *frame) +{ + uint8_t buf[17]; + + hdmi_infoframe_log_header((struct hdmi_any_infoframe *)frame); + + memset(buf, 0, sizeof(buf)); + + strncpy(buf, frame->vendor, 8); + hdmi_log(" vendor: %s\n", buf); + strncpy(buf, frame->product, 16); + hdmi_log(" product: %s\n", buf); + hdmi_log(" source device information: %s (0x%x)\n", + hdmi_spd_sdi_get_name(frame->sdi), frame->sdi); +} + +static const char * +hdmi_audio_coding_type_get_name(enum hdmi_audio_coding_type coding_type) +{ + switch (coding_type) { + case HDMI_AUDIO_CODING_TYPE_STREAM: + return "Refer to Stream Header"; + case HDMI_AUDIO_CODING_TYPE_PCM: + return "PCM"; + case HDMI_AUDIO_CODING_TYPE_AC3: + return "AC-3"; + case HDMI_AUDIO_CODING_TYPE_MPEG1: + return "MPEG1"; + case HDMI_AUDIO_CODING_TYPE_MP3: + return "MP3"; + case HDMI_AUDIO_CODING_TYPE_MPEG2: + return "MPEG2"; + case HDMI_AUDIO_CODING_TYPE_AAC_LC: + return "AAC"; + case HDMI_AUDIO_CODING_TYPE_DTS: + return "DTS"; + case HDMI_AUDIO_CODING_TYPE_ATRAC: + return "ATRAC"; + case HDMI_AUDIO_CODING_TYPE_DSD: + return "One Bit Audio"; + case HDMI_AUDIO_CODING_TYPE_EAC3: + return "Dolby Digital +"; + case HDMI_AUDIO_CODING_TYPE_DTS_HD: + return "DTS-HD"; + case HDMI_AUDIO_CODING_TYPE_MLP: + return "MAT (MLP)"; + case HDMI_AUDIO_CODING_TYPE_DST: + return "DST"; + case HDMI_AUDIO_CODING_TYPE_WMA_PRO: + return "WMA PRO"; + case HDMI_AUDIO_CODING_TYPE_CXT: + return "Refer to CXT"; + } + return "Invalid"; +} + +static const char * +hdmi_audio_sample_size_get_name(enum hdmi_audio_sample_size sample_size) +{ + switch (sample_size) { + case HDMI_AUDIO_SAMPLE_SIZE_STREAM: + return "Refer to Stream Header"; + case HDMI_AUDIO_SAMPLE_SIZE_16: + return "16 bit"; + case HDMI_AUDIO_SAMPLE_SIZE_20: + return "20 bit"; + case HDMI_AUDIO_SAMPLE_SIZE_24: + return "24 bit"; + } + return "Invalid"; +} + +static const char * +hdmi_audio_sample_frequency_get_name(enum hdmi_audio_sample_frequency freq) +{ + switch (freq) { + case HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM: + return "Refer to Stream Header"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_32000: + return "32 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_44100: + return "44.1 kHz (CD)"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_48000: + return "48 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_88200: + return "88.2 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_96000: + return "96 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_176400: + return "176.4 kHz"; + case HDMI_AUDIO_SAMPLE_FREQUENCY_192000: + return "192 kHz"; + } + return "Invalid"; +} + +static const char * +hdmi_audio_coding_type_ext_get_name(enum hdmi_audio_coding_type_ext ctx) +{ + + switch (ctx) { + case HDMI_AUDIO_CODING_TYPE_EXT_CT: + return "Refer to CT"; + case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC: + return "HE AAC"; + case HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2: + return "HE AAC v2"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND: + return "MPEG SURROUND"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC: + return "MPEG-4 HE AAC"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2: + return "MPEG-4 HE AAC v2"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC: + return "MPEG-4 AAC LC"; + case HDMI_AUDIO_CODING_TYPE_EXT_DRA: + return "DRA"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND: + return "MPEG-4 HE AAC + MPEG Surround"; + case HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND: + return "MPEG-4 AAC LC + MPEG Surround"; + } + return "Reserved"; +} + +/** + * hdmi_audio_infoframe_log() - log info of HDMI AUDIO infoframe + * @level: logging level + * @dev: device + * @frame: HDMI AUDIO infoframe + */ +static void hdmi_audio_infoframe_log(struct hdmi_audio_infoframe *frame) +{ + hdmi_infoframe_log_header((struct hdmi_any_infoframe *)frame); + + if (frame->channels) + hdmi_log(" channels: %u\n", frame->channels - 1); + else + hdmi_log(" channels: Refer to stream header\n"); + hdmi_log(" coding type: %s\n", + hdmi_audio_coding_type_get_name(frame->coding_type)); + hdmi_log(" sample size: %s\n", + hdmi_audio_sample_size_get_name(frame->sample_size)); + hdmi_log(" sample frequency: %s\n", + hdmi_audio_sample_frequency_get_name(frame->sample_frequency)); + hdmi_log(" coding type ext: %s\n", + hdmi_audio_coding_type_ext_get_name(frame->coding_type_ext)); + hdmi_log(" channel allocation: 0x%x\n", + frame->channel_allocation); + hdmi_log(" level shift value: %u dB\n", + frame->level_shift_value); + hdmi_log(" downmix inhibit: %s\n", + frame->downmix_inhibit ? "Yes" : "No"); +} + +static const char * +hdmi_3d_structure_get_name(enum hdmi_3d_structure s3d_struct) +{ + if (s3d_struct < 0 || s3d_struct > 0xf) + return "Invalid"; + + switch (s3d_struct) { + case HDMI_3D_STRUCTURE_FRAME_PACKING: + return "Frame Packing"; + case HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE: + return "Field Alternative"; + case HDMI_3D_STRUCTURE_LINE_ALTERNATIVE: + return "Line Alternative"; + case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL: + return "Side-by-side (Full)"; + case HDMI_3D_STRUCTURE_L_DEPTH: + return "L + Depth"; + case HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH: + return "L + Depth + Graphics + Graphics-depth"; + case HDMI_3D_STRUCTURE_TOP_AND_BOTTOM: + return "Top-and-Bottom"; + case HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF: + return "Side-by-side (Half)"; + default: + break; + } + return "Reserved"; +} + +/** + * hdmi_vendor_infoframe_log() - log info of HDMI VENDOR infoframe + * @level: logging level + * @dev: device + * @frame: HDMI VENDOR infoframe + */ +static void +hdmi_vendor_any_infoframe_log(union hdmi_vendor_any_infoframe *frame) +{ + struct hdmi_vendor_infoframe *hvf = &frame->hdmi; + + hdmi_infoframe_log_header((struct hdmi_any_infoframe *)frame); + + if (frame->any.oui != HDMI_IEEE_OUI) { + hdmi_log(" not a HDMI vendor infoframe\n"); + return; + } + if (hvf->vic == 0 && hvf->s3d_struct == HDMI_3D_STRUCTURE_INVALID) { + hdmi_log(" empty frame\n"); + return; + } + + if (hvf->vic) + hdmi_log(" HDMI VIC: %u\n", hvf->vic); + if (hvf->s3d_struct != HDMI_3D_STRUCTURE_INVALID) { + hdmi_log(" 3D structure: %s\n", + hdmi_3d_structure_get_name(hvf->s3d_struct)); + if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) + hdmi_log(" 3D extension data: %d\n", + hvf->s3d_ext_data); + } +} + +/** + * hdmi_infoframe_log() - log info of HDMI infoframe + * @level: logging level + * @dev: device + * @frame: HDMI infoframe + */ +void hdmi_infoframe_log(union hdmi_infoframe *frame) +{ + switch (frame->any.type) { + case HDMI_INFOFRAME_TYPE_AVI: + hdmi_avi_infoframe_log(&frame->avi); + break; + case HDMI_INFOFRAME_TYPE_SPD: + hdmi_spd_infoframe_log(&frame->spd); + break; + case HDMI_INFOFRAME_TYPE_AUDIO: + hdmi_audio_infoframe_log(&frame->audio); + break; + case HDMI_INFOFRAME_TYPE_VENDOR: + hdmi_vendor_any_infoframe_log(&frame->vendor); + break; + } +} +EXPORT_SYMBOL(hdmi_infoframe_log); + +/** + * hdmi_avi_infoframe_unpack() - unpack binary buffer to a HDMI AVI infoframe + * @buffer: source buffer + * @frame: HDMI AVI infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Auxiliary Video (AVI) information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int hdmi_avi_infoframe_unpack(struct hdmi_avi_infoframe *frame, + void *buffer) +{ + uint8_t *ptr = buffer; + int ret; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_AVI || + ptr[1] != 2 || + ptr[2] != HDMI_AVI_INFOFRAME_SIZE) + return -EINVAL; + + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AVI)) != 0) + return -EINVAL; + + ret = hdmi_avi_infoframe_init(frame); + if (ret) + return ret; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + frame->colorspace = (ptr[0] >> 5) & 0x3; + if (ptr[0] & 0x10) + frame->active_aspect = ptr[1] & 0xf; + if (ptr[0] & 0x8) { + frame->top_bar = (ptr[5] << 8) + ptr[6]; + frame->bottom_bar = (ptr[7] << 8) + ptr[8]; + } + if (ptr[0] & 0x4) { + frame->left_bar = (ptr[9] << 8) + ptr[10]; + frame->right_bar = (ptr[11] << 8) + ptr[12]; + } + frame->scan_mode = ptr[0] & 0x3; + + frame->colorimetry = (ptr[1] >> 6) & 0x3; + frame->picture_aspect = (ptr[1] >> 4) & 0x3; + frame->active_aspect = ptr[1] & 0xf; + + frame->itc = ptr[2] & 0x80 ? true : false; + frame->extended_colorimetry = (ptr[2] >> 4) & 0x7; + frame->quantization_range = (ptr[2] >> 2) & 0x3; + frame->nups = ptr[2] & 0x3; + + frame->video_code = ptr[3] & 0x7f; + frame->ycc_quantization_range = (ptr[4] >> 6) & 0x3; + frame->content_type = (ptr[4] >> 4) & 0x3; + + frame->pixel_repeat = ptr[4] & 0xf; + + return 0; +} + +/** + * hdmi_spd_infoframe_unpack() - unpack binary buffer to a HDMI SPD infoframe + * @buffer: source buffer + * @frame: HDMI SPD infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Source Product Description (SPD) information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int hdmi_spd_infoframe_unpack(struct hdmi_spd_infoframe *frame, + void *buffer) +{ + uint8_t *ptr = buffer; + int ret; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_SPD || + ptr[1] != 1 || + ptr[2] != HDMI_SPD_INFOFRAME_SIZE) { + return -EINVAL; + } + + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(SPD)) != 0) + return -EINVAL; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + ret = hdmi_spd_infoframe_init(frame, ptr, ptr + 8); + if (ret) + return ret; + + frame->sdi = ptr[24]; + + return 0; +} + +/** + * hdmi_audio_infoframe_unpack() - unpack binary buffer to a HDMI AUDIO infoframe + * @buffer: source buffer + * @frame: HDMI Audio infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Audio information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int hdmi_audio_infoframe_unpack(struct hdmi_audio_infoframe *frame, + void *buffer) +{ + uint8_t *ptr = buffer; + int ret; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_AUDIO || + ptr[1] != 1 || + ptr[2] != HDMI_AUDIO_INFOFRAME_SIZE) { + return -EINVAL; + } + + if (hdmi_infoframe_checksum(buffer, HDMI_INFOFRAME_SIZE(AUDIO)) != 0) + return -EINVAL; + + ret = hdmi_audio_infoframe_init(frame); + if (ret) + return ret; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + frame->channels = ptr[0] & 0x7; + frame->coding_type = (ptr[0] >> 4) & 0xf; + frame->sample_size = ptr[1] & 0x3; + frame->sample_frequency = (ptr[1] >> 2) & 0x7; + frame->coding_type_ext = ptr[2] & 0x1f; + frame->channel_allocation = ptr[3]; + frame->level_shift_value = (ptr[4] >> 3) & 0xf; + frame->downmix_inhibit = ptr[4] & 0x80 ? true : false; + + return 0; +} + +/** + * hdmi_vendor_infoframe_unpack() - unpack binary buffer to a HDMI vendor infoframe + * @buffer: source buffer + * @frame: HDMI Vendor infoframe + * + * Unpacks the information contained in binary @buffer into a structured + * @frame of the HDMI Vendor information frame. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +static int +hdmi_vendor_any_infoframe_unpack(union hdmi_vendor_any_infoframe *frame, + void *buffer) +{ + uint8_t *ptr = buffer; + size_t length; + int ret; + uint8_t hdmi_video_format; + struct hdmi_vendor_infoframe *hvf = &frame->hdmi; + + if (ptr[0] != HDMI_INFOFRAME_TYPE_VENDOR || + ptr[1] != 1 || + (ptr[2] != 5 && ptr[2] != 6)) + return -EINVAL; + + length = ptr[2]; + + if (hdmi_infoframe_checksum(buffer, + HDMI_INFOFRAME_HEADER_SIZE + length) != 0) + return -EINVAL; + + ptr += HDMI_INFOFRAME_HEADER_SIZE; + + /* HDMI OUI */ + if ((ptr[0] != 0x03) || + (ptr[1] != 0x0c) || + (ptr[2] != 0x00)) + return -EINVAL; + + hdmi_video_format = ptr[3] >> 5; + + if (hdmi_video_format > 0x2) + return -EINVAL; + + ret = hdmi_vendor_infoframe_init(hvf); + if (ret) + return ret; + + hvf->length = length; + + if (hdmi_video_format == 0x1) { + hvf->vic = ptr[4]; + } else if (hdmi_video_format == 0x2) { + hvf->s3d_struct = ptr[4] >> 4; + if (hvf->s3d_struct >= HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF) { + if (length == 6) + hvf->s3d_ext_data = ptr[5] >> 4; + else + return -EINVAL; + } + } + + return 0; +} + +/** + * hdmi_infoframe_unpack() - unpack binary buffer to a HDMI infoframe + * @buffer: source buffer + * @frame: HDMI infoframe + * + * Unpacks the information contained in binary buffer @buffer into a structured + * @frame of a HDMI infoframe. + * Also verifies the checksum as required by section 5.3.5 of the HDMI 1.4 + * specification. + * + * Returns 0 on success or a negative error code on failure. + */ +int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer) +{ + int ret; + uint8_t *ptr = buffer; + + switch (ptr[0]) { + case HDMI_INFOFRAME_TYPE_AVI: + ret = hdmi_avi_infoframe_unpack(&frame->avi, buffer); + break; + case HDMI_INFOFRAME_TYPE_SPD: + ret = hdmi_spd_infoframe_unpack(&frame->spd, buffer); + break; + case HDMI_INFOFRAME_TYPE_AUDIO: + ret = hdmi_audio_infoframe_unpack(&frame->audio, buffer); + break; + case HDMI_INFOFRAME_TYPE_VENDOR: + ret = hdmi_vendor_any_infoframe_unpack(&frame->vendor, buffer); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +EXPORT_SYMBOL(hdmi_infoframe_unpack); Property changes on: stable/11/sys/arm/nvidia/drm2/hdmi.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/hdmi.h =================================================================== --- stable/11/sys/arm/nvidia/drm2/hdmi.h (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/hdmi.h (revision 332010) @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2012 Avionic Design GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef _HDMI_H_ +#define _HDMI_H_ + + +enum hdmi_infoframe_type { + HDMI_INFOFRAME_TYPE_VENDOR = 0x81, + HDMI_INFOFRAME_TYPE_AVI = 0x82, + HDMI_INFOFRAME_TYPE_SPD = 0x83, + HDMI_INFOFRAME_TYPE_AUDIO = 0x84, +}; + +#define HDMI_IEEE_OUI 0x000c03 +#define HDMI_INFOFRAME_HEADER_SIZE 4 +#define HDMI_AVI_INFOFRAME_SIZE 13 +#define HDMI_SPD_INFOFRAME_SIZE 25 +#define HDMI_AUDIO_INFOFRAME_SIZE 10 + +#define HDMI_INFOFRAME_SIZE(type) \ + (HDMI_INFOFRAME_HEADER_SIZE + HDMI_ ## type ## _INFOFRAME_SIZE) + +struct hdmi_any_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; +}; + +enum hdmi_colorspace { + HDMI_COLORSPACE_RGB, + HDMI_COLORSPACE_YUV422, + HDMI_COLORSPACE_YUV444, + HDMI_COLORSPACE_YUV420, + HDMI_COLORSPACE_RESERVED4, + HDMI_COLORSPACE_RESERVED5, + HDMI_COLORSPACE_RESERVED6, + HDMI_COLORSPACE_IDO_DEFINED, +}; + +enum hdmi_scan_mode { + HDMI_SCAN_MODE_NONE, + HDMI_SCAN_MODE_OVERSCAN, + HDMI_SCAN_MODE_UNDERSCAN, + HDMI_SCAN_MODE_RESERVED, +}; + +enum hdmi_colorimetry { + HDMI_COLORIMETRY_NONE, + HDMI_COLORIMETRY_ITU_601, + HDMI_COLORIMETRY_ITU_709, + HDMI_COLORIMETRY_EXTENDED, +}; + +enum hdmi_picture_aspect { + HDMI_PICTURE_ASPECT_NONE, + HDMI_PICTURE_ASPECT_4_3, + HDMI_PICTURE_ASPECT_16_9, + HDMI_PICTURE_ASPECT_RESERVED, +}; + +enum hdmi_active_aspect { + HDMI_ACTIVE_ASPECT_16_9_TOP = 2, + HDMI_ACTIVE_ASPECT_14_9_TOP = 3, + HDMI_ACTIVE_ASPECT_16_9_CENTER = 4, + HDMI_ACTIVE_ASPECT_PICTURE = 8, + HDMI_ACTIVE_ASPECT_4_3 = 9, + HDMI_ACTIVE_ASPECT_16_9 = 10, + HDMI_ACTIVE_ASPECT_14_9 = 11, + HDMI_ACTIVE_ASPECT_4_3_SP_14_9 = 13, + HDMI_ACTIVE_ASPECT_16_9_SP_14_9 = 14, + HDMI_ACTIVE_ASPECT_16_9_SP_4_3 = 15, +}; + +enum hdmi_extended_colorimetry { + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601, + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709, + HDMI_EXTENDED_COLORIMETRY_S_YCC_601, + HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601, + HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB, + + /* The following EC values are only defined in CEA-861-F. */ + HDMI_EXTENDED_COLORIMETRY_BT2020_CONST_LUM, + HDMI_EXTENDED_COLORIMETRY_BT2020, + HDMI_EXTENDED_COLORIMETRY_RESERVED, +}; + +enum hdmi_quantization_range { + HDMI_QUANTIZATION_RANGE_DEFAULT, + HDMI_QUANTIZATION_RANGE_LIMITED, + HDMI_QUANTIZATION_RANGE_FULL, + HDMI_QUANTIZATION_RANGE_RESERVED, +}; + +/* non-uniform picture scaling */ +enum hdmi_nups { + HDMI_NUPS_UNKNOWN, + HDMI_NUPS_HORIZONTAL, + HDMI_NUPS_VERTICAL, + HDMI_NUPS_BOTH, +}; + +enum hdmi_ycc_quantization_range { + HDMI_YCC_QUANTIZATION_RANGE_LIMITED, + HDMI_YCC_QUANTIZATION_RANGE_FULL, +}; + +enum hdmi_content_type { + HDMI_CONTENT_TYPE_GRAPHICS, + HDMI_CONTENT_TYPE_PHOTO, + HDMI_CONTENT_TYPE_CINEMA, + HDMI_CONTENT_TYPE_GAME, +}; + +struct hdmi_avi_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + enum hdmi_colorspace colorspace; + enum hdmi_scan_mode scan_mode; + enum hdmi_colorimetry colorimetry; + enum hdmi_picture_aspect picture_aspect; + enum hdmi_active_aspect active_aspect; + bool itc; + enum hdmi_extended_colorimetry extended_colorimetry; + enum hdmi_quantization_range quantization_range; + enum hdmi_nups nups; + unsigned char video_code; + enum hdmi_ycc_quantization_range ycc_quantization_range; + enum hdmi_content_type content_type; + unsigned char pixel_repeat; + unsigned short top_bar; + unsigned short bottom_bar; + unsigned short left_bar; + unsigned short right_bar; +}; + +int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame); +ssize_t hdmi_avi_infoframe_pack(struct hdmi_avi_infoframe *frame, void *buffer, + size_t size); + +enum hdmi_spd_sdi { + HDMI_SPD_SDI_UNKNOWN, + HDMI_SPD_SDI_DSTB, + HDMI_SPD_SDI_DVDP, + HDMI_SPD_SDI_DVHS, + HDMI_SPD_SDI_HDDVR, + HDMI_SPD_SDI_DVC, + HDMI_SPD_SDI_DSC, + HDMI_SPD_SDI_VCD, + HDMI_SPD_SDI_GAME, + HDMI_SPD_SDI_PC, + HDMI_SPD_SDI_BD, + HDMI_SPD_SDI_SACD, + HDMI_SPD_SDI_HDDVD, + HDMI_SPD_SDI_PMP, +}; + +struct hdmi_spd_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + char vendor[8]; + char product[16]; + enum hdmi_spd_sdi sdi; +}; + +int hdmi_spd_infoframe_init(struct hdmi_spd_infoframe *frame, + const char *vendor, const char *product); +ssize_t hdmi_spd_infoframe_pack(struct hdmi_spd_infoframe *frame, void *buffer, + size_t size); + +enum hdmi_audio_coding_type { + HDMI_AUDIO_CODING_TYPE_STREAM, + HDMI_AUDIO_CODING_TYPE_PCM, + HDMI_AUDIO_CODING_TYPE_AC3, + HDMI_AUDIO_CODING_TYPE_MPEG1, + HDMI_AUDIO_CODING_TYPE_MP3, + HDMI_AUDIO_CODING_TYPE_MPEG2, + HDMI_AUDIO_CODING_TYPE_AAC_LC, + HDMI_AUDIO_CODING_TYPE_DTS, + HDMI_AUDIO_CODING_TYPE_ATRAC, + HDMI_AUDIO_CODING_TYPE_DSD, + HDMI_AUDIO_CODING_TYPE_EAC3, + HDMI_AUDIO_CODING_TYPE_DTS_HD, + HDMI_AUDIO_CODING_TYPE_MLP, + HDMI_AUDIO_CODING_TYPE_DST, + HDMI_AUDIO_CODING_TYPE_WMA_PRO, + HDMI_AUDIO_CODING_TYPE_CXT, +}; + +enum hdmi_audio_sample_size { + HDMI_AUDIO_SAMPLE_SIZE_STREAM, + HDMI_AUDIO_SAMPLE_SIZE_16, + HDMI_AUDIO_SAMPLE_SIZE_20, + HDMI_AUDIO_SAMPLE_SIZE_24, +}; + +enum hdmi_audio_sample_frequency { + HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM, + HDMI_AUDIO_SAMPLE_FREQUENCY_32000, + HDMI_AUDIO_SAMPLE_FREQUENCY_44100, + HDMI_AUDIO_SAMPLE_FREQUENCY_48000, + HDMI_AUDIO_SAMPLE_FREQUENCY_88200, + HDMI_AUDIO_SAMPLE_FREQUENCY_96000, + HDMI_AUDIO_SAMPLE_FREQUENCY_176400, + HDMI_AUDIO_SAMPLE_FREQUENCY_192000, +}; + +enum hdmi_audio_coding_type_ext { + /* Refer to Audio Coding Type (CT) field in Data Byte 1 */ + HDMI_AUDIO_CODING_TYPE_EXT_CT, + + /* + * The next three CXT values are defined in CEA-861-E only. + * They do not exist in older versions, and in CEA-861-F they are + * defined as 'Not in use'. + */ + HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC, + HDMI_AUDIO_CODING_TYPE_EXT_HE_AAC_V2, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG_SURROUND, + + /* The following CXT values are only defined in CEA-861-F. */ + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_V2, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC, + HDMI_AUDIO_CODING_TYPE_EXT_DRA, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_HE_AAC_SURROUND, + HDMI_AUDIO_CODING_TYPE_EXT_MPEG4_AAC_LC_SURROUND = 10, +}; + +struct hdmi_audio_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned char channels; + enum hdmi_audio_coding_type coding_type; + enum hdmi_audio_sample_size sample_size; + enum hdmi_audio_sample_frequency sample_frequency; + enum hdmi_audio_coding_type_ext coding_type_ext; + unsigned char channel_allocation; + unsigned char level_shift_value; + bool downmix_inhibit; + +}; + +int hdmi_audio_infoframe_init(struct hdmi_audio_infoframe *frame); +ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, + void *buffer, size_t size); + +enum hdmi_3d_structure { + HDMI_3D_STRUCTURE_INVALID = -1, + HDMI_3D_STRUCTURE_FRAME_PACKING = 0, + HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE, + HDMI_3D_STRUCTURE_LINE_ALTERNATIVE, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL, + HDMI_3D_STRUCTURE_L_DEPTH, + HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH, + HDMI_3D_STRUCTURE_TOP_AND_BOTTOM, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF = 8, +}; + + +struct hdmi_vendor_infoframe { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned int oui; + uint8_t vic; + enum hdmi_3d_structure s3d_struct; + unsigned int s3d_ext_data; +}; + +int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame); +ssize_t hdmi_vendor_infoframe_pack(struct hdmi_vendor_infoframe *frame, + void *buffer, size_t size); + +union hdmi_vendor_any_infoframe { + struct { + enum hdmi_infoframe_type type; + unsigned char version; + unsigned char length; + unsigned int oui; + } any; + struct hdmi_vendor_infoframe hdmi; +}; + +/** + * union hdmi_infoframe - overall union of all abstract infoframe representations + * @any: generic infoframe + * @avi: avi infoframe + * @spd: spd infoframe + * @vendor: union of all vendor infoframes + * @audio: audio infoframe + * + * This is used by the generic pack function. This works since all infoframes + * have the same header which also indicates which type of infoframe should be + * packed. + */ +union hdmi_infoframe { + struct hdmi_any_infoframe any; + struct hdmi_avi_infoframe avi; + struct hdmi_spd_infoframe spd; + union hdmi_vendor_any_infoframe vendor; + struct hdmi_audio_infoframe audio; +}; + +ssize_t +hdmi_infoframe_pack(union hdmi_infoframe *frame, void *buffer, size_t size); +int hdmi_infoframe_unpack(union hdmi_infoframe *frame, void *buffer); +void hdmi_infoframe_log(union hdmi_infoframe *frame); + +#endif /* _HDMI_H */ Property changes on: stable/11/sys/arm/nvidia/drm2/hdmi.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_bo.c =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_bo.c (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_bo.c (revision 332010) @@ -0,0 +1,369 @@ +/*- + * Copyright (c) 2015 Michal Meloun + * 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 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 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +static void +tegra_bo_destruct(struct tegra_bo *bo) +{ + vm_page_t m; + size_t size; + int i; + + if (bo->cdev_pager == NULL) + return; + + size = round_page(bo->gem_obj.size); + if (bo->vbase != 0) + pmap_qremove(bo->vbase, bo->npages); + + VM_OBJECT_WLOCK(bo->cdev_pager); + for (i = 0; i < bo->npages; i++) { + m = bo->m[i]; + cdev_pager_free_page(bo->cdev_pager, m); + vm_page_lock(m); + m->flags &= ~PG_FICTITIOUS; + vm_page_unwire(m, PQ_NONE); + vm_page_free(m); + vm_page_unlock(m); + } + VM_OBJECT_WUNLOCK(bo->cdev_pager); + + vm_object_deallocate(bo->cdev_pager); + if (bo->vbase != 0) + vmem_free(kmem_arena, bo->vbase, size); +} + +static void +tegra_bo_free_object(struct drm_gem_object *gem_obj) +{ + struct tegra_bo *bo; + + bo = container_of(gem_obj, struct tegra_bo, gem_obj); + drm_gem_free_mmap_offset(gem_obj); + drm_gem_object_release(gem_obj); + + tegra_bo_destruct(bo); + + free(bo->m, DRM_MEM_DRIVER); + free(bo, DRM_MEM_DRIVER); +} + +static int +tegra_bo_alloc_contig(size_t npages, u_long alignment, vm_memattr_t memattr, + vm_page_t **ret_page) +{ + vm_page_t m; + int pflags, tries, i; + vm_paddr_t low, high, boundary; + + low = 0; + high = -1UL; + boundary = 0; + pflags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_NOBUSY | + VM_ALLOC_WIRED | VM_ALLOC_ZERO; + tries = 0; +retry: + m = vm_page_alloc_contig(NULL, 0, pflags, npages, low, high, alignment, + boundary, memattr); + if (m == NULL) { + if (tries < 3) { + if (!vm_page_reclaim_contig(pflags, npages, low, high, + alignment, boundary)) + VM_WAIT; + tries++; + goto retry; + } + return (ENOMEM); + } + + for (i = 0; i < npages; i++, m++) { + if ((m->flags & PG_ZERO) == 0) + pmap_zero_page(m); + m->valid = VM_PAGE_BITS_ALL; + (*ret_page)[i] = m; + } + + return (0); +} + +/* Initialize pager and insert all object pages to it*/ +static int +tegra_bo_init_pager(struct tegra_bo *bo) +{ + vm_page_t m; + size_t size; + int i; + + size = round_page(bo->gem_obj.size); + + bo->pbase = VM_PAGE_TO_PHYS(bo->m[0]); + if (vmem_alloc(kmem_arena, size, M_WAITOK | M_BESTFIT, &bo->vbase)) + return (ENOMEM); + + VM_OBJECT_WLOCK(bo->cdev_pager); + for (i = 0; i < bo->npages; i++) { + m = bo->m[i]; + /* + * XXX This is a temporary hack. + * We need pager suitable for paging (mmap) managed + * real (non-fictitious) pages. + * - managed pages are needed for clean module unload. + * - aliasing fictitious page to real one is bad, + * pmap cannot handle this situation without issues + * It expects that + * paddr = PHYS_TO_VM_PAGE(VM_PAGE_TO_PHYS(paddr)) + * for every single page passed to pmap. + */ + m->oflags &= ~VPO_UNMANAGED; + m->flags |= PG_FICTITIOUS; + if (vm_page_insert(m, bo->cdev_pager, i) != 0) + return (EINVAL); + } + VM_OBJECT_WUNLOCK(bo->cdev_pager); + + pmap_qenter(bo->vbase, bo->m, bo->npages); + return (0); +} + +/* Allocate memory for frame buffer */ +static int +tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo) +{ + size_t size; + int rv; + + size = bo->gem_obj.size; + + bo->npages = atop(size); + bo->m = malloc(sizeof(vm_page_t *) * bo->npages, DRM_MEM_DRIVER, + M_WAITOK | M_ZERO); + + rv = tegra_bo_alloc_contig(bo->npages, PAGE_SIZE, + VM_MEMATTR_WRITE_COMBINING, &(bo->m)); + if (rv != 0) { + DRM_WARNING("Cannot allocate memory for gem object.\n"); + return (rv); + } + rv = tegra_bo_init_pager(bo); + if (rv != 0) { + DRM_WARNING("Cannot initialize gem object pager.\n"); + return (rv); + } + return (0); +} + +int +tegra_bo_create(struct drm_device *drm, size_t size, struct tegra_bo **res_bo) +{ + struct tegra_bo *bo; + int rv; + + if (size <= 0) + return (-EINVAL); + + bo = malloc(sizeof(*bo), DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + + size = round_page(size); + rv = drm_gem_object_init(drm, &bo->gem_obj, size); + if (rv != 0) { + free(bo, DRM_MEM_DRIVER); + return (rv); + } + rv = drm_gem_create_mmap_offset(&bo->gem_obj); + if (rv != 0) { + drm_gem_object_release(&bo->gem_obj); + free(bo, DRM_MEM_DRIVER); + return (rv); + } + + bo->cdev_pager = cdev_pager_allocate(&bo->gem_obj, OBJT_MGTDEVICE, + drm->driver->gem_pager_ops, size, 0, 0, NULL); + rv = tegra_bo_alloc(drm, bo); + if (rv != 0) { + tegra_bo_free_object(&bo->gem_obj); + return (rv); + } + + *res_bo = bo; + return (0); +} + + + +static int +tegra_bo_create_with_handle(struct drm_file *file, struct drm_device *drm, + size_t size, uint32_t *handle, struct tegra_bo **res_bo) +{ + int rv; + struct tegra_bo *bo; + + rv = tegra_bo_create(drm, size, &bo); + if (rv != 0) + return (rv); + + rv = drm_gem_handle_create(file, &bo->gem_obj, handle); + if (rv != 0) { + tegra_bo_free_object(&bo->gem_obj); + drm_gem_object_release(&bo->gem_obj); + return (rv); + } + + drm_gem_object_unreference_unlocked(&bo->gem_obj); + + *res_bo = bo; + return (0); +} + +static int +tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm_dev, + struct drm_mode_create_dumb *args) +{ + struct tegra_drm *drm; + struct tegra_bo *bo; + int rv; + + drm = container_of(drm_dev, struct tegra_drm, drm_dev); + + args->pitch= (args->width * args->bpp + 7) / 8; + args->pitch = roundup(args->pitch, drm->pitch_align); + args->size = args->pitch * args->height; + rv = tegra_bo_create_with_handle(file, drm_dev, args->size, + &args->handle, &bo); + + return (rv); +} + +static int +tegra_bo_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *drm_dev, uint32_t handle, uint64_t *offset) +{ + struct drm_gem_object *gem_obj; + int rv; + + DRM_LOCK(drm_dev); + gem_obj = drm_gem_object_lookup(drm_dev, file_priv, handle); + if (gem_obj == NULL) { + device_printf(drm_dev->dev, "Object not found\n"); + DRM_UNLOCK(drm_dev); + return (-EINVAL); + } + rv = drm_gem_create_mmap_offset(gem_obj); + if (rv != 0) + goto fail; + + *offset = DRM_GEM_MAPPING_OFF(gem_obj->map_list.key) | + DRM_GEM_MAPPING_KEY; + + drm_gem_object_unreference(gem_obj); + DRM_UNLOCK(drm_dev); + return (0); + +fail: + drm_gem_object_unreference(gem_obj); + DRM_UNLOCK(drm_dev); + return (rv); +} + +static int +tegra_bo_dumb_destroy(struct drm_file *file_priv, struct drm_device *drm_dev, + unsigned int handle) +{ + int rv; + + rv = drm_gem_handle_delete(file_priv, handle); + return (rv); +} + +/* + * mmap support + */ +static int +tegra_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot, + vm_page_t *mres) +{ + +#ifdef DRM_PAGER_DEBUG + DRM_DEBUG("object %p offset %jd prot %d mres %p\n", + vm_obj, (intmax_t)offset, prot, mres); +#endif + return (VM_PAGER_FAIL); + +} + +static int +tegra_gem_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred, u_short *color) +{ + + if (color != NULL) + *color = 0; + return (0); +} + +static void +tegra_gem_pager_dtor(void *handle) +{ + +} + +static struct cdev_pager_ops tegra_gem_pager_ops = { + .cdev_pg_fault = tegra_gem_pager_fault, + .cdev_pg_ctor = tegra_gem_pager_ctor, + .cdev_pg_dtor = tegra_gem_pager_dtor +}; + +/* Fill up relevant fields in drm_driver ops */ +void +tegra_bo_driver_register(struct drm_driver *drm_drv) +{ + drm_drv->gem_free_object = tegra_bo_free_object; + drm_drv->gem_pager_ops = &tegra_gem_pager_ops; + drm_drv->dumb_create = tegra_bo_dumb_create; + drm_drv->dumb_map_offset = tegra_bo_dumb_map_offset; + drm_drv->dumb_destroy = tegra_bo_dumb_destroy; +} Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_bo.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_dc.c =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_dc.c (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_dc.c (revision 332010) @@ -0,0 +1,1447 @@ +/*- + * Copyright (c) 2015 Michal Meloun + * 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 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 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tegra_drm_if.h" +#include "tegra_dc_if.h" + +#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, 4 * (_r), (_v)) +#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, 4 * (_r)) + +#define LOCK(_sc) mtx_lock(&(_sc)->mtx) +#define UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) +#define SLEEP(_sc, timeout) \ + mtx_sleep(sc, &sc->mtx, 0, "tegra_dc_wait", timeout); +#define LOCK_INIT(_sc) \ + mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_dc", MTX_DEF) +#define LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx) +#define ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED) +#define ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED) + + +#define SYNCPT_VBLANK0 26 +#define SYNCPT_VBLANK1 27 + +#define DC_MAX_PLANES 2 /* Maximum planes */ + +/* DRM Formats supported by DC */ +/* XXXX expand me */ +static uint32_t dc_plane_formats[] = { + DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_UYVY, + DRM_FORMAT_YUYV, + DRM_FORMAT_YUV420, + DRM_FORMAT_YUV422, +}; + + +/* Complete description of one window (plane) */ +struct dc_window { + /* Source (in framebuffer) rectangle, in pixels */ + u_int src_x; + u_int src_y; + u_int src_w; + u_int src_h; + + /* Destination (on display) rectangle, in pixels */ + u_int dst_x; + u_int dst_y; + u_int dst_w; + u_int dst_h; + + /* Parsed pixel format */ + u_int bits_per_pixel; + bool is_yuv; /* any YUV mode */ + bool is_yuv_planar; /* planar YUV mode */ + uint32_t color_mode; /* DC_WIN_COLOR_DEPTH */ + uint32_t swap; /* DC_WIN_BYTE_SWAP */ + uint32_t surface_kind; /* DC_WINBUF_SURFACE_KIND */ + uint32_t block_height; /* DC_WINBUF_SURFACE_KIND */ + + /* Parsed flipping, rotation is not supported for pitched modes */ + bool flip_x; /* inverted X-axis */ + bool flip_y; /* inverted Y-axis */ + bool transpose_xy; /* swap X and Y-axis */ + + /* Color planes base addresses and strides */ + bus_size_t base[3]; + uint32_t stride[3]; /* stride[2] isn't used by HW */ +}; + +struct dc_softc { + device_t dev; + struct resource *mem_res; + struct resource *irq_res; + void *irq_ih; + struct mtx mtx; + + clk_t clk_parent; + clk_t clk_dc; + hwreset_t hwreset_dc; + + int pitch_align; + + struct tegra_crtc tegra_crtc; + struct drm_pending_vblank_event *event; + struct drm_gem_object *cursor_gem; +}; + + +static struct ofw_compat_data compat_data[] = { + {"nvidia,tegra124-dc", 1}, + {NULL, 0}, +}; + +/* Convert standard drm pixel format to tegra windows parameters. */ +static int +dc_parse_drm_format(struct tegra_fb *fb, struct dc_window *win) +{ + struct tegra_bo *bo; + uint32_t cm; + uint32_t sw; + bool is_yuv, is_yuv_planar; + int nplanes, i; + + switch (fb->drm_fb.pixel_format) { + case DRM_FORMAT_XBGR8888: + sw = BYTE_SWAP(NOSWAP); + cm = WIN_COLOR_DEPTH_R8G8B8A8; + is_yuv = false; + is_yuv_planar = false; + break; + + case DRM_FORMAT_XRGB8888: + sw = BYTE_SWAP(NOSWAP); + cm = WIN_COLOR_DEPTH_B8G8R8A8; + is_yuv = false; + is_yuv_planar = false; + break; + + case DRM_FORMAT_RGB565: + sw = BYTE_SWAP(NOSWAP); + cm = WIN_COLOR_DEPTH_B5G6R5; + is_yuv = false; + is_yuv_planar = false; + break; + + case DRM_FORMAT_UYVY: + sw = BYTE_SWAP(NOSWAP); + cm = WIN_COLOR_DEPTH_YCbCr422; + is_yuv = true; + is_yuv_planar = false; + break; + + case DRM_FORMAT_YUYV: + sw = BYTE_SWAP(SWAP2); + cm = WIN_COLOR_DEPTH_YCbCr422; + is_yuv = true; + is_yuv_planar = false; + break; + + case DRM_FORMAT_YUV420: + sw = BYTE_SWAP(NOSWAP); + cm = WIN_COLOR_DEPTH_YCbCr420P; + is_yuv = true; + is_yuv_planar = true; + break; + + case DRM_FORMAT_YUV422: + sw = BYTE_SWAP(NOSWAP); + cm = WIN_COLOR_DEPTH_YCbCr422P; + is_yuv = true; + is_yuv_planar = true; + break; + + default: + /* Unsupported format */ + return (-EINVAL); + } + + /* Basic check of arguments. */ + switch (fb->rotation) { + case 0: + case 180: + break; + + case 90: /* Rotation is supported only */ + case 270: /* for block linear surfaces */ + if (!fb->block_linear) + return (-EINVAL); + break; + + default: + return (-EINVAL); + } + /* XXX Add more checks (sizes, scaling...) */ + + if (win == NULL) + return (0); + + win->surface_kind = + fb->block_linear ? SURFACE_KIND_BL_16B2: SURFACE_KIND_PITCH; + win->block_height = fb->block_height; + switch (fb->rotation) { + case 0: /* (0,0,0) */ + win->transpose_xy = false; + win->flip_x = false; + win->flip_y = false; + break; + + case 90: /* (1,0,1) */ + win->transpose_xy = true; + win->flip_x = false; + win->flip_y = true; + break; + + case 180: /* (0,1,1) */ + win->transpose_xy = false; + win->flip_x = true; + win->flip_y = true; + break; + + case 270: /* (1,1,0) */ + win->transpose_xy = true; + win->flip_x = true; + win->flip_y = false; + break; + } + win->flip_x ^= fb->flip_x; + win->flip_y ^= fb->flip_y; + + win->color_mode = cm; + win->swap = sw; + win->bits_per_pixel = fb->drm_fb.bits_per_pixel; + win->is_yuv = is_yuv; + win->is_yuv_planar = is_yuv_planar; + + nplanes = drm_format_num_planes(fb->drm_fb.pixel_format); + for (i = 0; i < nplanes; i++) { + bo = fb->planes[i]; + win->base[i] = bo->pbase + fb->drm_fb.offsets[i]; + win->stride[i] = fb->drm_fb.pitches[i]; + } + return (0); +} + +/* + * Scaling functions. + * + * It's unclear if we want/must program the fractional portion + * (aka bias) of init_dda registers, mainly when mirrored axis + * modes are used. + * For now, we use 1.0 as recommended by TRM. + */ +static inline uint32_t +dc_scaling_init(uint32_t start) +{ + + return (1 << 12); +} + +static inline uint32_t +dc_scaling_incr(uint32_t src, uint32_t dst, uint32_t maxscale) +{ + uint32_t val; + + val = (src - 1) << 12 ; /* 4.12 fixed float */ + val /= (dst - 1); + if (val > (maxscale << 12)) + val = maxscale << 12; + return val; +} + +/* ------------------------------------------------------------------- + * + * HW Access. + * + */ + +/* + * Setup pixel clock. + * Minimal frequency is pixel clock, but output is free to select + * any higher. + */ +static int +dc_setup_clk(struct dc_softc *sc, struct drm_crtc *crtc, + struct drm_display_mode *mode, uint32_t *div) +{ + uint64_t pclk, freq; + struct tegra_drm_encoder *output; + struct drm_encoder *encoder; + long rv; + + pclk = mode->clock * 1000; + + /* Find attached encoder */ + output = NULL; + list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, + head) { + if (encoder->crtc == crtc) { + output = container_of(encoder, struct tegra_drm_encoder, + encoder); + break; + } + } + if (output == NULL) + return (-ENODEV); + + if (output->setup_clock == NULL) + panic("Output have not setup_clock function.\n"); + rv = output->setup_clock(output, sc->clk_dc, pclk); + if (rv != 0) { + device_printf(sc->dev, "Cannot setup pixel clock: %llu\n", + pclk); + return (rv); + } + + rv = clk_get_freq(sc->clk_dc, &freq); + *div = (freq * 2 / pclk) - 2; + + DRM_DEBUG_KMS("frequency: %llu, DC divider: %u\n", freq, *div); + + return 0; +} + +static void +dc_setup_window(struct dc_softc *sc, unsigned int index, struct dc_window *win) +{ + uint32_t h_offset, v_offset, h_size, v_size, bpp; + uint32_t h_init_dda, v_init_dda, h_incr_dda, v_incr_dda; + uint32_t val; + +#ifdef DMR_DEBUG_WINDOW + printf("%s window: %d\n", __func__, index); + printf(" src: x: %d, y: %d, w: %d, h: %d\n", + win->src_x, win->src_y, win->src_w, win->src_h); + printf(" dst: x: %d, y: %d, w: %d, h: %d\n", + win->dst_x, win->dst_y, win->dst_w, win->dst_h); + printf(" bpp: %d, color_mode: %d, swap: %d\n", + win->bits_per_pixel, win->color_mode, win->swap); +#endif + + if (win->is_yuv) + bpp = win->is_yuv_planar ? 1 : 2; + else + bpp = (win->bits_per_pixel + 7) / 8; + + if (!win->transpose_xy) { + h_size = win->src_w * bpp; + v_size = win->src_h; + } else { + h_size = win->src_h * bpp; + v_size = win->src_w; + } + + h_offset = win->src_x * bpp;; + v_offset = win->src_y; + if (win->flip_x) { + h_offset += win->src_w * bpp - 1; + } + if (win->flip_y) + v_offset += win->src_h - 1; + + /* Adjust offsets for planar yuv modes */ + if (win->is_yuv_planar) { + h_offset &= ~1; + if (win->flip_x ) + h_offset |= 1; + v_offset &= ~1; + if (win->flip_y ) + v_offset |= 1; + } + + /* Setup scaling. */ + if (!win->transpose_xy) { + h_init_dda = dc_scaling_init(win->src_x); + v_init_dda = dc_scaling_init(win->src_y); + h_incr_dda = dc_scaling_incr(win->src_w, win->dst_w, 4); + v_incr_dda = dc_scaling_incr(win->src_h, win->dst_h, 15); + } else { + h_init_dda = dc_scaling_init(win->src_y); + v_init_dda = dc_scaling_init(win->src_x); + h_incr_dda = dc_scaling_incr(win->src_h, win->dst_h, 4); + v_incr_dda = dc_scaling_incr(win->src_w, win->dst_w, 15); + } +#ifdef DMR_DEBUG_WINDOW + printf("\n"); + printf(" bpp: %d, size: h: %d v: %d, offset: h:%d v: %d\n", + bpp, h_size, v_size, h_offset, v_offset); + printf(" init_dda: h: %d v: %d, incr_dda: h: %d v: %d\n", + h_init_dda, v_init_dda, h_incr_dda, v_incr_dda); +#endif + + LOCK(sc); + + /* Select target window */ + val = WINDOW_A_SELECT << index; + WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, val); + + /* Sizes */ + WR4(sc, DC_WIN_POSITION, WIN_POSITION(win->dst_x, win->dst_y)); + WR4(sc, DC_WIN_SIZE, WIN_SIZE(win->dst_w, win->dst_h)); + WR4(sc, DC_WIN_PRESCALED_SIZE, WIN_PRESCALED_SIZE(h_size, v_size)); + + /* DDA */ + WR4(sc, DC_WIN_DDA_INCREMENT, + WIN_DDA_INCREMENT(h_incr_dda, v_incr_dda)); + WR4(sc, DC_WIN_H_INITIAL_DDA, h_init_dda); + WR4(sc, DC_WIN_V_INITIAL_DDA, v_init_dda); + + /* Color planes base addresses and strides */ + WR4(sc, DC_WINBUF_START_ADDR, win->base[0]); + if (win->is_yuv_planar) { + WR4(sc, DC_WINBUF_START_ADDR_U, win->base[1]); + WR4(sc, DC_WINBUF_START_ADDR_V, win->base[2]); + WR4(sc, DC_WIN_LINE_STRIDE, + win->stride[1] << 16 | win->stride[0]); + } else { + WR4(sc, DC_WIN_LINE_STRIDE, win->stride[0]); + } + + /* Offsets for rotation and axis flip */ + WR4(sc, DC_WINBUF_ADDR_H_OFFSET, h_offset); + WR4(sc, DC_WINBUF_ADDR_V_OFFSET, v_offset); + + /* Color format */ + WR4(sc, DC_WIN_COLOR_DEPTH, win->color_mode); + WR4(sc, DC_WIN_BYTE_SWAP, win->swap); + + /* Tiling */ + val = win->surface_kind; + if (win->surface_kind == SURFACE_KIND_BL_16B2) + val |= SURFACE_KIND_BLOCK_HEIGHT(win->block_height); + WR4(sc, DC_WINBUF_SURFACE_KIND, val); + + /* Color space coefs for YUV modes */ + if (win->is_yuv) { + WR4(sc, DC_WINC_CSC_YOF, 0x00f0); + WR4(sc, DC_WINC_CSC_KYRGB, 0x012a); + WR4(sc, DC_WINC_CSC_KUR, 0x0000); + WR4(sc, DC_WINC_CSC_KVR, 0x0198); + WR4(sc, DC_WINC_CSC_KUG, 0x039b); + WR4(sc, DC_WINC_CSC_KVG, 0x032f); + WR4(sc, DC_WINC_CSC_KUB, 0x0204); + WR4(sc, DC_WINC_CSC_KVB, 0x0000); + } + + val = WIN_ENABLE; + if (win->is_yuv) + val |= CSC_ENABLE; + else if (win->bits_per_pixel < 24) + val |= COLOR_EXPAND; + if (win->flip_y) + val |= V_DIRECTION; + if (win->flip_x) + val |= H_DIRECTION; + if (win->transpose_xy) + val |= SCAN_COLUMN; + WR4(sc, DC_WINC_WIN_OPTIONS, val); + +#ifdef DMR_DEBUG_WINDOW + /* Set underflow debug mode -> highlight missing pixels. */ + WR4(sc, DC_WINBUF_UFLOW_CTRL, UFLOW_CTR_ENABLE); + WR4(sc, DC_WINBUF_UFLOW_DBG_PIXEL, 0xFFFF0000); +#endif + + UNLOCK(sc); +} + +/* ------------------------------------------------------------------- + * + * Plane functions. + * + */ +static int +dc_plane_update(struct drm_plane *drm_plane, struct drm_crtc *drm_crtc, + struct drm_framebuffer *drm_fb, + int crtc_x, int crtc_y, unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h) +{ + struct tegra_plane *plane; + struct tegra_crtc *crtc; + struct tegra_fb *fb; + struct dc_softc *sc; + struct dc_window win; + int rv; + + plane = container_of(drm_plane, struct tegra_plane, drm_plane); + fb = container_of(drm_fb, struct tegra_fb, drm_fb); + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + + memset(&win, 0, sizeof(win)); + win.src_x = src_x >> 16; + win.src_y = src_y >> 16; + win.src_w = src_w >> 16; + win.src_h = src_h >> 16; + win.dst_x = crtc_x; + win.dst_y = crtc_y; + win.dst_w = crtc_w; + win.dst_h = crtc_h; + + rv = dc_parse_drm_format(fb, &win); + if (rv != 0) { + DRM_WARNING("unsupported pixel format %d\n", + fb->drm_fb.pixel_format); + return (rv); + } + + dc_setup_window(sc, plane->index, &win); + + WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_UPDATE << plane->index); + WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_ACT_REQ << plane->index); + + return (0); +} + +static int +dc_plane_disable(struct drm_plane *drm_plane) +{ + struct tegra_plane *plane; + struct tegra_crtc *crtc; + struct dc_softc *sc; + uint32_t val, idx; + + if (drm_plane->crtc == NULL) + return (0); + plane = container_of(drm_plane, struct tegra_plane, drm_plane); + crtc = container_of(drm_plane->crtc, struct tegra_crtc, drm_crtc); + + sc = device_get_softc(crtc->dev); + idx = plane->index; + + LOCK(sc); + + WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT << idx); + + val = RD4(sc, DC_WINC_WIN_OPTIONS); + val &= ~WIN_ENABLE; + WR4(sc, DC_WINC_WIN_OPTIONS, val); + + UNLOCK(sc); + + WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_UPDATE << idx); + WR4(sc, DC_CMD_STATE_CONTROL, WIN_A_ACT_REQ << idx); + + return (0); +} + +static void +dc_plane_destroy(struct drm_plane *plane) +{ + + dc_plane_disable(plane); + drm_plane_cleanup(plane); + free(plane, DRM_MEM_KMS); +} + +static const struct drm_plane_funcs dc_plane_funcs = { + .update_plane = dc_plane_update, + .disable_plane = dc_plane_disable, + .destroy = dc_plane_destroy, +}; + +/* ------------------------------------------------------------------- + * + * CRTC helper functions. + * + */ +static void +dc_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + /* Empty function */ +} + +static bool +dc_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, + struct drm_display_mode *adjusted) +{ + + return (true); +} + +static int +dc_set_base(struct dc_softc *sc, int x, int y, struct tegra_fb *fb) +{ + struct dc_window win; + int rv; + + memset(&win, 0, sizeof(win)); + win.src_x = x; + win.src_y = y; + win.src_w = fb->drm_fb.width; + win.src_h = fb->drm_fb.height; + win.dst_x = x; + win.dst_y = y; + win.dst_w = fb->drm_fb.width; + win.dst_h = fb->drm_fb.height; + + rv = dc_parse_drm_format(fb, &win); + if (rv != 0) { + DRM_WARNING("unsupported pixel format %d\n", + fb->drm_fb.pixel_format); + return (rv); + } + dc_setup_window(sc, 0, &win); + + return (0); +} + +static int +dc_crtc_mode_set(struct drm_crtc *drm_crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + struct tegra_fb *fb; + struct dc_window win; + uint32_t div, h_ref_to_sync, v_ref_to_sync; + int rv; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb); + + + h_ref_to_sync = 1; + v_ref_to_sync = 1; + /* Setup timing */ + rv = dc_setup_clk(sc, drm_crtc, mode, &div); + if (rv != 0) { + device_printf(sc->dev, "Cannot set pixel clock\n"); + return (rv); + } + + /* Timing */ + WR4(sc, DC_DISP_DISP_TIMING_OPTIONS, 0); + + WR4(sc, DC_DISP_REF_TO_SYNC, + (v_ref_to_sync << 16) | + h_ref_to_sync); + + WR4(sc, DC_DISP_SYNC_WIDTH, + ((mode->vsync_end - mode->vsync_start) << 16) | + ((mode->hsync_end - mode->hsync_start) << 0)); + + WR4(sc, DC_DISP_BACK_PORCH, + ((mode->vtotal - mode->vsync_end) << 16) | + ((mode->htotal - mode->hsync_end) << 0)); + + WR4(sc, DC_DISP_FRONT_PORCH, + ((mode->vsync_start - mode->vdisplay) << 16) | + ((mode->hsync_start - mode->hdisplay) << 0)); + + WR4(sc, DC_DISP_DISP_ACTIVE, + (mode->vdisplay << 16) | mode->hdisplay); + + WR4(sc, DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT(DF1P1C)); + + WR4(sc,DC_DISP_DISP_CLOCK_CONTROL, + SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER(PCD1)); + + memset(&win, 0, sizeof(win)); + win.src_x = x; + win.src_y = y; + win.src_w = mode->hdisplay; + win.src_h = mode->vdisplay; + win.dst_x = x; + win.dst_y = y; + win.dst_w = mode->hdisplay; + win.dst_h = mode->vdisplay; + + rv = dc_parse_drm_format(fb, &win); + if (rv != 0) { + DRM_WARNING("unsupported pixel format %d\n", + drm_crtc->fb->pixel_format); + return (rv); + } + + dc_setup_window(sc, 0, &win); + + return (0); + +} + +static int +dc_crtc_mode_set_base(struct drm_crtc *drm_crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + struct tegra_fb *fb; + int rv; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb); + sc = device_get_softc(crtc->dev); + + rv = dc_set_base(sc, x, y, fb); + + /* Commit */ + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE); + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ); + return (rv); +} + + +static void +dc_crtc_prepare(struct drm_crtc *drm_crtc) +{ + + struct dc_softc *sc; + struct tegra_crtc *crtc; + uint32_t val; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + + WR4(sc, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL); + /* XXX allocate syncpoint from host1x */ + WR4(sc, DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | + (sc->tegra_crtc.nvidia_head == 0 ? SYNCPT_VBLANK0: SYNCPT_VBLANK1)); + + WR4(sc, DC_CMD_DISPLAY_POWER_CONTROL, + PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | + PW4_ENABLE | PM0_ENABLE | PM1_ENABLE); + + val = RD4(sc, DC_CMD_DISPLAY_COMMAND); + val |= DISPLAY_CTRL_MODE(CTRL_MODE_C_DISPLAY); + WR4(sc, DC_CMD_DISPLAY_COMMAND, val); + + WR4(sc, DC_CMD_INT_MASK, + WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | + WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT); + + WR4(sc, DC_CMD_INT_ENABLE, + VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | + WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT); +} + +static void +dc_crtc_commit(struct drm_crtc *drm_crtc) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + uint32_t val; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE); + + val = RD4(sc, DC_CMD_INT_MASK); + val |= FRAME_END_INT; + WR4(sc, DC_CMD_INT_MASK, val); + + val = RD4(sc, DC_CMD_INT_ENABLE); + val |= FRAME_END_INT; + WR4(sc, DC_CMD_INT_ENABLE, val); + + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ); +} + +static void +dc_crtc_load_lut(struct drm_crtc *crtc) +{ + + /* empty function */ +} + +static const struct drm_crtc_helper_funcs dc_crtc_helper_funcs = { + .dpms = dc_crtc_dpms, + .mode_fixup = dc_crtc_mode_fixup, + .mode_set = dc_crtc_mode_set, + .mode_set_base = dc_crtc_mode_set_base, + .prepare = dc_crtc_prepare, + .commit = dc_crtc_commit, + .load_lut = dc_crtc_load_lut, +}; + +static int +drm_crtc_index(struct drm_crtc *crtc) +{ + int idx; + struct drm_crtc *tmp; + + idx = 0; + list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { + if (tmp == crtc) + return (idx); + idx++; + } + panic("Cannot find CRTC"); +} + +/* ------------------------------------------------------------------- + * + * Exported functions (mainly vsync related). + * + * XXX revisit this -> convert to bus methods? + */ +int +tegra_dc_get_pipe(struct drm_crtc *drm_crtc) +{ + struct tegra_crtc *crtc; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + return (crtc->nvidia_head); +} + +void +tegra_dc_enable_vblank(struct drm_crtc *drm_crtc) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + uint32_t val; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + + LOCK(sc); + val = RD4(sc, DC_CMD_INT_MASK); + val |= VBLANK_INT; + WR4(sc, DC_CMD_INT_MASK, val); + UNLOCK(sc); +} + +void +tegra_dc_disable_vblank(struct drm_crtc *drm_crtc) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + uint32_t val; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + + LOCK(sc); + val = RD4(sc, DC_CMD_INT_MASK); + val &= ~VBLANK_INT; + WR4(sc, DC_CMD_INT_MASK, val); + UNLOCK(sc); +} + +static void +dc_finish_page_flip(struct dc_softc *sc) +{ + struct drm_crtc *drm_crtc; + struct drm_device *drm; + struct tegra_fb *fb; + struct tegra_bo *bo; + uint32_t base; + int idx; + + drm_crtc = &sc->tegra_crtc.drm_crtc; + drm = drm_crtc->dev; + fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb); + + mtx_lock(&drm->event_lock); + + if (sc->event == NULL) { + mtx_unlock(&drm->event_lock); + return; + } + + LOCK(sc); + /* Read active copy of WINBUF_START_ADDR */ + WR4(sc, DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT); + WR4(sc, DC_CMD_STATE_ACCESS, READ_MUX); + base = RD4(sc, DC_WINBUF_START_ADDR); + WR4(sc, DC_CMD_STATE_ACCESS, 0); + UNLOCK(sc); + + /* Is already active */ + bo = tegra_fb_get_plane(fb, 0); + if (base == (bo->pbase + fb->drm_fb.offsets[0])) { + idx = drm_crtc_index(drm_crtc); + drm_send_vblank_event(drm, idx, sc->event); + drm_vblank_put(drm, idx); + sc->event = NULL; + } + + mtx_unlock(&drm->event_lock); +} + + +void +tegra_dc_cancel_page_flip(struct drm_crtc *drm_crtc, struct drm_file *file) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + struct drm_device *drm; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + drm = drm_crtc->dev; + mtx_lock(&drm->event_lock); + + if ((sc->event != NULL) && (sc->event->base.file_priv == file)) { + sc->event->base.destroy(&sc->event->base); + drm_vblank_put(drm, drm_crtc_index(drm_crtc)); + sc->event = NULL; + } + mtx_unlock(&drm->event_lock); +} + +/* ------------------------------------------------------------------- + * + * CRTC functions. + * + */ +static int +dc_page_flip(struct drm_crtc *drm_crtc, struct drm_framebuffer *drm_fb, + struct drm_pending_vblank_event *event) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + struct tegra_fb *fb; + struct drm_device *drm; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + fb = container_of(drm_crtc->fb, struct tegra_fb, drm_fb); + drm = drm_crtc->dev; + + if (sc->event != NULL) + return (-EBUSY); + + if (event != NULL) { + event->pipe = sc->tegra_crtc.nvidia_head; + sc->event = event; + drm_vblank_get(drm, event->pipe); + } + + dc_set_base(sc, drm_crtc->x, drm_crtc->y, fb); + drm_crtc->fb = drm_fb; + + /* Commit */ + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE); + + return (0); +} + +static int +dc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file, + uint32_t handle, uint32_t width, uint32_t height) +{ + + struct dc_softc *sc; + struct tegra_crtc *crtc; + struct drm_gem_object *gem; + struct tegra_bo *bo; + int i; + uint32_t val, *src, *dst; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + + if (width != height) + return (-EINVAL); + + switch (width) { + case 32: + val = CURSOR_SIZE(C32x32); + break; + case 64: + val = CURSOR_SIZE(C64x64); + break; + case 128: + val = CURSOR_SIZE(C128x128); + break; + case 256: + val = CURSOR_SIZE(C256x256); + break; + default: + return (-EINVAL); + } + + bo = NULL; + gem = NULL; + if (handle != 0) { + gem = drm_gem_object_lookup(drm_crtc->dev, file, handle); + if (gem == NULL) + return (-ENOENT); + bo = container_of(gem, struct tegra_bo, gem_obj); + } + + if (sc->cursor_gem != NULL) { + drm_gem_object_unreference(sc->cursor_gem); + } + sc->cursor_gem = gem; + + if (bo != NULL) { + /* + * Copy cursor into cache and convert it from ARGB to RGBA. + * XXXX - this is broken by design - client can write to BO at + * any time. We can dedicate other window for cursor or switch + * to sw cursor in worst case. + */ + src = (uint32_t *)bo->vbase; + dst = (uint32_t *)crtc->cursor_vbase; + for (i = 0; i < width * height; i++) + dst[i] = (src[i] << 8) | (src[i] >> 24); + + val |= CURSOR_CLIP(CC_DISPLAY); + val |= CURSOR_START_ADDR(crtc->cursor_pbase); + WR4(sc, DC_DISP_CURSOR_START_ADDR, val); + + val = RD4(sc, DC_DISP_BLEND_CURSOR_CONTROL); + val &= ~CURSOR_DST_BLEND_FACTOR_SELECT(~0); + val &= ~CURSOR_SRC_BLEND_FACTOR_SELECT(~0); + val |= CURSOR_MODE_SELECT; + val |= CURSOR_DST_BLEND_FACTOR_SELECT(DST_NEG_K1_TIMES_SRC); + val |= CURSOR_SRC_BLEND_FACTOR_SELECT(SRC_BLEND_K1_TIMES_SRC); + val |= CURSOR_ALPHA(~0); + WR4(sc, DC_DISP_BLEND_CURSOR_CONTROL, val); + + val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS); + val |= CURSOR_ENABLE; + WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val); + } else { + val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS); + val &= ~CURSOR_ENABLE; + WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val); + } + + /* XXX This fixes cursor underflow issues, but why ? */ + WR4(sc, DC_DISP_CURSOR_UNDERFLOW_CTRL, CURSOR_UFLOW_CYA); + + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE | CURSOR_UPDATE ); + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | CURSOR_ACT_REQ); + return (0); +} + +static int +dc_cursor_move(struct drm_crtc *drm_crtc, int x, int y) +{ + struct dc_softc *sc; + struct tegra_crtc *crtc; + + crtc = container_of(drm_crtc, struct tegra_crtc, drm_crtc); + sc = device_get_softc(crtc->dev); + WR4(sc, DC_DISP_CURSOR_POSITION, CURSOR_POSITION(x, y)); + + WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_UPDATE); + WR4(sc, DC_CMD_STATE_CONTROL, CURSOR_ACT_REQ); + + return (0); +} + +static void +dc_destroy(struct drm_crtc *crtc) +{ + + drm_crtc_cleanup(crtc); + memset(crtc, 0, sizeof(*crtc)); +} + +static const struct drm_crtc_funcs dc_crtc_funcs = { + .page_flip = dc_page_flip, + .cursor_set = dc_cursor_set, + .cursor_move = dc_cursor_move, + .set_config = drm_crtc_helper_set_config, + .destroy = dc_destroy, +}; + +/* ------------------------------------------------------------------- + * + * Bus and infrastructure. + * + */ +static int +dc_init_planes(struct dc_softc *sc, struct tegra_drm *drm) +{ + int i, rv; + struct tegra_plane *plane; + + rv = 0; + for (i = 0; i < DC_MAX_PLANES; i++) { + plane = malloc(sizeof(*plane), DRM_MEM_KMS, M_WAITOK | M_ZERO); + plane->index = i + 1; + rv = drm_plane_init(&drm->drm_dev, &plane->drm_plane, + 1 << sc->tegra_crtc.nvidia_head, &dc_plane_funcs, + dc_plane_formats, nitems(dc_plane_formats), false); + if (rv != 0) { + free(plane, DRM_MEM_KMS); + return (rv); + } + } + return 0; +} + +static void +dc_display_enable(device_t dev, bool enable) +{ + struct dc_softc *sc; + uint32_t val; + + sc = device_get_softc(dev); + + /* Set display mode */ + val = enable ? CTRL_MODE_C_DISPLAY: CTRL_MODE_STOP; + WR4(sc, DC_CMD_DISPLAY_COMMAND, DISPLAY_CTRL_MODE(val)); + + /* and commit it*/ + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_UPDATE); + WR4(sc, DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ); +} + +static void +dc_hdmi_enable(device_t dev, bool enable) +{ + struct dc_softc *sc; + uint32_t val; + + sc = device_get_softc(dev); + + val = RD4(sc, DC_DISP_DISP_WIN_OPTIONS); + if (enable) + val |= HDMI_ENABLE; + else + val &= ~HDMI_ENABLE; + WR4(sc, DC_DISP_DISP_WIN_OPTIONS, val); + +} + +static void +dc_setup_timing(device_t dev, int h_pulse_start) +{ + struct dc_softc *sc; + + sc = device_get_softc(dev); + + /* Setup display timing */ + WR4(sc, DC_DISP_DISP_TIMING_OPTIONS, VSYNC_H_POSITION(1)); + WR4(sc, DC_DISP_DISP_COLOR_CONTROL, + DITHER_CONTROL(DITHER_DISABLE) | BASE_COLOR_SIZE(SIZE_BASE888)); + + WR4(sc, DC_DISP_DISP_SIGNAL_OPTIONS0, H_PULSE2_ENABLE); + WR4(sc, DC_DISP_H_PULSE2_CONTROL, + PULSE_CONTROL_QUAL(QUAL_VACTIVE) | PULSE_CONTROL_LAST(LAST_END_A)); + + WR4(sc, DC_DISP_H_PULSE2_POSITION_A, + PULSE_START(h_pulse_start) | PULSE_END(h_pulse_start + 8)); +} + +static void +dc_intr(void *arg) +{ + struct dc_softc *sc; + uint32_t status; + + sc = arg; + + /* Confirm interrupt */ + status = RD4(sc, DC_CMD_INT_STATUS); + WR4(sc, DC_CMD_INT_STATUS, status); + if (status & VBLANK_INT) { + drm_handle_vblank(sc->tegra_crtc.drm_crtc.dev, + sc->tegra_crtc.nvidia_head); + dc_finish_page_flip(sc); + } +} + +static int +dc_init_client(device_t dev, device_t host1x, struct tegra_drm *drm) +{ + struct dc_softc *sc; + int rv; + + sc = device_get_softc(dev); + + if (drm->pitch_align < sc->pitch_align) + drm->pitch_align = sc->pitch_align; + + drm_crtc_init(&drm->drm_dev, &sc->tegra_crtc.drm_crtc, &dc_crtc_funcs); + drm_mode_crtc_set_gamma_size(&sc->tegra_crtc.drm_crtc, 256); + drm_crtc_helper_add(&sc->tegra_crtc.drm_crtc, &dc_crtc_helper_funcs); + + rv = dc_init_planes(sc, drm); + if (rv!= 0){ + device_printf(dev, "Cannot init planes\n"); + return (rv); + } + + WR4(sc, DC_CMD_INT_TYPE, + WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | + WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT); + + WR4(sc, DC_CMD_INT_POLARITY, + WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | + WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT); + + WR4(sc, DC_CMD_INT_ENABLE, 0); + WR4(sc, DC_CMD_INT_MASK, 0); + + rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, dc_intr, sc, &sc->irq_ih); + if (rv != 0) { + device_printf(dev, "Cannot register interrupt handler\n"); + return (rv); + } + + /* allocate memory for cursor cache */ + sc->tegra_crtc.cursor_vbase = kmem_alloc_contig(kernel_arena, + 256 * 256 * 4, M_WAITOK | M_ZERO, + 0, -1UL, PAGE_SIZE, 0, VM_MEMATTR_WRITE_COMBINING); + sc->tegra_crtc.cursor_pbase = vtophys(sc->tegra_crtc.cursor_vbase); + return (0); +} + +static int +dc_exit_client(device_t dev, device_t host1x, struct tegra_drm *drm) +{ + struct dc_softc *sc; + + sc = device_get_softc(dev); + + if (sc->irq_ih != NULL) + bus_teardown_intr(dev, sc->irq_res, sc->irq_ih); + sc->irq_ih = NULL; + + return (0); +} + +static int +get_fdt_resources(struct dc_softc *sc, phandle_t node) +{ + int rv; + + rv = hwreset_get_by_ofw_name(sc->dev, 0, "dc", &sc->hwreset_dc); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'dc' reset\n"); + return (rv); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "parent", &sc->clk_parent); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'parent' clock\n"); + return (rv); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "dc", &sc->clk_dc); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'dc' clock\n"); + return (rv); + } + + rv = OF_getencprop(node, "nvidia,head", &sc->tegra_crtc.nvidia_head, + sizeof(sc->tegra_crtc.nvidia_head)); + if (rv <= 0) { + device_printf(sc->dev, + "Cannot get 'nvidia,head' property\n"); + return (rv); + } + return (0); +} + +static int +enable_fdt_resources(struct dc_softc *sc) +{ + int id, rv; + + rv = clk_set_parent_by_clk(sc->clk_dc, sc->clk_parent); + if (rv != 0) { + device_printf(sc->dev, "Cannot set parent for 'dc' clock\n"); + return (rv); + } + + id = (sc->tegra_crtc.nvidia_head == 0) ? + TEGRA_POWERGATE_DIS: TEGRA_POWERGATE_DISB; + rv = tegra_powergate_sequence_power_up(id, sc->clk_dc, sc->hwreset_dc); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable 'DIS' powergate\n"); + return (rv); + } + + return (0); +} + +static int +dc_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Tegra Display Controller"); + return (BUS_PROBE_DEFAULT); +} + +static int +dc_attach(device_t dev) +{ + struct dc_softc *sc; + phandle_t node; + int rid, rv; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->tegra_crtc.dev = dev; + + node = ofw_bus_get_node(sc->dev); + LOCK_INIT(sc); + + rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res == NULL) { + device_printf(dev, "Cannot allocate memory resources\n"); + goto fail; + } + + rid = 0; + sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); + if (sc->irq_res == NULL) { + device_printf(dev, "Cannot allocate IRQ resources\n"); + goto fail; + } + + rv = get_fdt_resources(sc, node); + if (rv != 0) { + device_printf(dev, "Cannot parse FDT resources\n"); + goto fail; + } + rv = enable_fdt_resources(sc); + if (rv != 0) { + device_printf(dev, "Cannot enable FDT resources\n"); + goto fail; + } + + /* + * Tegra124 + * - 64 for RGB modes + * - 128 for YUV planar modes + * - 256 for block linear modes + */ + sc->pitch_align = 256; + + rv = TEGRA_DRM_REGISTER_CLIENT(device_get_parent(sc->dev), sc->dev); + if (rv != 0) { + device_printf(dev, "Cannot register DRM device\n"); + goto fail; + } + + return (bus_generic_attach(dev)); + +fail: + TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev); + if (sc->irq_ih != NULL) + bus_teardown_intr(dev, sc->irq_res, sc->irq_ih); + if (sc->clk_parent != NULL) + clk_release(sc->clk_parent); + if (sc->clk_dc != NULL) + clk_release(sc->clk_dc); + if (sc->hwreset_dc != NULL) + hwreset_release(sc->hwreset_dc); + if (sc->irq_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); + if (sc->mem_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + LOCK_DESTROY(sc); + + return (ENXIO); +} + +static int +dc_detach(device_t dev) +{ + struct dc_softc *sc; + + sc = device_get_softc(dev); + + TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev); + + if (sc->irq_ih != NULL) + bus_teardown_intr(dev, sc->irq_res, sc->irq_ih); + if (sc->clk_parent != NULL) + clk_release(sc->clk_parent); + if (sc->clk_dc != NULL) + clk_release(sc->clk_dc); + if (sc->hwreset_dc != NULL) + hwreset_release(sc->hwreset_dc); + if (sc->irq_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); + if (sc->mem_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + LOCK_DESTROY(sc); + + return (bus_generic_detach(dev)); +} + +static device_method_t tegra_dc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, dc_probe), + DEVMETHOD(device_attach, dc_attach), + DEVMETHOD(device_detach, dc_detach), + + /* tegra drm interface */ + DEVMETHOD(tegra_drm_init_client, dc_init_client), + DEVMETHOD(tegra_drm_exit_client, dc_exit_client), + + /* tegra dc interface */ + DEVMETHOD(tegra_dc_display_enable, dc_display_enable), + DEVMETHOD(tegra_dc_hdmi_enable, dc_hdmi_enable), + DEVMETHOD(tegra_dc_setup_timing, dc_setup_timing), + + DEVMETHOD_END +}; + +static devclass_t tegra_dc_devclass; +DEFINE_CLASS_0(tegra_dc, tegra_dc_driver, tegra_dc_methods, + sizeof(struct dc_softc)); +DRIVER_MODULE(tegra_dc, host1x, tegra_dc_driver, tegra_dc_devclass, NULL, NULL); Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_dc.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_dc_if.m =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_dc_if.m (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_dc_if.m (revision 332010) @@ -0,0 +1,57 @@ +#- +# Copyright (c) 2015 Michal Meloun +# 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 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 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 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. +# +# $FreeBSD$ +# + +#include + +INTERFACE tegra_dc; + + +METHOD void write_4{ + device_t dev; + bus_size_t offset; + uint32_t val; +}; +METHOD uint32_t read_4{ + device_t dev; + bus_size_t offset; +}; + +METHOD void display_enable{ + device_t dev; + bool enable; +}; + +METHOD void hdmi_enable{ + device_t dev; + bool enable; +}; + +METHOD void setup_timing{ + device_t dev; + int h_pulse_start; +}; Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_dc_if.m ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_dc_reg.h =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_dc_reg.h (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_dc_reg.h (revision 332010) @@ -0,0 +1,400 @@ +/*- + * Copyright 1992-2015 Michal Meloun + * 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 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 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 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. + * + * $FreeBSD$ + */ +#ifndef _TEGRA_DC_REG_H_ +#define _TEGRA_DC_REG_H_ + +/* + * !!! WARNING !!! + * Tegra manual uses registers index (and not register addreses). + * We follow the TRM notation and index is converted to offset in + * WR4 / RD4 macros + */ + +/* --------------------------- DC CMD -------------------------------------- */ +#define DC_CMD_GENERAL_INCR_SYNCPT 0x000 +#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001 +#define SYNCPT_CNTRL_NO_STALL (1 << 8) +#define SYNCPT_CNTRL_SOFT_RESET (1 << 0) + +#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002 +#define DC_CMD_WIN_A_INCR_SYNCPT 0x008 +#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009 +#define DC_CMD_WIN_A_INCR_SYNCPT_ERROR 0x00a +#define DC_CMD_WIN_B_INCR_SYNCPT 0x010 +#define DC_CMD_WIN_B_INCR_SYNCPT_CNTRL 0x011 +#define DC_CMD_WIN_B_INCR_SYNCPT_ERROR 0x012 +#define DC_CMD_WIN_C_INCR_SYNCPT 0x018 +#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019 +#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a +#define DC_CMD_CONT_SYNCPT_VSYNC 0x028 +#define SYNCPT_VSYNC_ENABLE (1 << 8) + +#define DC_CMD_CTXSW 0x030 +#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 +#define DC_CMD_DISPLAY_COMMAND 0x032 +#define DISPLAY_CTRL_MODE(x) ((x) << 5) +#define CTRL_MODE_STOP 0 +#define CTRL_MODE_C_DISPLAY 1 +#define CTRL_MODE_NC_DISPLAY 2 + +#define DC_CMD_SIGNAL_RAISE 0x033 +#define DC_CMD_DISPLAY_POWER_CONTROL 0x036 +#define PM1_ENABLE (1 << 18) +#define PM0_ENABLE (1 << 16) +#define PW4_ENABLE (1 << 8) +#define PW3_ENABLE (1 << 6) +#define PW2_ENABLE (1 << 4) +#define PW1_ENABLE (1 << 2) +#define PW0_ENABLE (1 << 0) + +#define DC_CMD_INT_STATUS 0x037 +#define DC_CMD_INT_MASK 0x038 +#define DC_CMD_INT_ENABLE 0x039 +#define DC_CMD_INT_TYPE 0x03a +#define DC_CMD_INT_POLARITY 0x03b +#define WIN_T_UF_INT (1 << 25) +#define WIN_D_UF_INT (1 << 24) +#define HC_UF_INT (1 << 23) +#define CMU_LUT_CONFLICT_INT (1 << 22) +#define WIN_C_OF_INT (1 << 16) +#define WIN_B_OF_INT (1 << 15) +#define WIN_A_OF_INT (1 << 14) +#define SSF_INT (1 << 13) +#define MSF_INT (1 << 12) +#define WIN_C_UF_INT (1 << 10) +#define WIN_B_UF_INT (1 << 9) +#define WIN_A_UF_INT (1 << 8) +#define SPI_BUSY_INT (1 << 6) +#define V_PULSE2_INT (1 << 5) +#define V_PULSE3_INT (1 << 4) +#define HBLANK_INT (1 << 3) +#define VBLANK_INT (1 << 2) +#define FRAME_END_INT (1 << 1) + +#define DC_CMD_STATE_ACCESS 0x040 +#define WRITE_MUX (1 << 2) +#define READ_MUX (1 << 0) + +#define DC_CMD_STATE_CONTROL 0x041 +#define NC_HOST_TRIG (1 << 24) +#define CURSOR_UPDATE (1 << 15) +#define WIN_C_UPDATE (1 << 11) +#define WIN_B_UPDATE (1 << 10) +#define WIN_A_UPDATE (1 << 9) +#define WIN_UPDATE(x) (1 << (9 + (x))) +#define GENERAL_UPDATE (1 << 8) +#define CURSOR_ACT_REQ (1 << 7) +#define WIN_D_ACT_REQ (1 << 4) +#define WIN_C_ACT_REQ (1 << 3) +#define WIN_B_ACT_REQ (1 << 2) +#define WIN_A_ACT_REQ (1 << 1) +#define WIN_ACT_REQ(x) (1 << (1 + (x))) +#define GENERAL_ACT_REQ (1 << 0) + +#define DC_CMD_DISPLAY_WINDOW_HEADER 0x042 +#define WINDOW_D_SELECT (1 << 7) +#define WINDOW_C_SELECT (1 << 6) +#define WINDOW_B_SELECT (1 << 5) +#define WINDOW_A_SELECT (1 << 4) +#define WINDOW_SELECT(x) (1 << (4 + (x))) + +#define DC_CMD_REG_ACT_CONTROL 0x043 +#define DC_CMD_WIN_D_INCR_SYNCPT 0x04c +#define DC_CMD_WIN_D_INCR_SYNCPT_CNTRL 0x04d +#define DC_CMD_WIN_D_INCR_SYNCPT_ERROR 0x04e + +/* ---------------------------- DC COM ------------------------------------- */ + +/* --------------------------- DC DISP ------------------------------------- */ + +#define DC_DISP_DISP_SIGNAL_OPTIONS0 0x400 +#define M1_ENABLE (1 << 26) +#define M0_ENABLE (1 << 24) +#define V_PULSE2_ENABLE (1 << 18) +#define V_PULSE1_ENABLE (1 << 16) +#define V_PULSE0_ENABLE (1 << 14) +#define H_PULSE2_ENABLE (1 << 12) +#define H_PULSE1_ENABLE (1 << 10) +#define H_PULSE0_ENABLE (1 << 8) + +#define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401 + +#define DC_DISP_DISP_WIN_OPTIONS 0x402 +#define HDMI_ENABLE (1 << 30) +#define DSI_ENABLE (1 << 29) +#define SOR1_TIMING_CYA (1 << 27) +#define SOR1_ENABLE (1 << 26) +#define SOR_ENABLE (1 << 25) +#define CURSOR_ENABLE (1 << 16) + +#define DC_DISP_DISP_TIMING_OPTIONS 0x405 +#define VSYNC_H_POSITION(x) (((x) & 0xfff) << 0) + +#define DC_DISP_REF_TO_SYNC 0x406 +#define DC_DISP_SYNC_WIDTH 0x407 +#define DC_DISP_BACK_PORCH 0x408 +#define DC_DISP_DISP_ACTIVE 0x409 +#define DC_DISP_FRONT_PORCH 0x40a +#define DC_DISP_H_PULSE0_CONTROL 0x40b +#define DC_DISP_H_PULSE0_POSITION_A 0x40c +#define DC_DISP_H_PULSE0_POSITION_B 0x40d +#define DC_DISP_H_PULSE0_POSITION_C 0x40e +#define DC_DISP_H_PULSE0_POSITION_D 0x40f +#define DC_DISP_H_PULSE1_CONTROL 0x410 +#define DC_DISP_H_PULSE1_POSITION_A 0x411 +#define DC_DISP_H_PULSE1_POSITION_B 0x412 +#define DC_DISP_H_PULSE1_POSITION_C 0x413 +#define DC_DISP_H_PULSE1_POSITION_D 0x414 +#define DC_DISP_H_PULSE2_CONTROL 0x415 +#define DC_DISP_H_PULSE2_POSITION_A 0x416 +#define DC_DISP_H_PULSE2_POSITION_B 0x417 +#define DC_DISP_H_PULSE2_POSITION_C 0x418 +#define DC_DISP_H_PULSE2_POSITION_D 0x419 +#define DC_DISP_V_PULSE0_CONTROL 0x41a +#define DC_DISP_V_PULSE0_POSITION_A 0x41b +#define DC_DISP_V_PULSE0_POSITION_B 0x41c +#define DC_DISP_V_PULSE0_POSITION_C 0x41d +#define DC_DISP_V_PULSE1_CONTROL 0x41e +#define DC_DISP_V_PULSE1_POSITION_A 0x41f +#define DC_DISP_V_PULSE1_POSITION_B 0x420 +#define DC_DISP_V_PULSE1_POSITION_C 0x421 +#define DC_DISP_V_PULSE2_CONTROL 0x422 +#define DC_DISP_V_PULSE2_POSITION_A 0x423 +#define DC_DISP_V_PULSE3_CONTROL 0x424 +#define PULSE_CONTROL_LAST(x) (((x) & 0x7f) << 8) +#define LAST_START_A 0 +#define LAST_END_A 1 +#define LAST_START_B 2 +#define LAST_END_B 3 +#define LAST_START_C 4 +#define LAST_END_C 5 +#define LAST_START_D 6 +#define LAST_END_D 7 +#define PULSE_CONTROL_QUAL(x) (((x) & 0x3) << 8) +#define QUAL_ALWAYS 0 +#define QUAL_VACTIVE 2 +#define QUAL_VACTIVE1 3 +#define PULSE_POLARITY (1 << 4) +#define PULSE_MODE (1 << 3) + +#define DC_DISP_V_PULSE3_POSITION_A 0x425 +#define PULSE_END(x) (((x) & 0xfff) << 16) +#define PULSE_START(x) (((x) & 0xfff) << 0) + + +#define DC_DISP_DISP_CLOCK_CONTROL 0x42e +#define PIXEL_CLK_DIVIDER(x) (((x) & 0xf) << 8) +#define PCD1 0 +#define PCD1H 1 +#define PCD2 2 +#define PCD3 3 +#define PCD4 4 +#define PCD6 5 +#define PCD8 6 +#define PCD9 7 +#define PCD12 8 +#define PCD16 9 +#define PCD18 10 +#define PCD24 11 +#define PCD13 12 +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) + +#define DC_DISP_DISP_INTERFACE_CONTROL 0x42f +#define DISP_ORDER_BLUE_RED ( 1 << 9) +#define DISP_ALIGNMENT_LSB ( 1 << 8) +#define DISP_DATA_FORMAT(x) (((x) & 0xf) << 8) +#define DF1P1C 0 +#define DF1P2C24B 1 +#define DF1P2C18B 2 +#define DF1P2C16B 3 +#define DF1S 4 +#define DF2S 5 +#define DF3S 6 +#define DFSPI 7 +#define DF1P3C24B 8 +#define DF2P1C18B 9 +#define DFDUAL1P1C18B 10 + +#define DC_DISP_DISP_COLOR_CONTROL 0x430 +#define NON_BASE_COLOR (1 << 18) +#define BLANK_COLOR (1 << 17) +#define DISP_COLOR_SWAP (1 << 16) +#define ORD_DITHER_ROTATION(x) (((x) & 0x3) << 12) +#define DITHER_CONTROL(x) (((x) & 0x3) << 8) +#define DITHER_DISABLE 0 +#define DITHER_ORDERED 2 +#define DITHER_TEMPORAL 3 +#define BASE_COLOR_SIZE(x) (((x) & 0xF) << 0) +#define SIZE_BASE666 0 +#define SIZE_BASE111 1 +#define SIZE_BASE222 2 +#define SIZE_BASE333 3 +#define SIZE_BASE444 4 +#define SIZE_BASE555 5 +#define SIZE_BASE565 6 +#define SIZE_BASE332 7 +#define SIZE_BASE888 8 + +#define DC_DISP_CURSOR_START_ADDR 0x43e +#define CURSOR_CLIP(x) (((x) & 0x3) << 28) +#define CC_DISPLAY 0 +#define CC_WA 1 +#define CC_WB 2 +#define CC_WC 3 +#define CURSOR_SIZE(x) (((x) & 0x3) << 24) +#define C32x32 0 +#define C64x64 1 +#define C128x128 2 +#define C256x256 3 +#define CURSOR_START_ADDR(x) (((x) >> 10) & 0x3FFFFF) + +#define DC_DISP_CURSOR_POSITION 0x440 +#define CURSOR_POSITION(h, v) ((((h) & 0x3fff) << 0) | \ + (((v) & 0x3fff) << 16)) +#define DC_DISP_CURSOR_UNDERFLOW_CTRL 0x4eb +#define DC_DISP_BLEND_CURSOR_CONTROL 0x4f1 +#define CURSOR_MODE_SELECT (1 << 24) +#define CURSOR_DST_BLEND_FACTOR_SELECT(x) (((x) & 0x3) << 16) +#define DST_BLEND_ZERO 0 +#define DST_BLEND_K1 1 +#define DST_NEG_K1_TIMES_SRC 2 +#define CURSOR_SRC_BLEND_FACTOR_SELECT(x) (((x) & 0x3) << 8) +#define SRC_BLEND_K1 0 +#define SRC_BLEND_K1_TIMES_SRC 1 +#define CURSOR_ALPHA(x) (((x) & 0xFF) << 0) + +#define DC_DISP_CURSOR_UFLOW_DBG_PIXEL 0x4f3 +#define CURSOR_UFLOW_CYA (1 << 7) +#define CURSOR_UFLOW_CTRL_DBG_MODE (1 << 0) +/* --------------------------- DC WIN ------------------------------------- */ + +#define DC_WINC_COLOR_PALETTE 0x500 +#define DC_WINC_CSC_YOF 0x611 +#define DC_WINC_CSC_KYRGB 0x612 +#define DC_WINC_CSC_KUR 0x613 +#define DC_WINC_CSC_KVR 0x614 +#define DC_WINC_CSC_KUG 0x615 +#define DC_WINC_CSC_KVG 0x616 +#define DC_WINC_CSC_KUB 0x617 +#define DC_WINC_CSC_KVB 0x618 + +#define DC_WINC_WIN_OPTIONS 0x700 +#define H_FILTER_MODE (1U << 31) +#define WIN_ENABLE (1 << 30) +#define INTERLACE_ENABLE (1 << 23) +#define YUV_RANGE_EXPAND (1 << 22) +#define DV_ENABLE (1 << 20) +#define CSC_ENABLE (1 << 18) +#define CP_ENABLE (1 << 16) +#define V_FILTER_UV_ALIGN (1 << 14) +#define V_FILTER_OPTIMIZE (1 << 12) +#define V_FILTER_ENABLE (1 << 10) +#define H_FILTER_ENABLE (1 << 8) +#define COLOR_EXPAND (1 << 6) +#define SCAN_COLUMN (1 << 4) +#define V_DIRECTION (1 << 2) +#define H_DIRECTION (1 << 0) + +#define DC_WIN_BYTE_SWAP 0x701 +#define BYTE_SWAP(x) (((x) & 0x7) << 0) +#define NOSWAP 0 +#define SWAP2 1 +#define SWAP4 2 +#define SWAP4HW 3 +#define SWAP02 4 +#define SWAPLEFT 5 + +#define DC_WIN_COLOR_DEPTH 0x703 +#define WIN_COLOR_DEPTH_P8 3 +#define WIN_COLOR_DEPTH_B4G4R4A4 4 +#define WIN_COLOR_DEPTH_B5G5R5A 5 +#define WIN_COLOR_DEPTH_B5G6R5 6 +#define WIN_COLOR_DEPTH_AB5G5R5 7 +#define WIN_COLOR_DEPTH_B8G8R8A8 12 +#define WIN_COLOR_DEPTH_R8G8B8A8 13 +#define WIN_COLOR_DEPTH_YCbCr422 16 +#define WIN_COLOR_DEPTH_YUV422 17 +#define WIN_COLOR_DEPTH_YCbCr420P 18 +#define WIN_COLOR_DEPTH_YUV420P 19 +#define WIN_COLOR_DEPTH_YCbCr422P 20 +#define WIN_COLOR_DEPTH_YUV422P 21 +#define WIN_COLOR_DEPTH_YCbCr422R 22 +#define WIN_COLOR_DEPTH_YUV422R 23 +#define WIN_COLOR_DEPTH_YCbCr422RA 24 +#define WIN_COLOR_DEPTH_YUV422RA 25 + +#define DC_WIN_POSITION 0x704 +#define WIN_POSITION(h, v) ((((h) & 0x1fff) << 0) | \ + (((v) & 0x1fff) << 16)) + +#define DC_WIN_SIZE 0x705 +#define WIN_SIZE(h, v) ((((h) & 0x1fff) << 0) | \ + (((v) & 0x1fff) << 16)) + +#define DC_WIN_PRESCALED_SIZE 0x706 +#define WIN_PRESCALED_SIZE(h, v) ((((h) & 0x7fff) << 0) | \ + (((v) & 0x1fff) << 16)) + + +#define DC_WIN_H_INITIAL_DDA 0x707 +#define DC_WIN_V_INITIAL_DDA 0x708 +#define DC_WIN_DDA_INCREMENT 0x709 +#define WIN_DDA_INCREMENT(h, v) ((((h) & 0xffff) << 0) | \ + (((v) & 0xffff) << 16)) +#define DC_WIN_LINE_STRIDE 0x70a + +/* -------------------------- DC WINBUF ------------------------------------ */ + +#define DC_WINBUF_START_ADDR 0x800 +#define DC_WINBUF_START_ADDR_NS 0x801 +#define DC_WINBUF_START_ADDR_U 0x802 +#define DC_WINBUF_START_ADDR_U_NS 0x803 +#define DC_WINBUF_START_ADDR_V 0x804 +#define DC_WINBUF_START_ADDR_V_NS 0x805 +#define DC_WINBUF_ADDR_H_OFFSET 0x806 +#define DC_WINBUF_ADDR_H_OFFSET_NS 0x807 +#define DC_WINBUF_ADDR_V_OFFSET 0x808 +#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809 +#define DC_WINBUF_UFLOW_STATUS 0x80a +#define DC_WINBUF_SURFACE_KIND 0x80b +#define SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4) +#define SURFACE_KIND_PITCH 0 +#define SURFACE_KIND_TILED 1 +#define SURFACE_KIND_BL_16B2 2 +#define DC_WINBUF_SURFACE_WEIGHT 0x80c +#define DC_WINBUF_START_ADDR_HI 0x80d +#define DC_WINBUF_START_ADDR_HI_NS 0x80e +#define DC_WINBUF_START_ADDR_U_HI 0x80f +#define DC_WINBUF_START_ADDR_U_HI_NS 0x810 +#define DC_WINBUF_START_ADDR_V_HI 0x811 +#define DC_WINBUF_START_ADDR_V_HI_NS 0x812 +#define DC_WINBUF_UFLOW_CTRL 0x824 +#define UFLOW_CTR_ENABLE (1 << 0) +#define DC_WINBUF_UFLOW_DBG_PIXEL 0x825 + +#endif /* _TEGRA_DC_REG_H_ */ Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_dc_reg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_drm.h =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_drm.h (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_drm.h (revision 332010) @@ -0,0 +1,125 @@ +/*- + * Copyright 1992-2015 Michal Meloun + * 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 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 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 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. + * + * $FreeBSD$ + */ +#ifndef _TEGRA_DRM_H_ +#define _TEGRA_DRM_H_ + +#include + +struct tegra_bo { + struct drm_gem_object gem_obj; + /* mapped memory buffer */ + vm_paddr_t pbase; + vm_offset_t vbase; + size_t npages; + vm_page_t *m; + vm_object_t cdev_pager; +}; + +struct tegra_plane { + struct drm_plane drm_plane; + int index; /* Window index */ +}; + +struct tegra_fb { + struct drm_framebuffer drm_fb; + struct drm_fb_helper fb_helper; + struct tegra_bo **planes; /* Attached planes */ + int nplanes; + + /* Surface and display geometry */ + bool block_linear; /* Surface_kind */ + uint32_t block_height; + int rotation; /* In degrees */ + bool flip_x; /* Inverted X-axis */ + bool flip_y; /* Inverted Y-axis */ +}; + +struct tegra_crtc { + struct drm_crtc drm_crtc; + device_t dev; + int nvidia_head; + vm_paddr_t cursor_pbase; /* Cursor buffer */ + vm_offset_t cursor_vbase; +}; + +struct tegra_drm_encoder { + device_t dev; + + void *panel; /* XXX For LVDS panel */ + device_t ddc; + struct edid *edid; + + gpio_pin_t gpio_hpd; + + struct drm_encoder encoder; + struct drm_connector connector; + int (*setup_clock)(struct tegra_drm_encoder *output, + clk_t clk, uint64_t pclk); +}; + +struct tegra_drm { + struct drm_device drm_dev; + struct tegra_fb *fb; /* Prime framebuffer */ + int pitch_align; +}; + +/* tegra_drm_subr.c */ +int tegra_drm_encoder_attach(struct tegra_drm_encoder *output, phandle_t node); +int tegra_drm_encoder_init(struct tegra_drm_encoder *output, + struct tegra_drm *drm); +int tegra_drm_encoder_exit(struct tegra_drm_encoder *output, + struct tegra_drm *drm); +enum drm_connector_status tegra_drm_connector_detect( + struct drm_connector *connector, bool force); +int tegra_drm_connector_get_modes(struct drm_connector *connector); +struct drm_encoder *tegra_drm_connector_best_encoder( + struct drm_connector *connector); + +/* tegra_dc.c */ +void tegra_dc_cancel_page_flip(struct drm_crtc *drm_crtc, + struct drm_file *file); +void tegra_dc_enable_vblank(struct drm_crtc *drm_crtc); +void tegra_dc_disable_vblank(struct drm_crtc *drm_crtc); +int tegra_dc_get_pipe(struct drm_crtc *drm_crtc); + +/* tegra_fb.c */ +struct fb_info *tegra_drm_fb_getinfo(struct drm_device *drm); +struct tegra_bo *tegra_fb_get_plane(struct tegra_fb *fb, int idx); +int tegra_drm_fb_create(struct drm_device *drm, struct drm_file *file, + struct drm_mode_fb_cmd2 *cmd, struct drm_framebuffer **fb_res); +int tegra_drm_fb_init(struct drm_device *drm); +void tegra_drm_fb_destroy(struct drm_device *drm); + + +/* tegra_bo.c */ +struct tegra_bo; +int tegra_bo_create(struct drm_device *drm, size_t size, + struct tegra_bo **res_bo); +void tegra_bo_driver_register(struct drm_driver *drm_drv); + +#endif /* _TEGRA_DRM_H_ */ Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_drm.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_drm_if.m =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_drm_if.m (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_drm_if.m (revision 332010) @@ -0,0 +1,68 @@ +#- +# Copyright (c) 2015 Michal Meloun +# 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 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 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 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. +# +# $FreeBSD$ +# + + +INTERFACE tegra_drm; +HEADER { + struct tegra_drm; +}; + + +/** + * Register client to host1x + */ +METHOD int register_client{ + device_t host1x; + device_t client; +}; + +/** + * Deregister client to host1x + */ +METHOD int deregister_client{ + device_t host1x; + device_t client; +}; + +/** + * Call client init method + */ +METHOD int init_client{ + device_t client; + device_t host1x; + struct tegra_drm *drm; +}; + +/** + * Call client exit method + */ +METHOD int exit_client{ + device_t client; + device_t host1x; + struct tegra_drm *drm; +}; Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_drm_if.m ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_drm_subr.c =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_drm_subr.c (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_drm_subr.c (revision 332010) @@ -0,0 +1,177 @@ +/*- + * Copyright (c) 2015 Michal Meloun + * 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 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 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +int +tegra_drm_connector_get_modes(struct drm_connector *connector) +{ + struct tegra_drm_encoder *output; + struct edid *edid = NULL; + int rv; + + output = container_of(connector, struct tegra_drm_encoder, + connector); + + /* Panel is first */ + if (output->panel != NULL) { + /* XXX panel parsing */ + return (0); + } + + /* static EDID is second*/ + edid = output->edid; + + /* EDID from monitor is last */ + if (edid == NULL) + edid = drm_get_edid(connector, output->ddc); + + if (edid == NULL) + return (0); + + /* Process EDID */ + drm_mode_connector_update_edid_property(connector, edid); + rv = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + return (rv); +} + +struct drm_encoder * +tegra_drm_connector_best_encoder(struct drm_connector *connector) +{ + struct tegra_drm_encoder *output; + + output = container_of(connector, struct tegra_drm_encoder, + connector); + + return &(output->encoder); +} + +enum drm_connector_status +tegra_drm_connector_detect(struct drm_connector *connector, bool force) +{ + struct tegra_drm_encoder *output; + bool active; + int rv; + + output = container_of(connector, struct tegra_drm_encoder, + connector); + if (output->gpio_hpd == NULL) { + return ((output->panel != NULL) ? + connector_status_connected: + connector_status_disconnected); + } + + rv = gpio_pin_is_active(output->gpio_hpd, &active); + if (rv != 0) { + device_printf(output->dev, " GPIO read failed: %d\n", rv); + return (connector_status_unknown); + } + + return (active ? + connector_status_connected : connector_status_disconnected); +} + +int +tegra_drm_encoder_attach(struct tegra_drm_encoder *output, phandle_t node) +{ + int rv; + phandle_t ddc; + + /* XXX parse output panel here */ + + rv = OF_getencprop_alloc(node, "nvidia,edid", 1, + (void **)&output->edid); + + /* EDID exist but have invalid size */ + if ((rv >= 0) && (rv != sizeof(struct edid))) { + device_printf(output->dev, + "Malformed \"nvidia,edid\" property\n"); + if (output->edid != NULL) + free(output->edid, M_OFWPROP); + return (ENXIO); + } + + gpio_pin_get_by_ofw_property(output->dev, node, "nvidia,hpd-gpio", + &output->gpio_hpd); + ddc = 0; + OF_getencprop(node, "nvidia,ddc-i2c-bus", &ddc, sizeof(ddc)); + if (ddc > 0) + output->ddc = OF_device_from_xref(ddc); + if ((output->edid == NULL) && (output->ddc == NULL)) + return (ENXIO); + + if (output->gpio_hpd != NULL) { + output->connector.polled = +// DRM_CONNECTOR_POLL_HPD; + DRM_CONNECTOR_POLL_DISCONNECT | + DRM_CONNECTOR_POLL_CONNECT; + } + + return (0); +} + +int tegra_drm_encoder_init(struct tegra_drm_encoder *output, + struct tegra_drm *drm) +{ + + if (output->panel) { + /* attach panel */ + } + return (0); +} + +int tegra_drm_encoder_exit(struct tegra_drm_encoder *output, + struct tegra_drm *drm) +{ + + if (output->panel) { + /* detach panel */ + } + return (0); +} \ No newline at end of file Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_drm_subr.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_fb.c =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_fb.c (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_fb.c (revision 332010) @@ -0,0 +1,338 @@ +/*- + * Copyright (c) 2016 Michal Meloun + * 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 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 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +static void +fb_destroy(struct drm_framebuffer *drm_fb) +{ + struct tegra_fb *fb; + struct tegra_bo *bo; + unsigned int i; + + fb = container_of(drm_fb, struct tegra_fb, drm_fb); + for (i = 0; i < fb->nplanes; i++) { + bo = fb->planes[i]; + if (bo != NULL) + drm_gem_object_unreference_unlocked(&bo->gem_obj); + } + + drm_framebuffer_cleanup(drm_fb); + free(fb->planes, DRM_MEM_DRIVER); +} + +static int +fb_create_handle(struct drm_framebuffer *drm_fb, struct drm_file *file, + unsigned int *handle) +{ + struct tegra_fb *fb; + int rv; + + fb = container_of(drm_fb, struct tegra_fb, drm_fb); + rv = drm_gem_handle_create(file, &fb->planes[0]->gem_obj, handle); + return (rv); +} + +/* XXX Probably not needed */ +static int +fb_dirty(struct drm_framebuffer *fb, struct drm_file *file_priv, +unsigned flags, unsigned color, struct drm_clip_rect *clips, unsigned num_clips) +{ + + return (0); +} + +static const struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, + .create_handle = fb_create_handle, + .dirty = fb_dirty, +}; + +static int +fb_alloc(struct drm_device *drm, struct drm_mode_fb_cmd2 *mode_cmd, + struct tegra_bo **planes, int num_planes, struct tegra_fb **res_fb) +{ + struct tegra_fb *fb; + int i; + int rv; + + fb = malloc(sizeof(*fb), DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + fb->planes = malloc(num_planes * sizeof(*fb->planes), DRM_MEM_DRIVER, + M_WAITOK | M_ZERO); + fb->nplanes = num_planes; + + drm_helper_mode_fill_fb_struct(&fb->drm_fb, mode_cmd); + for (i = 0; i < fb->nplanes; i++) + fb->planes[i] = planes[i]; + rv = drm_framebuffer_init(drm, &fb->drm_fb, &fb_funcs); + if (rv < 0) { + device_printf(drm->dev, + "Cannot initialize frame buffer %d\n", rv); + free(fb->planes, DRM_MEM_DRIVER); + return (rv); + } + *res_fb = fb; + return (0); +} + +static int +tegra_fb_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + u_int bpp, size; + struct tegra_drm *drm; + struct tegra_fb *fb; + struct fb_info *info; + struct tegra_bo *bo; + struct drm_mode_fb_cmd2 mode_cmd; + struct drm_device *drm_dev; + int rv; + + if (helper->fb != NULL) + return (0); + + DRM_DEBUG_KMS("surface: %d x %d (bpp: %d)\n", sizes->surface_width, + sizes->surface_height, sizes->surface_bpp); + + drm_dev = helper->dev; + fb = container_of(helper, struct tegra_fb, fb_helper); + drm = container_of(drm_dev, struct tegra_drm, drm_dev); + bpp = (sizes->surface_bpp + 7) / 8; + + /* Create mode_cmd */ + memset(&mode_cmd, 0, sizeof(mode_cmd)); + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + mode_cmd.pitches[0] = roundup(sizes->surface_width * bpp, + drm->pitch_align); + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + size = mode_cmd.pitches[0] * mode_cmd.height; + + DRM_LOCK(drm_dev); + rv = tegra_bo_create(drm_dev, size, &bo); + DRM_UNLOCK(drm_dev); + if (rv != 0) + return (rv); + + info = framebuffer_alloc(); + if (info == NULL) { + device_printf(drm_dev->dev, + "Cannot allocate DRM framebuffer info.\n"); + rv = -ENOMEM; + goto err_object; + } + + rv = fb_alloc(drm_dev, &mode_cmd, &bo, 1, &fb); + if (rv != 0) { + device_printf(drm_dev->dev, + "Cannot allocate DRM framebuffer.\n"); + goto err_fb; + } + helper->fb = &fb->drm_fb; + helper->fbdev = info; + + /* Fill FB info */ + info->fb_vbase = bo->vbase; + info->fb_pbase = bo->pbase; + info->fb_size = size; + info->fb_bpp = sizes->surface_bpp; + drm_fb_helper_fill_fix(info, fb->drm_fb.pitches[0], fb->drm_fb.depth); + drm_fb_helper_fill_var(info, helper, fb->drm_fb.width, + fb->drm_fb.height); + + DRM_DEBUG_KMS("allocated %dx%d (s %dbits) fb size: %d, bo %p\n", + fb->drm_fb.width, fb->drm_fb.height, fb->drm_fb.depth, + size, bo); + return (1); +err_fb: + drm_gem_object_unreference_unlocked(&bo->gem_obj); + framebuffer_release(info); +err_object: + drm_gem_object_release(&bo->gem_obj); + return (rv); +} + +static struct drm_fb_helper_funcs fb_helper_funcs = { + .fb_probe = tegra_fb_probe, +}; + +/* + * Exported functions + */ +struct fb_info * +tegra_drm_fb_getinfo(struct drm_device *drm_dev) +{ + struct tegra_fb *fb; + struct tegra_drm *drm; + + drm = container_of(drm_dev, struct tegra_drm, drm_dev); + fb = drm->fb; + if (fb == NULL) + return (NULL); + return (fb->fb_helper.fbdev); +} + +struct tegra_bo * +tegra_fb_get_plane(struct tegra_fb *fb, int idx) +{ + + if (idx >= drm_format_num_planes(fb->drm_fb.pixel_format)) + return (NULL); + if (idx >= fb->nplanes) + return (NULL); + return (fb->planes[idx]); +} + +int +tegra_drm_fb_init(struct drm_device *drm_dev) +{ + struct tegra_fb *fb; + struct tegra_drm *drm; + int rv; + + drm = drm_dev->dev_private; + drm = container_of(drm_dev, struct tegra_drm, drm_dev); + fb = malloc(sizeof(*fb), DRM_MEM_DRIVER, M_WAITOK | M_ZERO); + drm->fb = fb; + + fb->fb_helper.funcs = &fb_helper_funcs; + rv = drm_fb_helper_init(drm_dev, &fb->fb_helper, + drm_dev->mode_config.num_crtc, drm_dev->mode_config.num_connector); + if (rv != 0) { + device_printf(drm_dev->dev, + "Cannot initialize frame buffer %d\n", rv); + return (rv); + } + + rv = drm_fb_helper_single_add_all_connectors(&fb->fb_helper); + if (rv != 0) { + device_printf(drm_dev->dev, "Cannot add all connectors: %d\n", + rv); + goto err_fini; + } + + rv = drm_fb_helper_initial_config(&fb->fb_helper, 32); + if (rv != 0) { + device_printf(drm_dev->dev, + "Cannot set initial config: %d\n", rv); + goto err_fini; + } + /* XXXX Setup initial mode for FB */ + /* drm_fb_helper_set_par(fb->fb_helper.fbdev); */ + return 0; + +err_fini: + drm_fb_helper_fini(&fb->fb_helper); + return (rv); +} + +int +tegra_drm_fb_create(struct drm_device *drm, struct drm_file *file, + struct drm_mode_fb_cmd2 *cmd, struct drm_framebuffer **fb_res) +{ + int hsub, vsub, i; + int width, height, size, bpp; + struct tegra_bo *planes[4]; + struct drm_gem_object *gem_obj; + struct tegra_fb *fb; + int rv, nplanes; + + hsub = drm_format_horz_chroma_subsampling(cmd->pixel_format); + vsub = drm_format_vert_chroma_subsampling(cmd->pixel_format); + + nplanes = drm_format_num_planes(cmd->pixel_format); + for (i = 0; i < nplanes; i++) { + width = cmd->width; + height = cmd->height; + if (i != 0) { + width /= hsub; + height /= vsub; + } + gem_obj = drm_gem_object_lookup(drm, file, cmd->handles[i]); + if (gem_obj == NULL) { + rv = -ENXIO; + goto fail; + } + + bpp = drm_format_plane_cpp(cmd->pixel_format, i); + size = (height - 1) * cmd->pitches[i] + + width * bpp + cmd->offsets[i]; + if (gem_obj->size < size) { + rv = -EINVAL; + goto fail; + } + planes[i] = container_of(gem_obj, struct tegra_bo, gem_obj); + } + + rv = fb_alloc(drm, cmd, planes, nplanes, &fb); + if (rv != 0) + goto fail; + + *fb_res = &fb->drm_fb; + return (0); + +fail: + while (i--) + drm_gem_object_unreference_unlocked(&planes[i]->gem_obj); + return (rv); +} + +void +tegra_drm_fb_destroy(struct drm_device *drm_dev) +{ + struct fb_info *info; + struct tegra_fb *fb; + struct tegra_drm *drm; + + drm = container_of(drm_dev, struct tegra_drm, drm_dev); + fb = drm->fb; + if (fb == NULL) + return; + info = fb->fb_helper.fbdev; + drm_framebuffer_remove(&fb->drm_fb); + framebuffer_release(info); + drm_fb_helper_fini(&fb->fb_helper); + drm_framebuffer_cleanup(&fb->drm_fb); + free(fb, DRM_MEM_DRIVER); + drm->fb = NULL; +} Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_fb.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_hdmi.c =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_hdmi.c (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_hdmi.c (revision 332010) @@ -0,0 +1,1326 @@ +/*- + * Copyright (c) 2015 Michal Meloun + * 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 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 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tegra_dc_if.h" +#include "tegra_drm_if.h" + +#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, 4 * (_r), (_v)) +#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, 4 * (_r)) + +/* HDA stream format verb. */ +#define AC_FMT_CHAN_GET(x) (((x) >> 0) & 0xf) +#define AC_FMT_CHAN_BITS_GET(x) (((x) >> 4) & 0x7) +#define AC_FMT_DIV_GET(x) (((x) >> 8) & 0x7) +#define AC_FMT_MUL_GET(x) (((x) >> 11) & 0x7) +#define AC_FMT_BASE_44K (1 << 14) +#define AC_FMT_TYPE_NON_PCM (1 << 15) + +#define HDMI_REKEY_DEFAULT 56 +#define HDMI_ELD_BUFFER_SIZE 96 + +#define HDMI_DC_CLOCK_MULTIPIER 2 + +struct audio_reg { + uint32_t audio_clk; + bus_size_t acr_reg; + bus_size_t nval_reg; + bus_size_t aval_reg; +}; + +static const struct audio_reg audio_regs[] = +{ + { + .audio_clk = 32000, + .acr_reg = HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW, + .nval_reg = HDMI_NV_PDISP_SOR_AUDIO_NVAL_0320, + .aval_reg = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320, + }, + { + .audio_clk = 44100, + .acr_reg = HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW, + .nval_reg = HDMI_NV_PDISP_SOR_AUDIO_NVAL_0441, + .aval_reg = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441, + }, + { + .audio_clk = 88200, + .acr_reg = HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW, + .nval_reg = HDMI_NV_PDISP_SOR_AUDIO_NVAL_0882, + .aval_reg = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882, + }, + { + .audio_clk = 176400, + .acr_reg = HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW, + .nval_reg = HDMI_NV_PDISP_SOR_AUDIO_NVAL_1764, + .aval_reg = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764, + }, + { + .audio_clk = 48000, + .acr_reg = HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW, + .nval_reg = HDMI_NV_PDISP_SOR_AUDIO_NVAL_0480, + .aval_reg = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480, + }, + { + .audio_clk = 96000, + .acr_reg = HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW, + .nval_reg = HDMI_NV_PDISP_SOR_AUDIO_NVAL_0960, + .aval_reg = HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960, + }, + { + .audio_clk = 192000, + .acr_reg = HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW, + .nval_reg = HDMI_NV_PDISP_SOR_AUDIO_NVAL_1920, + .aval_reg = HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920, + }, +}; + +struct tmds_config { + uint32_t pclk; + uint32_t pll0; + uint32_t pll1; + uint32_t drive_c; + uint32_t pe_c; + uint32_t peak_c; + uint32_t pad_ctls; +}; + +static const struct tmds_config tegra124_tmds_config[] = +{ + { /* 480p/576p / 25.2MHz/27MHz */ + .pclk = 27000000, + .pll0 = 0x01003010, + .pll1 = 0x00301B00, + .drive_c = 0x1F1F1F1F, + .pe_c = 0x00000000, + .peak_c = 0x03030303, + .pad_ctls = 0x800034BB, + }, + { /* 720p/1080i / 74.25MHz */ + .pclk = 74250000, + .pll0 = 0x01003110, + .pll1 = 0x00301500, + .drive_c = 0x2C2C2C2C, + .pe_c = 0x00000000, + .peak_c = 0x07070707, + .pad_ctls = 0x800034BB, + }, + { /* 1080p / 148.5MHz */ + .pclk = 148500000, + .pll0 = 0x01003310, + .pll1 = 0x00301500, + .drive_c = 0x33333333, + .pe_c = 0x00000000, + .peak_c = 0x0C0C0C0C, + .pad_ctls = 0x800034BB, + }, + { /* 2216p / 297MHz */ + .pclk = UINT_MAX, + .pll0 = 0x01003F10, + .pll1 = 0x00300F00, + .drive_c = 0x37373737, + .pe_c = 0x00000000, + .peak_c = 0x17171717, + .pad_ctls = 0x800036BB, + }, +}; + + +struct hdmi_softc { + device_t dev; + struct resource *mem_res; + struct resource *irq_res; + void *irq_ih; + + clk_t clk_parent; + clk_t clk_hdmi; + hwreset_t hwreset_hdmi; + regulator_t supply_hdmi; + regulator_t supply_pll; + regulator_t supply_vdd; + + uint64_t pclk; + boolean_t hdmi_mode; + + int audio_src_type; + int audio_freq; + int audio_chans; + + struct tegra_drm *drm; + struct tegra_drm_encoder output; + + const struct tmds_config *tmds_config; + int n_tmds_configs; +}; + +static struct ofw_compat_data compat_data[] = { + {"nvidia,tegra124-hdmi", 1}, + {NULL, 0}, +}; + +/* These functions have been copied from newer version of drm_edid.c */ +/* ELD Header Block */ +#define DRM_ELD_HEADER_BLOCK_SIZE 4 +#define DRM_ELD_BASELINE_ELD_LEN 2 /* in dwords! */ +static int drm_eld_size(const uint8_t *eld) +{ + return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; +} + +static int +drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, + struct drm_display_mode *mode) +{ + int rv; + + if (!frame || !mode) + return -EINVAL; + + rv = hdmi_avi_infoframe_init(frame); + if (rv < 0) + return rv; + + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + frame->pixel_repeat = 1; + + frame->video_code = drm_match_cea_mode(mode); + + frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE; +#ifdef FREEBSD_NOTYET + /* + * Populate picture aspect ratio from either + * user input (if specified) or from the CEA mode list. + */ + if (mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_4_3 || + mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_16_9) + frame->picture_aspect = mode->picture_aspect_ratio; + else if (frame->video_code > 0) + frame->picture_aspect = drm_get_cea_aspect_ratio( + frame->video_code); +#endif + + frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE; + frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN; + + return 0; +} +/* --------------------------------------------------------------------- */ + +static int +hdmi_setup_clock(struct tegra_drm_encoder *output, clk_t clk, uint64_t pclk) +{ + struct hdmi_softc *sc; + uint64_t freq; + int rv; + + sc = device_get_softc(output->dev); + + /* Disable consumers clock for while. */ + rv = clk_disable(sc->clk_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot disable 'hdmi' clock\n"); + return (rv); + } + rv = clk_disable(clk); + if (rv != 0) { + device_printf(sc->dev, "Cannot disable display clock\n"); + return (rv); + } + + /* Set frequency for Display Controller PLL. */ + freq = HDMI_DC_CLOCK_MULTIPIER * pclk; + rv = clk_set_freq(sc->clk_parent, freq, 0); + if (rv != 0) { + device_printf(output->dev, + "Cannot set display pixel frequency\n"); + return (rv); + } + + /* Reparent display controller */ + rv = clk_set_parent_by_clk(clk, sc->clk_parent); + if (rv != 0) { + device_printf(output->dev, "Cannot set parent clock\n"); + return (rv); + + } + rv = clk_set_freq(clk, freq, 0); + if (rv != 0) { + device_printf(output->dev, + "Cannot set display controller frequency\n"); + return (rv); + } + rv = clk_set_freq(sc->clk_hdmi, pclk, 0); + if (rv != 0) { + device_printf(output->dev, + "Cannot set display controller frequency\n"); + return (rv); + } + + /* And reenable consumers clock. */ + rv = clk_enable(clk); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable display clock\n"); + return (rv); + } + rv = clk_enable(sc->clk_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable 'hdmi' clock\n"); + return (rv); + } + + rv = clk_get_freq(clk, &freq); + if (rv != 0) { + device_printf(output->dev, + "Cannot get display controller frequency\n"); + return (rv); + } + + DRM_DEBUG_KMS("DC frequency: %llu\n", freq); + + return (0); +} + +/* ------------------------------------------------------------------- + * + * Infoframes. + * + */ +static void +avi_setup_infoframe(struct hdmi_softc *sc, struct drm_display_mode *mode) +{ + struct hdmi_avi_infoframe frame; + uint8_t buf[17], *hdr, *pb;; + ssize_t rv; + + rv = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); + if (rv < 0) { + device_printf(sc->dev, "Cannot setup AVI infoframe: %zd\n", rv); + return; + } + rv = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf)); + if (rv < 0) { + device_printf(sc->dev, "Cannot pack AVI infoframe: %zd\n", rv); + return; + } + hdr = buf + 0; + pb = buf + 3; + WR4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER, + (hdr[2] << 16) | (hdr[1] << 8) | (hdr[0] << 0)); + WR4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW, + (pb[3] << 24) |(pb[2] << 16) | (pb[1] << 8) | (pb[0] << 0)); + WR4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH, + (pb[6] << 16) | (pb[5] << 8) | (pb[4] << 0)); + WR4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW, + (pb[10] << 24) |(pb[9] << 16) | (pb[8] << 8) | (pb[7] << 0)); + WR4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH, + (pb[13] << 16) | (pb[12] << 8) | (pb[11] << 0)); + + WR4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL, + AVI_INFOFRAME_CTRL_ENABLE); +} + +static void +audio_setup_infoframe(struct hdmi_softc *sc) +{ + struct hdmi_audio_infoframe frame; + uint8_t buf[14], *hdr, *pb; + ssize_t rv; + + + rv = hdmi_audio_infoframe_init(&frame); + frame.channels = sc->audio_chans; + rv = hdmi_audio_infoframe_pack(&frame, buf, sizeof(buf)); + if (rv < 0) { + device_printf(sc->dev, "Cannot pack audio infoframe\n"); + return; + } + hdr = buf + 0; + pb = buf + 3; + WR4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER, + (hdr[2] << 16) | (hdr[1] << 8) | (hdr[0] << 0)); + WR4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW, + (pb[3] << 24) |(pb[2] << 16) | (pb[1] << 8) | (pb[0] << 0)); + WR4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH, + (pb[5] << 8) | (pb[4] << 0)); + + WR4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL, + AUDIO_INFOFRAME_CTRL_ENABLE); +} + +/* ------------------------------------------------------------------- + * + * Audio + * + */ +static void +init_hda_eld(struct hdmi_softc *sc) +{ + size_t size; + int i ; + uint32_t val; + + size = drm_eld_size(sc->output.connector.eld); + for (i = 0; i < HDMI_ELD_BUFFER_SIZE; i++) { + val = i << 8; + if (i < size) + val |= sc->output.connector.eld[i]; + WR4(sc, HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR, val); + } + WR4(sc,HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE, + SOR_AUDIO_HDA_PRESENSE_VALID | SOR_AUDIO_HDA_PRESENSE_PRESENT); +} + +static int +get_audio_regs(int freq, bus_size_t *acr_reg, bus_size_t *nval_reg, + bus_size_t *aval_reg) +{ + int i; + const struct audio_reg *reg; + + for (i = 0; i < nitems(audio_regs) ; i++) { + reg = audio_regs + i; + if (reg->audio_clk == freq) { + if (acr_reg != NULL) + *acr_reg = reg->acr_reg; + if (nval_reg != NULL) + *nval_reg = reg->nval_reg; + if (aval_reg != NULL) + *aval_reg = reg->aval_reg; + return (0); + } + } + return (ERANGE); +} + +#define FR_BITS 16 +#define TO_FFP(x) (((int64_t)(x)) << FR_BITS) +#define TO_INT(x) ((int)((x) >> FR_BITS)) +static int +get_hda_cts_n(uint32_t audio_freq_hz, uint32_t pixclk_freq_hz, + uint32_t *best_cts, uint32_t *best_n, uint32_t *best_a) +{ + int min_n; + int max_n; + int ideal_n; + int n; + int cts; + int aval; + int64_t err_f; + int64_t min_err_f; + int64_t cts_f; + int64_t aval_f; + int64_t half_f; /* constant 0.5 */ + bool better_n; + + /* + * All floats are in fixed I48.16 format. + * + * Ideal ACR interval is 1000 hz (1 ms); + * acceptable is 300 hz .. 1500 hz + */ + min_n = 128 * audio_freq_hz / 1500; + max_n = 128 * audio_freq_hz / 300; + ideal_n = 128 * audio_freq_hz / 1000; + min_err_f = TO_FFP(100); + half_f = TO_FFP(1) / 2; + + *best_n = 0; + *best_cts = 0; + *best_a = 0; + + for (n = min_n; n <= max_n; n++) { + cts_f = TO_FFP(pixclk_freq_hz); + cts_f *= n; + cts_f /= 128 * audio_freq_hz; + cts = TO_INT(cts_f + half_f); /* round */ + err_f = cts_f - TO_FFP(cts); + if (err_f < 0) + err_f = -err_f; + aval_f = TO_FFP(24000000); + aval_f *= n; + aval_f /= 128 * audio_freq_hz; + aval = TO_INT(aval_f); /* truncate */ + + better_n = abs(n - ideal_n) < abs((int)(*best_n) - ideal_n); + if (TO_FFP(aval) == aval_f && + (err_f < min_err_f || (err_f == min_err_f && better_n))) { + + min_err_f = err_f; + *best_n = (uint32_t)n; + *best_cts = (uint32_t)cts; + *best_a = (uint32_t)aval; + + if (err_f == 0 && n == ideal_n) + break; + } + } + return (0); +} +#undef FR_BITS +#undef TO_FFP +#undef TO_INT + +static int +audio_setup(struct hdmi_softc *sc) +{ + uint32_t val; + uint32_t audio_n; + uint32_t audio_cts; + uint32_t audio_aval; + uint64_t hdmi_freq; + bus_size_t aval_reg; + int rv; + + if (!sc->hdmi_mode) + return (ENOTSUP); + rv = get_audio_regs(sc->audio_freq, NULL, NULL, &aval_reg); + if (rv != 0) { + device_printf(sc->dev, "Unsupported audio frequency.\n"); + return (rv); + } + + rv = clk_get_freq(sc->clk_hdmi, &hdmi_freq); + if (rv != 0) { + device_printf(sc->dev, "Cannot get hdmi frequency: %d\n", rv); + return (rv); + } + + rv = get_hda_cts_n(sc->audio_freq, hdmi_freq, &audio_cts, &audio_n, + &audio_aval); + if (rv != 0) { + device_printf(sc->dev, "Cannot compute audio coefs: %d\n", rv); + return (rv); + } + + /* Audio infoframe. */ + audio_setup_infoframe(sc); + /* Setup audio source */ + WR4(sc, HDMI_NV_PDISP_SOR_AUDIO_CNTRL0, + SOR_AUDIO_CNTRL0_SOURCE_SELECT(sc->audio_src_type) | + SOR_AUDIO_CNTRL0_INJECT_NULLSMPL); + + val = RD4(sc, HDMI_NV_PDISP_SOR_AUDIO_SPARE0); + val |= SOR_AUDIO_SPARE0_HBR_ENABLE; + WR4(sc, HDMI_NV_PDISP_SOR_AUDIO_SPARE0, val); + + WR4(sc, HDMI_NV_PDISP_HDMI_ACR_CTRL, 0); + + WR4(sc, HDMI_NV_PDISP_AUDIO_N, + AUDIO_N_RESETF | + AUDIO_N_GENERATE_ALTERNATE | + AUDIO_N_VALUE(audio_n - 1)); + + WR4(sc, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH, + ACR_SUBPACK_N(audio_n) | ACR_ENABLE); + + WR4(sc, HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW, + ACR_SUBPACK_CTS(audio_cts)); + + WR4(sc, HDMI_NV_PDISP_HDMI_SPARE, + SPARE_HW_CTS | SPARE_FORCE_SW_CTS | SPARE_CTS_RESET_VAL(1)); + + val = RD4(sc, HDMI_NV_PDISP_AUDIO_N); + val &= ~AUDIO_N_RESETF; + WR4(sc, HDMI_NV_PDISP_AUDIO_N, val); + + WR4(sc, aval_reg, audio_aval); + + return (0); +} + +static void +audio_disable(struct hdmi_softc *sc) { + uint32_t val; + + /* Disable audio */ + val = RD4(sc, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); + val &= ~GENERIC_CTRL_AUDIO; + WR4(sc, HDMI_NV_PDISP_HDMI_GENERIC_CTRL, val); + + /* Disable audio infoframes */ + val = RD4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); + val &= ~AUDIO_INFOFRAME_CTRL_ENABLE; + WR4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL, val); +} + +static void +audio_enable(struct hdmi_softc *sc) { + uint32_t val; + + if (!sc->hdmi_mode) + audio_disable(sc); + + /* Enable audio infoframes */ + val = RD4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL); + val |= AUDIO_INFOFRAME_CTRL_ENABLE; + WR4(sc, HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL, val); + + /* Enable audio */ + val = RD4(sc, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); + val |= GENERIC_CTRL_AUDIO; + WR4(sc, HDMI_NV_PDISP_HDMI_GENERIC_CTRL, val); +} + +/* ------------------------------------------------------------------- + * + * HDMI. + * + */ + /* Process format change notification from HDA */ +static void +hda_intr(struct hdmi_softc *sc) +{ + uint32_t val; + int rv; + + if (!sc->hdmi_mode) + return; + + val = RD4(sc, HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH0); + if ((val & (1 << 30)) == 0) { + audio_disable(sc); + return; + } + + /* XXX Move this to any header */ + /* Keep in sync with HDA */ + sc->audio_freq = val & 0x00FFFFFF; + sc->audio_chans = (val >> 24) & 0x0f; + DRM_DEBUG_KMS("%d channel(s) at %dHz\n", sc->audio_chans, + sc->audio_freq); + + rv = audio_setup(sc); + if (rv != 0) { + audio_disable(sc); + return; + } + + audio_enable(sc); +} + +static void +tmds_init(struct hdmi_softc *sc, const struct tmds_config *tmds) +{ + + WR4(sc, HDMI_NV_PDISP_SOR_PLL0, tmds->pll0); + WR4(sc, HDMI_NV_PDISP_SOR_PLL1, tmds->pll1); + WR4(sc, HDMI_NV_PDISP_PE_CURRENT, tmds->pe_c); + WR4(sc, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT, tmds->drive_c); + WR4(sc, HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT, tmds->peak_c); + WR4(sc, HDMI_NV_PDISP_SOR_PAD_CTLS0, tmds->pad_ctls); +} + +static int +hdmi_sor_start(struct hdmi_softc *sc, struct drm_display_mode *mode) +{ + int i; + uint32_t val; + + /* Enable TMDS macro */ + val = RD4(sc, HDMI_NV_PDISP_SOR_PLL0); + val &= ~SOR_PLL0_PWR; + val &= ~SOR_PLL0_VCOPD; + val &= ~SOR_PLL0_PULLDOWN; + WR4(sc, HDMI_NV_PDISP_SOR_PLL0, val); + DELAY(10); + + val = RD4(sc, HDMI_NV_PDISP_SOR_PLL0); + val &= ~SOR_PLL0_PDBG; + WR4(sc, HDMI_NV_PDISP_SOR_PLL0, val); + + WR4(sc, HDMI_NV_PDISP_SOR_PWR, SOR_PWR_SETTING_NEW); + WR4(sc, HDMI_NV_PDISP_SOR_PWR, 0); + + /* Wait until SOR is ready */ + for (i = 1000; i > 0; i--) { + val = RD4(sc, HDMI_NV_PDISP_SOR_PWR); + if ((val & SOR_PWR_SETTING_NEW) == 0) + break; + DELAY(10); + } + if (i <= 0) { + device_printf(sc->dev, "Timeouted while enabling SOR power.\n"); + return (ETIMEDOUT); + } + + val = SOR_STATE2_ASY_OWNER(ASY_OWNER_HEAD0) | + SOR_STATE2_ASY_SUBOWNER(SUBOWNER_BOTH) | + SOR_STATE2_ASY_CRCMODE(ASY_CRCMODE_COMPLETE) | + SOR_STATE2_ASY_PROTOCOL(ASY_PROTOCOL_SINGLE_TMDS_A); + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + val |= SOR_STATE2_ASY_HSYNCPOL_NEG; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + val |= SOR_STATE2_ASY_VSYNCPOL_NEG; + WR4(sc, HDMI_NV_PDISP_SOR_STATE2, val); + + WR4(sc, HDMI_NV_PDISP_SOR_STATE1, SOR_STATE1_ASY_ORMODE_NORMAL | + SOR_STATE1_ASY_HEAD_OPMODE(ASY_HEAD_OPMODE_AWAKE)); + + WR4(sc, HDMI_NV_PDISP_SOR_STATE0, 0); + WR4(sc, HDMI_NV_PDISP_SOR_STATE0, SOR_STATE0_UPDATE); + + val = RD4(sc, HDMI_NV_PDISP_SOR_STATE1); + val |= SOR_STATE1_ATTACHED; + WR4(sc, HDMI_NV_PDISP_SOR_STATE1, val); + + WR4(sc, HDMI_NV_PDISP_SOR_STATE0, 0); + + return 0; +} + +static int +hdmi_disable(struct hdmi_softc *sc) +{ + struct tegra_crtc *crtc; + device_t dc; + uint32_t val; + + dc = NULL; + if (sc->output.encoder.crtc != NULL) { + crtc = container_of(sc->output.encoder.crtc, struct tegra_crtc, + drm_crtc); + dc = crtc->dev; + } + + if (dc != NULL) { + TEGRA_DC_HDMI_ENABLE(dc, false); + TEGRA_DC_DISPLAY_ENABLE(dc, false); + } + audio_disable(sc); + val = RD4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL); + val &= ~AVI_INFOFRAME_CTRL_ENABLE; + WR4(sc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL, val); + + /* Disable interrupts */ + WR4(sc, HDMI_NV_PDISP_INT_ENABLE, 0); + WR4(sc, HDMI_NV_PDISP_INT_MASK, 0); + + return (0); +} + +static int +hdmi_enable(struct hdmi_softc *sc) +{ + uint64_t freq; + struct drm_display_mode *mode; + struct tegra_crtc *crtc; + uint32_t val, h_sync_width, h_back_porch, h_front_porch, h_pulse_start; + uint32_t h_max_ac_packet, div8_2; + device_t dc; + int i, rv; + + mode = &sc->output.encoder.crtc->mode; + crtc = container_of(sc->output.encoder.crtc, struct tegra_crtc, + drm_crtc); + dc = crtc->dev; + + /* Compute all timings first. */ + sc->pclk = mode->clock * 1000; + h_sync_width = mode->hsync_end - mode->hsync_start; + h_back_porch = mode->htotal - mode->hsync_end; + h_front_porch = mode->hsync_start - mode->hdisplay; + h_pulse_start = 1 + h_sync_width + h_back_porch - 10; + h_max_ac_packet = (h_sync_width + h_back_porch + h_front_porch - + HDMI_REKEY_DEFAULT - 18) / 32; + + /* Check if HDMI device is connected and detected. */ + if (sc->output.connector.edid_blob_ptr == NULL) { + sc->hdmi_mode = false; + } else { + sc->hdmi_mode = drm_detect_hdmi_monitor( + (struct edid *)sc->output.connector.edid_blob_ptr->data); + } + + /* Get exact HDMI pixel frequency. */ + rv = clk_get_freq(sc->clk_hdmi, &freq); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'hdmi' clock frequency\n"); + return (rv); + } + DRM_DEBUG_KMS("HDMI frequency: %llu Hz\n", freq); + + /* Wakeup SOR power */ + val = RD4(sc, HDMI_NV_PDISP_SOR_PLL0); + val &= ~SOR_PLL0_PDBG; + WR4(sc, HDMI_NV_PDISP_SOR_PLL0, val); + DELAY(10); + + val = RD4(sc, HDMI_NV_PDISP_SOR_PLL0); + val &= ~SOR_PLL0_PWR; + WR4(sc, HDMI_NV_PDISP_SOR_PLL0, val); + + /* Setup timings */ + TEGRA_DC_SETUP_TIMING(dc, h_pulse_start); + WR4(sc, HDMI_NV_PDISP_HDMI_VSYNC_WINDOW, + VSYNC_WINDOW_START(0x200) | VSYNC_WINDOW_END(0x210) | + VSYNC_WINDOW_ENABLE); + + /* Setup video source and adjust video range */ + val = 0; + if (crtc->nvidia_head != 0) + HDMI_SRC_DISPLAYB; + if ((mode->hdisplay != 640) || (mode->vdisplay != 480)) + val |= ARM_VIDEO_RANGE_LIMITED; + WR4(sc, HDMI_NV_PDISP_INPUT_CONTROL, val); + + /* Program SOR reference clock - it uses 8.2 fractional divisor */ + div8_2 = (freq * 4) / 1000000; + val = SOR_REFCLK_DIV_INT(div8_2 >> 2) | SOR_REFCLK_DIV_FRAC(div8_2); + WR4(sc, HDMI_NV_PDISP_SOR_REFCLK, val); + + /* Setup audio */ + if (sc->hdmi_mode) { + rv = audio_setup(sc); + if (rv != 0) + sc->hdmi_mode = false; + } + + /* Init HDA ELD */ + init_hda_eld(sc); + val = HDMI_CTRL_REKEY(HDMI_REKEY_DEFAULT); + val |= HDMI_CTRL_MAX_AC_PACKET(h_max_ac_packet); + if (sc->hdmi_mode) + val |= HDMI_CTRL_ENABLE; + WR4(sc, HDMI_NV_PDISP_HDMI_CTRL, val); + + /* Setup TMDS */ + for (i = 0; i < sc->n_tmds_configs; i++) { + if (sc->pclk <= sc->tmds_config[i].pclk) { + tmds_init(sc, sc->tmds_config + i); + break; + } + } + + /* Program sequencer. */ + WR4(sc, HDMI_NV_PDISP_SOR_SEQ_CTL, + SOR_SEQ_PU_PC(0) | SOR_SEQ_PU_PC_ALT(0) | + SOR_SEQ_PD_PC(8) | SOR_SEQ_PD_PC_ALT(8)); + + val = SOR_SEQ_INST_WAIT_TIME(1) | + SOR_SEQ_INST_WAIT_UNITS(WAIT_UNITS_VSYNC) | + SOR_SEQ_INST_HALT | + SOR_SEQ_INST_DRIVE_PWM_OUT_LO; + WR4(sc, HDMI_NV_PDISP_SOR_SEQ_INST(0), val); + WR4(sc, HDMI_NV_PDISP_SOR_SEQ_INST(8), val); + + val = RD4(sc,HDMI_NV_PDISP_SOR_CSTM); + val &= ~SOR_CSTM_LVDS_ENABLE; + val &= ~SOR_CSTM_ROTCLK(~0); + val |= SOR_CSTM_ROTCLK(2); + val &= ~SOR_CSTM_MODE(~0); + val |= SOR_CSTM_MODE(CSTM_MODE_TMDS); + val |= SOR_CSTM_PLLDIV; + WR4(sc, HDMI_NV_PDISP_SOR_CSTM, val); + + TEGRA_DC_DISPLAY_ENABLE(dc, false); + + rv = hdmi_sor_start(sc, mode); + if (rv != 0) + return (rv); + + TEGRA_DC_HDMI_ENABLE(dc, true); + TEGRA_DC_DISPLAY_ENABLE(dc, true); + + /* Enable HDA codec interrupt */ + WR4(sc, HDMI_NV_PDISP_INT_MASK, INT_CODEC_SCRATCH0); + WR4(sc, HDMI_NV_PDISP_INT_ENABLE, INT_CODEC_SCRATCH0); + + if (sc->hdmi_mode) { + avi_setup_infoframe(sc, mode); + audio_enable(sc); + } + + return (0); +} + +/* ------------------------------------------------------------------- + * + * DRM Interface. + * + */ +static enum drm_mode_status +hdmi_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct tegra_drm_encoder *output; + struct hdmi_softc *sc; + int rv; + uint64_t freq; + + output = container_of(connector, struct tegra_drm_encoder, + connector); + sc = device_get_softc(output->dev); + + freq = HDMI_DC_CLOCK_MULTIPIER * mode->clock * 1000; + rv = clk_test_freq(sc->clk_parent, freq, 0); + DRM_DEBUG_KMS("Test HDMI frequency: %u kHz, rv: %d\n", mode->clock, rv); + if (rv != 0) + return (MODE_NOCLOCK); + + return (MODE_OK); +} + + +static const struct drm_connector_helper_funcs hdmi_connector_helper_funcs = { + .get_modes = tegra_drm_connector_get_modes, + .mode_valid = hdmi_connector_mode_valid, + .best_encoder = tegra_drm_connector_best_encoder, +}; + +static const struct drm_connector_funcs hdmi_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = tegra_drm_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, +}; + +static const struct drm_encoder_funcs hdmi_encoder_funcs = { + .destroy = drm_encoder_cleanup, +}; + +static void +hdmi_encoder_dpms(struct drm_encoder *encoder, int mode) +{ + + /* Empty function. */ +} + +static bool +hdmi_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted) +{ + + return (true); +} + +static void +hdmi_encoder_prepare(struct drm_encoder *encoder) +{ + + /* Empty function. */ +} + +static void +hdmi_encoder_commit(struct drm_encoder *encoder) +{ + + /* Empty function. */ +} + +static void +hdmi_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, struct drm_display_mode *adjusted) +{ + struct tegra_drm_encoder *output; + struct hdmi_softc *sc; + int rv; + + output = container_of(encoder, struct tegra_drm_encoder, encoder); + sc = device_get_softc(output->dev); + rv = hdmi_enable(sc); + if (rv != 0) + device_printf(sc->dev, "Cannot enable HDMI port\n"); + +} + +static void +hdmi_encoder_disable(struct drm_encoder *encoder) +{ + struct tegra_drm_encoder *output; + struct hdmi_softc *sc; + int rv; + + output = container_of(encoder, struct tegra_drm_encoder, encoder); + sc = device_get_softc(output->dev); + if (sc == NULL) + return; + rv = hdmi_disable(sc); + if (rv != 0) + device_printf(sc->dev, "Cannot disable HDMI port\n"); +} + +static const struct drm_encoder_helper_funcs hdmi_encoder_helper_funcs = { + .dpms = hdmi_encoder_dpms, + .mode_fixup = hdmi_encoder_mode_fixup, + .prepare = hdmi_encoder_prepare, + .commit = hdmi_encoder_commit, + .mode_set = hdmi_encoder_mode_set, + .disable = hdmi_encoder_disable, +}; + +/* ------------------------------------------------------------------- + * + * Bus and infrastructure. + * + */ +static int +hdmi_init_client(device_t dev, device_t host1x, struct tegra_drm *drm) +{ + struct hdmi_softc *sc; + phandle_t node; + int rv; + + sc = device_get_softc(dev); + node = ofw_bus_get_node(sc->dev); + sc->drm = drm; + sc->output.setup_clock = &hdmi_setup_clock; + + rv = tegra_drm_encoder_attach(&sc->output, node); + if (rv != 0) { + device_printf(dev, "Cannot attach output connector\n"); + return(ENXIO); + } + + /* Connect this encoder + connector to DRM. */ + drm_connector_init(&drm->drm_dev, &sc->output.connector, + &hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); + + drm_connector_helper_add(&sc->output.connector, + &hdmi_connector_helper_funcs); + + sc->output.connector.dpms = DRM_MODE_DPMS_OFF; + + drm_encoder_init(&drm->drm_dev, &sc->output.encoder, + &hdmi_encoder_funcs, DRM_MODE_ENCODER_TMDS); + + drm_encoder_helper_add(&sc->output.encoder, &hdmi_encoder_helper_funcs); + + drm_mode_connector_attach_encoder(&sc->output.connector, + &sc->output.encoder); + + rv = tegra_drm_encoder_init(&sc->output, drm); + if (rv < 0) { + device_printf(sc->dev, "Unable to init HDMI output\n"); + return (rv); + } + sc->output.encoder.possible_crtcs = 0x3; + return (0); +} + +static int +hdmi_exit_client(device_t dev, device_t host1x, struct tegra_drm *drm) +{ + struct hdmi_softc *sc; + + sc = device_get_softc(dev); + tegra_drm_encoder_exit(&sc->output, drm); + return (0); +} + +static int +get_fdt_resources(struct hdmi_softc *sc, phandle_t node) +{ + int rv; + + rv = regulator_get_by_ofw_property(sc->dev, 0, "hdmi-supply", + &sc->supply_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'hdmi' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev,0, "pll-supply", + &sc->supply_pll); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'pll' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, "vdd-supply", + &sc->supply_vdd); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'vdd' regulator\n"); + return (ENXIO); + } + + rv = hwreset_get_by_ofw_name(sc->dev, 0, "hdmi", &sc->hwreset_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'hdmi' reset\n"); + return (ENXIO); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "parent", &sc->clk_parent); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'parent' clock\n"); + return (ENXIO); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "hdmi", &sc->clk_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'hdmi' clock\n"); + return (ENXIO); + } + + return (0); +} + +static int +enable_fdt_resources(struct hdmi_softc *sc) +{ + int rv; + + + rv = clk_set_parent_by_clk(sc->clk_hdmi, sc->clk_parent); + if (rv != 0) { + device_printf(sc->dev, + "Cannot set parent for 'hdmi' clock\n"); + return (rv); + } + + /* 594 MHz is arbitrarily selected value */ + rv = clk_set_freq(sc->clk_parent, 594000000, 0); + if (rv != 0) { + device_printf(sc->dev, + "Cannot set frequency for 'hdmi' parent clock\n"); + return (rv); + } + rv = clk_set_freq(sc->clk_hdmi, 594000000 / 4, 0); + if (rv != 0) { + device_printf(sc->dev, + "Cannot set frequency for 'hdmi' parent clock\n"); + return (rv); + } + + rv = regulator_enable(sc->supply_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable 'hdmi' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_pll); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable 'pll' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_vdd); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable 'vdd' regulator\n"); + return (rv); + } + + rv = clk_enable(sc->clk_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable 'hdmi' clock\n"); + return (rv); + } + + rv = hwreset_deassert(sc->hwreset_hdmi); + if (rv != 0) { + device_printf(sc->dev, "Cannot unreset 'hdmi' reset\n"); + return (rv); + } + return (0); +} + +static void +hdmi_intr(void *arg) +{ + struct hdmi_softc *sc; + uint32_t status; + + sc = arg; + + /* Confirm interrupt */ + status = RD4(sc, HDMI_NV_PDISP_INT_STATUS); + WR4(sc, HDMI_NV_PDISP_INT_STATUS, status); + + /* process audio verb from HDA */ + if (status & INT_CODEC_SCRATCH0) + hda_intr(sc); +} + +static int +hdmi_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Tegra HDMI"); + return (BUS_PROBE_DEFAULT); +} + +static int +hdmi_attach(device_t dev) +{ + struct hdmi_softc *sc; + phandle_t node; + int rid, rv; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->output.dev = sc->dev; + node = ofw_bus_get_node(sc->dev); + + sc->audio_src_type = SOURCE_SELECT_AUTO; + sc->audio_freq = 44100; + sc->audio_chans = 2; + sc->hdmi_mode = false; + + sc->tmds_config = tegra124_tmds_config; + sc->n_tmds_configs = nitems(tegra124_tmds_config); + + rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res == NULL) { + device_printf(dev, "Cannot allocate memory resources\n"); + goto fail; + } + + rid = 0; + sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); + if (sc->irq_res == NULL) { + device_printf(dev, "Cannot allocate IRQ resources\n"); + goto fail; + } + + rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, hdmi_intr, sc, &sc->irq_ih); + if (rv != 0) { + device_printf(dev, + "WARNING: unable to register interrupt handler\n"); + goto fail; + } + + rv = get_fdt_resources(sc, node); + if (rv != 0) { + device_printf(dev, "Cannot parse FDT resources\n"); + goto fail; + } + rv = enable_fdt_resources(sc); + if (rv != 0) { + device_printf(dev, "Cannot enable FDT resources\n"); + goto fail; + } + + rv = TEGRA_DRM_REGISTER_CLIENT(device_get_parent(sc->dev), sc->dev); + if (rv != 0) { + device_printf(dev, "Cannot register DRM device\n"); + goto fail; + } + return (bus_generic_attach(dev)); + +fail: + TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev); + + if (sc->irq_ih != NULL) + bus_teardown_intr(dev, sc->irq_res, sc->irq_ih); + if (sc->clk_parent != NULL) + clk_release(sc->clk_parent); + if (sc->clk_hdmi != NULL) + clk_release(sc->clk_hdmi); + if (sc->hwreset_hdmi != NULL) + hwreset_release(sc->hwreset_hdmi); + if (sc->supply_hdmi != NULL) + regulator_release(sc->supply_hdmi); + if (sc->supply_pll != NULL) + regulator_release(sc->supply_pll); + if (sc->supply_vdd != NULL) + regulator_release(sc->supply_vdd); + if (sc->irq_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); + if (sc->mem_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + return (ENXIO); +} + +static int +hdmi_detach(device_t dev) +{ + struct hdmi_softc *sc; + sc = device_get_softc(dev); + + TEGRA_DRM_DEREGISTER_CLIENT(device_get_parent(sc->dev), sc->dev); + + if (sc->irq_ih != NULL) + bus_teardown_intr(dev, sc->irq_res, sc->irq_ih); + if (sc->clk_parent != NULL) + clk_release(sc->clk_parent); + if (sc->clk_hdmi != NULL) + clk_release(sc->clk_hdmi); + if (sc->hwreset_hdmi != NULL) + hwreset_release(sc->hwreset_hdmi); + if (sc->supply_hdmi != NULL) + regulator_release(sc->supply_hdmi); + if (sc->supply_pll != NULL) + regulator_release(sc->supply_pll); + if (sc->supply_vdd != NULL) + regulator_release(sc->supply_vdd); + if (sc->irq_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); + if (sc->mem_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + return (bus_generic_detach(dev)); +} + +static device_method_t tegra_hdmi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, hdmi_probe), + DEVMETHOD(device_attach, hdmi_attach), + DEVMETHOD(device_detach, hdmi_detach), + + /* tegra drm interface */ + DEVMETHOD(tegra_drm_init_client, hdmi_init_client), + DEVMETHOD(tegra_drm_exit_client, hdmi_exit_client), + + DEVMETHOD_END +}; + +static devclass_t tegra_hdmi_devclass; +DEFINE_CLASS_0(tegra_hdmi, tegra_hdmi_driver, tegra_hdmi_methods, + sizeof(struct hdmi_softc)); +DRIVER_MODULE(tegra_hdmi, host1x, tegra_hdmi_driver, +tegra_hdmi_devclass, 0, 0); Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_hdmi.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_hdmi_reg.h =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_hdmi_reg.h (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_hdmi_reg.h (revision 332010) @@ -0,0 +1,285 @@ +/*- + * Copyright 1992-2016 Michal Meloun + * 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 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 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 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. + * + * $FreeBSD$ + */ +#ifndef _TEGRA_HDMI_REG_H_ +#define _TEGRA_HDMI_REG_H_ + +/* + * !!! WARNING !!! + * Tegra manual uses registers index (and not register addreses). + * We follow the TRM notation and index is converted to offset in + * WR4 / RD4 macros + */ +#define HDMI_NV_PDISP_SOR_STATE0 0x001 +#define SOR_STATE0_UPDATE (1 << 0) + +#define HDMI_NV_PDISP_SOR_STATE1 0x002 +#define SOR_STATE1_ATTACHED (1 << 3) +#define SOR_STATE1_ASY_ORMODE_NORMAL (1 << 2) +#define SOR_STATE1_ASY_HEAD_OPMODE(x) (((x) & 0x3) << 0) +#define ASY_HEAD_OPMODE_SLEEP 0 +#define ASY_HEAD_OPMODE_SNOOZE 1 +#define ASY_HEAD_OPMODE_AWAKE 2 + +#define HDMI_NV_PDISP_SOR_STATE2 0x003 +#define SOR_STATE2_ASY_DEPOL_NEG (1 << 14) +#define SOR_STATE2_ASY_VSYNCPOL_NEG (1 << 13) +#define SOR_STATE2_ASY_HSYNCPOL_NEG (1 << 12) +#define SOR_STATE2_ASY_PROTOCOL(x) (((x) & 0xf) << 8) +#define ASY_PROTOCOL_SINGLE_TMDS_A 1 +#define ASY_PROTOCOL_CUSTOM 15 +#define SOR_STATE2_ASY_CRCMODE(x) (((x) & 0x3) << 6) +#define ASY_CRCMODE_ACTIVE 0 +#define ASY_CRCMODE_COMPLETE 1 +#define ASY_CRCMODE_NON_ACTIVE 2 +#define SOR_STATE2_ASY_SUBOWNER(x) (((x) & 0x3) << 4) +#define ASY_SUBOWNER_NONE 0 +#define ASY_SUBOWNER_SUBHEAD0 1 +#define ASY_SUBOWNER_SUBHEAD1 2 +#define SUBOWNER_BOTH 3 +#define SOR_STATE2_ASY_OWNER(x) (((x) & 0x3) << 0) +#define ASY_OWNER_NONE 0 +#define ASY_OWNER_HEAD0 1 + +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_CTRL 0x01e +#define AUDIO_INFOFRAME_CTRL_ENABLE (1 << 0) +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_STATUS 0x01f +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_HEADER 0x020 +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_LOW 0x021 +#define HDMI_NV_PDISP_HDMI_AUDIO_INFOFRAME_SUBPACK0_HIGH 0x022 +#define INFOFRAME_HEADER_LEN(x) (((x) & 0x0f) << 16) +#define INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) << 8) +#define INFOFRAME_HEADER_TYPE(x) (((x) & 0xff) << 0) + +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_CTRL 0x023 +#define AVI_INFOFRAME_CTRL_ENABLE (1 << 0) +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_STATUS 0x024 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER 0x025 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_LOW 0x026 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK0_HIGH 0x027 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_LOW 0x028 +#define HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_SUBPACK1_HIGH 0x029 + +#define HDMI_NV_PDISP_HDMI_GENERIC_CTRL 0x02a +#define GENERIC_CTRL_AUDIO (1 << 16) +#define GENERIC_CTRL_HBLANK (1 << 12) +#define GENERIC_CTRL_SINGLE (1 << 8) +#define GENERIC_CTRL_OTHER (1 << 4) +#define GENERIC_CTRL_ENABLE (1 << 0) +#define HDMI_NV_PDISP_HDMI_GENERIC_STATUS 0x02b +#define HDMI_NV_PDISP_HDMI_GENERIC_HEADER 0x02c +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_LOW 0x02d +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK0_HIGH 0x02e +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_LOW 0x02f +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK1_HIGH 0x030 +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_LOW 0x031 +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK2_HIGH 0x032 +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_LOW 0x033 +#define HDMI_NV_PDISP_HDMI_GENERIC_SUBPACK3_HIGH 0x034 + +#define HDMI_NV_PDISP_HDMI_ACR_CTRL 0x035 +#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_LOW 0x036 +#define HDMI_NV_PDISP_HDMI_ACR_0320_SUBPACK_HIGH 0x037 +#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_LOW 0x038 +#define HDMI_NV_PDISP_HDMI_ACR_0441_SUBPACK_HIGH 0x039 +#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_LOW 0x03a +#define HDMI_NV_PDISP_HDMI_ACR_0882_SUBPACK_HIGH 0x03b +#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_LOW 0x03c +#define HDMI_NV_PDISP_HDMI_ACR_1764_SUBPACK_HIGH 0x03d +#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_LOW 0x03e +#define HDMI_NV_PDISP_HDMI_ACR_0480_SUBPACK_HIGH 0x03f +#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_LOW 0x040 +#define HDMI_NV_PDISP_HDMI_ACR_0960_SUBPACK_HIGH 0x041 +#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_LOW 0x042 +#define HDMI_NV_PDISP_HDMI_ACR_1920_SUBPACK_HIGH 0x043 +#define ACR_ENABLE (1U << 31) +#define ACR_SUBPACK_CTS(x) (((x) & 0xffffff) << 8) +#define ACR_SUBPACK_N(x) (((x) & 0xffffff) << 0) + +#define HDMI_NV_PDISP_HDMI_CTRL 0x044 +#define HDMI_CTRL_ENABLE (1 << 30) +#define HDMI_CTRL_CA_SELECT (1 << 28) +#define HDMI_CTRL_SS_SELECT (1 << 27) +#define HDMI_CTRL_SF_SELECT (1 << 26) +#define HDMI_CTRL_CC_SELECT (1 << 25) +#define HDMI_CTRL_CT_SELECT (1 << 24) +#define HDMI_CTRL_MAX_AC_PACKET(x) (((x) & 0x1f) << 16) +#define HDMI_CTRL_SAMPLE_FLAT (1 << 12) +#define HDMI_CTRL_AUDIO_LAYOUT_SELECT (1 << 10) +#define HDMI_CTRL_AUDIO_LAYOUT (1 << 8) +#define HDMI_CTRL_REKEY(x) (((x) & 0x7f) << 0) + +#define HDMI_NV_PDISP_HDMI_VSYNC_WINDOW 0x046 +#define VSYNC_WINDOW_ENABLE (1U << 31) +#define VSYNC_WINDOW_START(x) (((x) & 0x3ff) << 16) +#define VSYNC_WINDOW_END(x) (((x) & 0x3ff) << 0) + +#define HDMI_NV_PDISP_HDMI_SPARE 0x04f +#define SPARE_ACR_PRIORITY (1U << 31) +#define SPARE_CTS_RESET_VAL(x) (((x) & 0x7) << 16) +#define SPARE_SUPRESS_SP_B (1 << 2) +#define SPARE_FORCE_SW_CTS (1 << 1) +#define SPARE_HW_CTS (1 << 0) + +#define HDMI_NV_PDISP_SOR_PWR 0x055 +#define SOR_PWR_SETTING_NEW (1U << 31) +#define SOR_PWR_SAFE_STATE_PU (1 << 16) +#define SOR_PWR_NORMAL_START_ALT (1 << 1) +#define SOR_PWR_NORMAL_STATE_PU (1 << 0) + +#define HDMI_NV_PDISP_SOR_PLL0 0x057 +#define SOR_PLL0_TX_REG_LOAD(x) (((x) & 0xf) << 28) +#define SOR_PLL0_ICHPMP(x) (((x) & 0xf) << 24) +#define SOR_PLL0_FILTER(x) (((x) & 0xf) << 16) +#define SOR_PLL0_BG_V17_S(x) (((x) & 0xf) << 12) +#define SOR_PLL0_VCOCAP(x) (((x) & 0xf) << 8) +#define SOR_PLL0_PULLDOWN (1 << 5) +#define SOR_PLL0_RESISTORSEL (1 << 4) +#define SOR_PLL0_PDPORT (1 << 3) +#define SOR_PLL0_VCOPD (1 << 2) +#define SOR_PLL0_PDBG (1 << 1) +#define SOR_PLL0_PWR (1 << 0) + +#define HDMI_NV_PDISP_SOR_PLL1 0x058 +#define SOR_PLL1_S_D_PIN_PE (1 << 30) +#define SOR_PLL1_HALF_FULL_PE (1 << 29) +#define SOR_PLL1_PE_EN (1 << 28) +#define SOR_PLL1_LOADADJ(x) (((x) & 0xf) << 20) +#define SOR_PLL1_TMDS_TERMADJ(x) (((x) & 0xf) << 9) +#define SOR_PLL1_TMDS_TERM (1 << 8) + +#define HDMI_NV_PDISP_SOR_CSTM 0x05a +#define SOR_CSTM_ROTAT(x) (((x) & 0xf) << 28) +#define SOR_CSTM_ROTCLK(x) (((x) & 0xf) << 24) +#define SOR_CSTM_PLLDIV (1 << 21) +#define SOR_CSTM_BALANCED (1 << 19) +#define SOR_CSTM_NEW_MODE (1 << 18) +#define SOR_CSTM_DUP_SYNC (1 << 17) +#define SOR_CSTM_LVDS_ENABLE (1 << 16) +#define SOR_CSTM_LINKACTB (1 << 15) +#define SOR_CSTM_LINKACTA (1 << 14) +#define SOR_CSTM_MODE(x) (((x) & 0x3) << 12) +#define CSTM_MODE_LVDS 0 +#define CSTM_MODE_TMDS 1 + +#define HDMI_NV_PDISP_SOR_SEQ_CTL 0x05f +#define SOR_SEQ_SWITCH (1 << 30) +#define SOR_SEQ_STATUS (1 << 28) +#define SOR_SEQ_PC(x) (((x) & 0xf) << 16) +#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12) +#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8) +#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4) +#define SOR_SEQ_PU_PC(x) (((x) & 0xf) << 0) + +#define HDMI_NV_PDISP_SOR_SEQ_INST(x) (0x060 + (x)) +#define SOR_SEQ_INST_PLL_PULLDOWN (1U << 31) +#define SOR_SEQ_INST_POWERDOWN_MACRO (1 << 30) +#define SOR_SEQ_INST_ASSERT_PLL_RESETV (1 << 29) +#define SOR_SEQ_INST_BLANK_V (1 << 28) +#define SOR_SEQ_INST_BLANK_H (1 << 27) +#define SOR_SEQ_INST_BLANK_DE (1 << 26) +#define SOR_SEQ_INST_BLACK_DATA (1 << 25) +#define SOR_SEQ_INST_TRISTATE_IOS (1 << 24) +#define SOR_SEQ_INST_DRIVE_PWM_OUT_LO (1 << 23) +#define SOR_SEQ_INST_PIN_B_HIGH (1 << 22) +#define SOR_SEQ_INST_PIN_A_HIGH (1 << 21) +#define SOR_SEQ_INST_HALT (1 << 15) +#define SOR_SEQ_INST_WAIT_UNITS(x) (((x) & 0x3) << 12) +#define WAIT_UNITS_US 0 +#define WAIT_UNITS_MS 1 +#define WAIT_UNITS_VSYNC 2 +#define SOR_SEQ_INST_WAIT_TIME(x) (((x) & 0x3ff) << 0) + +#define HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT 0x07e + + +#define HDMI_NV_PDISP_AUDIO_N 0x08c +#define AUDIO_N_LOOKUP (1 << 28) +#define AUDIO_N_GENERATE_ALTERNATE (1 << 24) +#define AUDIO_N_RESETF (1 << 20) +#define AUDIO_N_VALUE(x) (((x) & 0xfffff) << 0) + +#define HDMI_NV_PDISP_SOR_REFCLK 0x095 +#define SOR_REFCLK_DIV_INT(x) (((x) & 0xff) << 8) +#define SOR_REFCLK_DIV_FRAC(x) (((x) & 0x03) << 6) + +#define HDMI_NV_PDISP_INPUT_CONTROL 0x097 +#define ARM_VIDEO_RANGE_LIMITED (1 << 1) +#define HDMI_SRC_DISPLAYB (1 << 0) + +#define HDMI_NV_PDISP_PE_CURRENT 0x099 +#define HDMI_NV_PDISP_SOR_AUDIO_CNTRL0 0x0ac +#define SOR_AUDIO_CNTRL0_INJECT_NULLSMPL (1 << 29) +#define SOR_AUDIO_CNTRL0_SOURCE_SELECT(x) (((x) & 0x03) << 20) +#define SOURCE_SELECT_AUTO 0 +#define SOURCE_SELECT_SPDIF 1 +#define SOURCE_SELECT_HDAL 2 +#define SOR_AUDIO_CNTRL0_AFIFO_FLUSH (1 << 12) + +#define HDMI_NV_PDISP_SOR_AUDIO_SPARE0 0x0ae +#define SOR_AUDIO_SPARE0_HBR_ENABLE (1 << 27) + +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0320 0x0af +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0441 0x0b0 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0882 0x0b1 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_1764 0x0b2 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0480 0x0b3 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_0960 0x0b4 +#define HDMI_NV_PDISP_SOR_AUDIO_NVAL_1920 0x0b5 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH0 0x0b6 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH1 0x0b7 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH2 0x0b8 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_SCRATCH3 0x0b9 +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH0 0x0ba +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_CODEC_SCRATCH1 0x0bb +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR 0x0bc +#define HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE 0x0bd +#define SOR_AUDIO_HDA_PRESENSE_VALID (1 << 1) +#define SOR_AUDIO_HDA_PRESENSE_PRESENT (1 << 0) + +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0320 0x0bf +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0441 0x0c0 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0882 0x0c1 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1764 0x0c2 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0480 0x0c3 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_0960 0x0c4 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_1920 0x0c5 +#define HDMI_NV_PDISP_SOR_AUDIO_AVAL_DEFAULT 0x0c6 + +#define HDMI_NV_PDISP_INT_STATUS 0x0cc +#define INT_SCRATCH (1 << 3) +#define INT_CP_REQUEST (1 << 2) +#define INT_CODEC_SCRATCH1 (1 << 1) +#define INT_CODEC_SCRATCH0 (1 << 0) + +#define HDMI_NV_PDISP_INT_MASK 0x0cd +#define HDMI_NV_PDISP_INT_ENABLE 0x0ce +#define HDMI_NV_PDISP_SOR_IO_PEAK_CURRENT 0x0d1 +#define HDMI_NV_PDISP_SOR_PAD_CTLS0 0x0d2 + + +#endif /* _TEGRA_HDMI_REG_H_ */ Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_hdmi_reg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/drm2/tegra_host1x.c =================================================================== --- stable/11/sys/arm/nvidia/drm2/tegra_host1x.c (nonexistent) +++ stable/11/sys/arm/nvidia/drm2/tegra_host1x.c (revision 332010) @@ -0,0 +1,650 @@ +/*- + * Copyright (c) 2015 Michal Meloun + * 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 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 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "fb_if.h" +#include "tegra_drm_if.h" + +#define WR4(_sc, _r, _v) bus_rite_4((_sc)->mem_res, (_r), (_v)) +#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r)) + +#define LOCK(_sc) sx_xlock(&(_sc)->lock) +#define UNLOCK(_sc) sx_xunlock(&(_sc)->lock) +#define SLEEP(_sc, timeout) sx_sleep(sc, &sc->lock, 0, "host1x", timeout); +#define LOCK_INIT(_sc) sx_init(&_sc->lock, "host1x") +#define LOCK_DESTROY(_sc) sx_destroy(&_sc->lock) +#define ASSERT_LOCKED(_sc) sx_assert(&_sc->lock, SA_LOCKED) +#define ASSERT_UNLOCKED(_sc) sx_assert(&_sc->lock, SA_UNLOCKED) + +static struct ofw_compat_data compat_data[] = { + {"nvidia,tegra124-host1x", 1}, + {NULL, 0} +}; + +#define DRIVER_NAME "tegra" +#define DRIVER_DESC "NVIDIA Tegra TK1" +#define DRIVER_DATE "20151101" +#define DRIVER_MAJOR 0 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 0 + +struct client_info; +TAILQ_HEAD(client_list, client_info); +typedef struct client_list client_list_t; + +struct client_info { + TAILQ_ENTRY(client_info) list_e; + device_t client; + int activated; +}; + +struct host1x_softc { + struct simplebus_softc simplebus_sc; /* must be first */ + device_t dev; + struct sx lock; + int attach_done; + + struct resource *mem_res; + struct resource *syncpt_irq_res; + void *syncpt_irq_h; + struct resource *gen_irq_res; + void *gen_irq_h; + + clk_t clk; + hwreset_t reset; + struct intr_config_hook irq_hook; + + int drm_inited; + client_list_t clients; + + struct tegra_drm *tegra_drm; +}; + + +static void +host1x_output_poll_changed(struct drm_device *drm_dev) +{ + struct tegra_drm *drm; + + drm = container_of(drm_dev, struct tegra_drm, drm_dev); + if (drm->fb != NULL) + drm_fb_helper_hotplug_event(&drm->fb->fb_helper); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = tegra_drm_fb_create, + .output_poll_changed = host1x_output_poll_changed, +}; + + +static int +host1x_drm_init(struct host1x_softc *sc) +{ + struct client_info *entry; + int rv; + + LOCK(sc); + + TAILQ_FOREACH(entry, &sc->clients, list_e) { + if (entry->activated) + continue; + rv = TEGRA_DRM_INIT_CLIENT(entry->client, sc->dev, + sc->tegra_drm); + if (rv != 0) { + device_printf(sc->dev, + "Cannot init DRM client %s: %d\n", + device_get_name(entry->client), rv); + return (rv); + } + entry->activated = 1; + } + UNLOCK(sc); + + return (0); +} + +static int +host1x_drm_exit(struct host1x_softc *sc) +{ + struct client_info *entry; + int rv; +#ifdef FREEBSD_NOTYET + struct drm_device *dev, *tmp; +#endif + LOCK(sc); + if (!sc->drm_inited) { + UNLOCK(sc); + return (0); + } + TAILQ_FOREACH_REVERSE(entry, &sc->clients, client_list, list_e) { + if (!entry->activated) + continue; + rv = TEGRA_DRM_EXIT_CLIENT(entry->client, sc->dev, + sc->tegra_drm); + if (rv != 0) { + device_printf(sc->dev, + "Cannot exit DRM client %s: %d\n", + device_get_name(entry->client), rv); + } + entry->activated = 0; + } + +#ifdef FREEBSD_NOTYET + list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) + drm_put_dev(dev); +#endif + sc->drm_inited = 0; + UNLOCK(sc); + + return (0); +} + +static int +host1x_drm_load(struct drm_device *drm_dev, unsigned long flags) +{ + struct host1x_softc *sc; + int rv; + + sc = device_get_softc(drm_dev->dev); + + drm_mode_config_init(drm_dev); + drm_dev->mode_config.min_width = 32; + drm_dev->mode_config.min_height = 32; + drm_dev->mode_config.max_width = 4096; + drm_dev->mode_config.max_height = 4096; + drm_dev->mode_config.funcs = &mode_config_funcs; + + rv = host1x_drm_init(sc); + if (rv != 0) + goto fail_host1x; + + drm_dev->irq_enabled = true; + drm_dev->max_vblank_count = 0xffffffff; + drm_dev->vblank_disable_allowed = true; + + rv = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc); + if (rv != 0) + goto fail_vblank; + + drm_mode_config_reset(drm_dev); + + rv = tegra_drm_fb_init(drm_dev); + if (rv != 0) + goto fail_fb; + drm_kms_helper_poll_init(drm_dev); + + return (0); + +fail_fb: + tegra_drm_fb_destroy(drm_dev); + drm_vblank_cleanup(drm_dev); +fail_vblank: + host1x_drm_exit(sc); +fail_host1x: + drm_mode_config_cleanup(drm_dev); + + return (rv); +} + +static int +host1x_drm_unload(struct drm_device *drm_dev) +{ + struct host1x_softc *sc; + int rv; + + sc = device_get_softc(drm_dev->dev); + + drm_kms_helper_poll_fini(drm_dev); + tegra_drm_fb_destroy(drm_dev); + drm_mode_config_cleanup(drm_dev); + + rv = host1x_drm_exit(sc); + if (rv < 0) + return (rv); + return (0); +} + +static int +host1x_drm_open(struct drm_device *drm_dev, struct drm_file *filp) +{ + + return (0); +} + +static void +tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) +{ + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) + tegra_dc_cancel_page_flip(crtc, file); +} + +static void +host1x_drm_lastclose(struct drm_device *drm_dev) +{ + + struct tegra_drm *drm; + + drm = container_of(drm_dev, struct tegra_drm, drm_dev); + if (drm->fb != NULL) + drm_fb_helper_restore_fbdev_mode(&drm->fb->fb_helper); +} + +static int +host1x_drm_enable_vblank(struct drm_device *drm_dev, int pipe) +{ + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) { + if (pipe == tegra_dc_get_pipe(crtc)) { + tegra_dc_enable_vblank(crtc); + return (0); + } + } + return (-ENODEV); +} + +static void +host1x_drm_disable_vblank(struct drm_device *drm_dev, int pipe) +{ + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) { + if (pipe == tegra_dc_get_pipe(crtc)) { + tegra_dc_disable_vblank(crtc); + return; + } + } +} + + +static struct drm_ioctl_desc host1x_drm_ioctls[] = { +}; + + +struct drm_driver tegra_drm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, + .load = host1x_drm_load, + .unload = host1x_drm_unload, + .open = host1x_drm_open, + .preclose = tegra_drm_preclose, + .lastclose = host1x_drm_lastclose, + + .get_vblank_counter = drm_vblank_count, + .enable_vblank = host1x_drm_enable_vblank, + .disable_vblank = host1x_drm_disable_vblank, + + /* Fields filled by tegra_bo_driver_register() + .gem_free_object + .gem_pager_ops + .dumb_create + .dumb_map_offset + .dumb_destroy + */ + .ioctls = host1x_drm_ioctls, + .num_ioctls = nitems(host1x_drm_ioctls), + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +/* + * ----------------- Device methods ------------------------- + */ +static void +host1x_irq_hook(void *arg) +{ + struct host1x_softc *sc; + int rv; + + sc = arg; + config_intrhook_disestablish(&sc->irq_hook); + + tegra_bo_driver_register(&tegra_drm_driver); + rv = drm_get_platform_dev(sc->dev, &sc->tegra_drm->drm_dev, + &tegra_drm_driver); + if (rv != 0) { + device_printf(sc->dev, "drm_get_platform_dev(): %d\n", rv); + return; + } + + sc->drm_inited = 1; +} + +static struct fb_info * +host1x_fb_helper_getinfo(device_t dev) +{ + struct host1x_softc *sc; + + sc = device_get_softc(dev); + if (sc->tegra_drm == NULL) + return (NULL); + return (tegra_drm_fb_getinfo(&sc->tegra_drm->drm_dev)); +} + +static int +host1x_register_client(device_t dev, device_t client) +{ + struct host1x_softc *sc; + struct client_info *entry; + + sc = device_get_softc(dev); + + entry = malloc(sizeof(struct client_info), M_DEVBUF, M_WAITOK | M_ZERO); + entry->client = client; + entry->activated = 0; + + LOCK(sc); + TAILQ_INSERT_TAIL(&sc->clients, entry, list_e); + UNLOCK(sc); + + return (0); +} + +static int +host1x_deregister_client(device_t dev, device_t client) +{ + struct host1x_softc *sc; + struct client_info *entry; + + sc = device_get_softc(dev); + + LOCK(sc); + TAILQ_FOREACH(entry, &sc->clients, list_e) { + if (entry->client == client) { + if (entry->activated) + panic("Tegra DRM: Attempt to deregister " + "activated client"); + TAILQ_REMOVE(&sc->clients, entry, list_e); + free(entry, M_DEVBUF); + UNLOCK(sc); + return (0); + } + } + UNLOCK(sc); + + return (0); +} + +static void +host1x_gen_intr(void *arg) +{ + struct host1x_softc *sc; + + sc = (struct host1x_softc *)arg; + LOCK(sc); + UNLOCK(sc); +} + +static void +host1x_syncpt_intr(void *arg) +{ + struct host1x_softc *sc; + + sc = (struct host1x_softc *)arg; + LOCK(sc); + UNLOCK(sc); +} + +static void +host1x_new_pass(device_t dev) +{ + struct host1x_softc *sc; + int rv, rid; + phandle_t node; + + /* + * We attach during BUS_PASS_BUS (because we must overcome simplebus), + * but some of our FDT resources are not ready until BUS_PASS_DEFAULT + */ + sc = device_get_softc(dev); + if (sc->attach_done || bus_current_pass < BUS_PASS_DEFAULT) { + bus_generic_new_pass(dev); + return; + } + + sc->attach_done = 1; + node = ofw_bus_get_node(dev); + + /* Allocate our IRQ resource. */ + rid = 0; + sc->syncpt_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->syncpt_irq_res == NULL) { + device_printf(dev, "Cannot allocate interrupt.\n"); + rv = ENXIO; + goto fail; + } + rid = 1; + sc->gen_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->gen_irq_res == NULL) { + device_printf(dev, "Cannot allocate interrupt.\n"); + rv = ENXIO; + goto fail; + } + + /* FDT resources */ + rv = hwreset_get_by_ofw_name(sc->dev, 0, "host1x", &sc->reset); + if (rv != 0) { + device_printf(dev, "Cannot get fuse reset\n"); + goto fail; + } + rv = clk_get_by_ofw_index(sc->dev, 0, 0, &sc->clk); + if (rv != 0) { + device_printf(dev, "Cannot get i2c clock: %d\n", rv); + goto fail; + } + + rv = clk_enable(sc->clk); + if (rv != 0) { + device_printf(dev, "Cannot enable clock: %d\n", rv); + goto fail; + } + rv = hwreset_deassert(sc->reset); + if (rv != 0) { + device_printf(sc->dev, "Cannot clear reset\n"); + goto fail; + } + + /* Setup interrupts */ + rv = bus_setup_intr(dev, sc->gen_irq_res, + INTR_TYPE_MISC | INTR_MPSAFE, NULL, host1x_gen_intr, + sc, &sc->gen_irq_h); + if (rv) { + device_printf(dev, "Cannot setup gen interrupt.\n"); + goto fail; + } + + rv = bus_setup_intr(dev, sc->syncpt_irq_res, + INTR_TYPE_MISC | INTR_MPSAFE, NULL, host1x_syncpt_intr, + sc, &sc->syncpt_irq_h); + if (rv) { + device_printf(dev, "Cannot setup syncpt interrupt.\n"); + goto fail; + } + + simplebus_init(dev, 0); + for (node = OF_child(node); node > 0; node = OF_peer(node)) + simplebus_add_device(dev, node, 0, NULL, -1, NULL); + + sc->irq_hook.ich_func = host1x_irq_hook; + sc->irq_hook.ich_arg = sc; + config_intrhook_establish(&sc->irq_hook); + bus_generic_new_pass(dev); + return; + +fail: + device_detach(dev); + return; +} + +static int +host1x_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + return (BUS_PROBE_DEFAULT); +} + +static int +host1x_attach(device_t dev) +{ + int rv, rid; + struct host1x_softc *sc; + + sc = device_get_softc(dev); + sc->tegra_drm = malloc(sizeof(struct tegra_drm), DRM_MEM_DRIVER, + M_WAITOK | M_ZERO); + + /* crosslink together all worlds */ + sc->dev = dev; + sc->tegra_drm->drm_dev.dev_private = &sc->tegra_drm; + sc->tegra_drm->drm_dev.dev = dev; + + TAILQ_INIT(&sc->clients); + + LOCK_INIT(sc); + + /* Get the memory resource for the register mapping. */ + rid = 0; + sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res == NULL) { + device_printf(dev, "Cannot map registers.\n"); + rv = ENXIO; + goto fail; + } + + return (bus_generic_attach(dev)); + +fail: + if (sc->tegra_drm != NULL) + free(sc->tegra_drm, DRM_MEM_DRIVER); + if (sc->mem_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + LOCK_DESTROY(sc); + return (rv); +} + +static int +host1x_detach(device_t dev) +{ + struct host1x_softc *sc; + + sc = device_get_softc(dev); + + host1x_drm_exit(sc); + + if (sc->gen_irq_h != NULL) + bus_teardown_intr(dev, sc->gen_irq_res, sc->gen_irq_h); + if (sc->tegra_drm != NULL) + free(sc->tegra_drm, DRM_MEM_DRIVER); + if (sc->clk != NULL) + clk_release(sc->clk); + if (sc->reset != NULL) + hwreset_release(sc->reset); + if (sc->syncpt_irq_h != NULL) + bus_teardown_intr(dev, sc->syncpt_irq_res, sc->syncpt_irq_h); + if (sc->gen_irq_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, 1, sc->gen_irq_res); + if (sc->syncpt_irq_res != NULL) + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->syncpt_irq_res); + if (sc->mem_res != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); + LOCK_DESTROY(sc); + return (bus_generic_detach(dev)); +} + +static device_method_t host1x_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, host1x_probe), + DEVMETHOD(device_attach, host1x_attach), + DEVMETHOD(device_detach, host1x_detach), + + /* Bus interface */ + DEVMETHOD(bus_new_pass, host1x_new_pass), + + /* Framebuffer service methods */ + DEVMETHOD(fb_getinfo, host1x_fb_helper_getinfo), + + /* tegra drm interface */ + DEVMETHOD(tegra_drm_register_client, host1x_register_client), + DEVMETHOD(tegra_drm_deregister_client, host1x_deregister_client), + + DEVMETHOD_END +}; + +static devclass_t host1x_devclass; +DEFINE_CLASS_1(host1x, host1x_driver, host1x_methods, + sizeof(struct host1x_softc), simplebus_driver); +EARLY_DRIVER_MODULE(host1x, simplebus, host1x_driver, + host1x_devclass, 0, 0, BUS_PASS_BUS); + +/* Bindings for fbd device. */ +extern devclass_t fbd_devclass; +extern driver_t fbd_driver; +DRIVER_MODULE(fbd, host1x, fbd_driver, fbd_devclass, 0, 0); + Property changes on: stable/11/sys/arm/nvidia/drm2/tegra_host1x.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/arm/nvidia/tegra124/files.tegra124 =================================================================== --- stable/11/sys/arm/nvidia/tegra124/files.tegra124 (revision 332009) +++ stable/11/sys/arm/nvidia/tegra124/files.tegra124 (revision 332010) @@ -1,57 +1,72 @@ # $FreeBSD$ # # Standard ARM support. # kern/kern_clocksource.c standard # # Standard tegra124 devices and support. # arm/nvidia/tegra124/tegra124_machdep.c standard arm/nvidia/tegra124/tegra124_mp.c optional smp arm/nvidia/tegra124/tegra124_car.c standard arm/nvidia/tegra124/tegra124_clk_pll.c standard arm/nvidia/tegra124/tegra124_clk_per.c standard arm/nvidia/tegra124/tegra124_clk_super.c standard arm/nvidia/tegra124/tegra124_xusbpadctl.c standard arm/nvidia/tegra124/tegra124_pmc.c standard arm/nvidia/tegra124/tegra124_cpufreq.c standard arm/nvidia/tegra124/tegra124_coretemp.c standard arm/nvidia/tegra_usbphy.c standard arm/nvidia/tegra_pinmux.c standard arm/nvidia/tegra_uart.c optional uart arm/nvidia/tegra_sdhci.c optional sdhci arm/nvidia/tegra_gpio.c optional gpio arm/nvidia/tegra_ehci.c optional ehci +arm/nvidia/tegra_xhci.c optional xhci arm/nvidia/tegra_ahci.c optional ahci arm/nvidia/tegra_pcie.c optional pci arm/nvidia/tegra_i2c.c optional iic arm/nvidia/tegra_rtc.c standard arm/nvidia/tegra_abpmisc.c standard arm/nvidia/tegra_efuse.c standard arm/nvidia/tegra_soctherm_if.m standard arm/nvidia/tegra_soctherm.c standard arm/nvidia/tegra_lic.c standard arm/nvidia/tegra_mc.c standard #arm/nvidia/tegra_hda.c optional snd_hda -#arm/nvidia/drm2/hdmi.c optional drm2 -#arm/nvidia/drm2/tegra_drm_if.m optional drm2 -#arm/nvidia/drm2/tegra_drm_subr.c optional drm2 -#arm/nvidia/drm2/tegra_host1x.c optional drm2 -#arm/nvidia/drm2/tegra_hdmi.c optional drm2 -#arm/nvidia/drm2/tegra_dc_if.m optional drm2 -#arm/nvidia/drm2/tegra_dc.c optional drm2 -#arm/nvidia/drm2/tegra_fb.c optional drm2 -#arm/nvidia/drm2/tegra_bo.c optional drm2 +arm/nvidia/drm2/hdmi.c optional drm2 +arm/nvidia/drm2/tegra_drm_if.m optional drm2 +arm/nvidia/drm2/tegra_drm_subr.c optional drm2 +arm/nvidia/drm2/tegra_host1x.c optional drm2 +arm/nvidia/drm2/tegra_hdmi.c optional drm2 +arm/nvidia/drm2/tegra_dc_if.m optional drm2 +arm/nvidia/drm2/tegra_dc.c optional drm2 +arm/nvidia/drm2/tegra_fb.c optional drm2 +arm/nvidia/drm2/tegra_bo.c optional drm2 # -# Optional devices. +# Firmware # - +tegra124_xusb_fw.c optional tegra124_xusb_fw \ + dependency "$S/arm/nvidia/tegra124/files.tegra124" \ + compile-with "${AWK} -f $S/tools/fw_stub.awk tegra124_xusb.fw:tegra124_xusb_fw -mtegra124_xusb_fw -c${.TARGET}" \ + no-implicit-rule before-depend local \ + clean "tegra124_xusb_fw.c" +tegra124_xusb.fwo optional tegra124_xusb_fw \ + dependency "tegra124_xusb.fw" \ + compile-with "${NORMAL_FWO}" \ + no-implicit-rule \ + clean "tegra124_xusb.fwo" +tegra124_xusb.fw optional tegra124_xusb_fw \ + dependency "$S/contrib/dev/nvidia/tegra124_xusb.bin.uu" \ + compile-with "${NORMAL_FW}" \ + no-obj no-implicit-rule \ + clean "tegra124_xusb.fw" # -# Temporary/ to be moved stuff +# Temporary/to be moved stuff # arm/nvidia/as3722.c optional iic arm/nvidia/as3722_regulators.c optional iic arm/nvidia/as3722_rtc.c optional iic arm/nvidia/as3722_gpio.c optional iic Index: stable/11/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c =================================================================== --- stable/11/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c (revision 332009) +++ stable/11/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c (revision 332010) @@ -1,597 +1,1208 @@ /*- * Copyright (c) 2016 Michal Meloun * 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 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 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 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. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include +#include + #include #include "phy_if.h" +/* FUSE calibration data. */ +#define FUSE_XUSB_CALIB 0x0F0 +#define FUSE_XUSB_CALIB_HS_CURR_LEVEL_123(x) (((x) >> 15) & 0x3F); +#define FUSE_XUSB_CALIB_HS_IREF_CAP(x) (((x) >> 13) & 0x03); +#define FUSE_XUSB_CALIB_HS_SQUELCH_LEVEL(x) (((x) >> 11) & 0x03); +#define FUSE_XUSB_CALIB_HS_TERM_RANGE_ADJ(x) (((x) >> 7) & 0x0F); +#define FUSE_XUSB_CALIB_HS_CURR_LEVEL_0(x) (((x) >> 0) & 0x3F); + + +/* Registers. */ #define XUSB_PADCTL_USB2_PAD_MUX 0x004 +#define XUSB_PADCTL_USB2_PORT_CAP 0x008 +#define USB2_PORT_CAP_ULPI_PORT_INTERNAL (1 << 25) +#define USB2_PORT_CAP_ULPI_PORT_CAP (1 << 24) +#define USB2_PORT_CAP_PORT_REVERSE_ID(p) (1 << (3 + (p) * 4)) +#define USB2_PORT_CAP_PORT_INTERNAL(p) (1 << (2 + (p) * 4)) +#define USB2_PORT_CAP_PORT_CAP(p, x) (((x) & 3) << ((p) * 4)) +#define USB2_PORT_CAP_PORT_CAP_OTG 0x3 +#define USB2_PORT_CAP_PORT_CAP_DEVICE 0x2 +#define USB2_PORT_CAP_PORT_CAP_HOST 0x1 +#define USB2_PORT_CAP_PORT_CAP_DISABLED 0x0 + +#define XUSB_PADCTL_SS_PORT_MAP 0x014 +#define SS_PORT_MAP_PORT_INTERNAL(p) (1 << (3 + (p) * 4)) +#define SS_PORT_MAP_PORT_MAP(p, x) (((x) & 7) << ((p) * 4)) + #define XUSB_PADCTL_ELPG_PROGRAM 0x01C #define ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) #define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) #define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) +#define ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4)) +#define ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(x) (1 << (17 + (x) * 4)) +#define ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4)) #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 #define IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) -#define IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf<< 12) +#define IOPHY_PLL_P0_CTL1_REFCLK_SEL(x) (((x) & 0xF) << 12) #define IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 #define IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) #define IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) #define IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) +#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(x) (0x058 + (x) * 4) +#define IOPHY_USB3_PAD_CTL2_CDR_CNTL(x) (((x) & 0x00FF) << 4) +#define IOPHY_USB3_PAD_CTL2_RX_EQ(x) (((x) & 0xFFFF) << 8) +#define IOPHY_USB3_PAD_CTL2_RX_WANDER(x) (((x) & 0x000F) << 4) +#define IOPHY_USB3_PAD_CTL2_RX_TERM_CNTL(x) (((x) & 0x0003) << 2) +#define IOPHY_USB3_PAD_CTL2_TX_TERM_CNTL(x) (((x) & 0x0003) << 0) + +#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(x) (0x068 + (x) * 4) + +#define XUSB_PADCTL_USB2_OTG_PAD_CTL0(x) (0x0A0 + (x) * 4) +#define USB2_OTG_PAD_CTL0_LSBIAS_SEL (1 << 23) +#define USB2_OTG_PAD_CTL0_DISCON_DETECT_METHOD (1 << 22) +#define USB2_OTG_PAD_CTL0_PD_ZI (1 << 21) +#define USB2_OTG_PAD_CTL0_PD2 (1 << 20) +#define USB2_OTG_PAD_CTL0_PD (1 << 19) +#define USB2_OTG_PAD_CTL0_TERM_EN (1 << 18) +#define USB2_OTG_PAD_CTL0_LS_LS_FSLEW(x) (((x) & 0x03) << 16) +#define USB2_OTG_PAD_CTL0_LS_RSLEW(x) (((x) & 0x03) << 14) +#define USB2_OTG_PAD_CTL0_FS_SLEW(x) (((x) & 0x03) << 12) +#define USB2_OTG_PAD_CTL0_HS_SLEW(x) (((x) & 0x3F) << 6) +#define USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(x) (((x) & 0x3F) << 0) + +#define XUSB_PADCTL_USB2_OTG_PAD_CTL1(x) (0x0AC + (x) * 4) +#define USB2_OTG_PAD_CTL1_RPU_RANGE_ADJ(x) (((x) & 0x3) << 11) +#define USB2_OTG_PAD_CTL1_HS_IREF_CAP(x) (((x) & 0x3) << 9) +#define USB2_OTG_PAD_CTL1_SPARE(x) (((x) & 0x3) << 7) +#define USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(x) (((x) & 0xF) << 3) +#define USB2_OTG_PAD_CTL1_PD_DR (1 << 2) +#define USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1) +#define USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0) + +#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0B8 +#define USB2_BIAS_PAD_CTL0_ADJRPU(x) (((x) & 0x7) << 14) +#define USB2_BIAS_PAD_CTL0_PD_TRK (1 << 13) +#define USB2_BIAS_PAD_CTL0_PD (1 << 12) +#define USB2_BIAS_PAD_CTL0_TERM_OFFSETL(x) (((x) & 0x3) << 9) +#define USB2_BIAS_PAD_CTL0_VBUS_LEVEL(x) (((x) & 0x3) << 7) +#define USB2_BIAS_PAD_CTL0_HS_CHIRP_LEVEL(x) (((x) & 0x3) << 5) +#define USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(x) (((x) & 0x7) << 2) +#define USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(x) (((x) & 0x3) << 0) + +#define XUSB_PADCTL_HSIC_PAD0_CTL0 0x0C8 +#define HSIC_PAD0_CTL0_HSIC_OPT(x) (((x) & 0xF) << 16) +#define HSIC_PAD0_CTL0_TX_SLEWN(x) (((x) & 0xF) << 12) +#define HSIC_PAD0_CTL0_TX_SLEWP(x) (((x) & 0xF) << 8) +#define HSIC_PAD0_CTL0_TX_RTUNEN(x) (((x) & 0xF) << 4) +#define HSIC_PAD0_CTL0_TX_RTUNEP(x) (((x) & 0xF) << 0) + #define XUSB_PADCTL_USB3_PAD_MUX 0x134 +#define USB3_PAD_MUX_PCIE_IDDQ_DISABLE(x) (1 << (1 + (x))) +#define USB3_PAD_MUX_SATA_IDDQ_DISABLE (1 << 6) + #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 #define IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) #define IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) #define IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) #define IOPHY_PLL_S0_CTL1_PLL_RST_L (1 << 1) #define IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) #define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13C #define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL4 0x144 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 #define IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) #define IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14C #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL3 0x150 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL4 0x154 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15C -struct lane_cfg { - char *function; - char **lanes; - int iddq; -}; -struct xusbpadctl_softc { +#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v)) +#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r)) + + +struct padctl_softc { device_t dev; struct resource *mem_res; - hwreset_t rst; + hwreset_t rst; int phy_ena_cnt; + + /* Fuses calibration data */ + uint32_t hs_curr_level_0; + uint32_t hs_curr_level_123; + uint32_t hs_iref_cap; + uint32_t hs_term_range_adj; + uint32_t hs_squelch_level; + + uint32_t hs_curr_level_offset; }; static struct ofw_compat_data compat_data[] = { {"nvidia,tegra124-xusb-padctl", 1}, {NULL, 0}, }; -struct padctl_lane { - const char *name; - bus_size_t reg; - uint32_t shift; - uint32_t mask; - int iddq; - char **mux; - int nmux; +/* Ports. */ +enum padctl_port_type { + PADCTL_PORT_USB2, + PADCTL_PORT_ULPI, + PADCTL_PORT_HSIC, + PADCTL_PORT_USB3, }; -static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"}; -static char *usb_mux[] = {"snps", "xusb"}; -static char *pci_mux[] = {"pcie", "usb3", "sata", "rsvd"}; +struct padctl_lane; +struct padctl_port { + enum padctl_port_type type; + const char *name; + const char *base_name; + int idx; + int (*init)(struct padctl_softc *sc, + struct padctl_port *port); -#define LANE(n, r, s, m, i, mx) \ -{ \ - .name = n, \ - .reg = r, \ - .shift = s, \ - .mask = m, \ - .iddq = i, \ - .mux = mx, \ - .nmux = nitems(mx), \ -} - -static const struct padctl_lane lanes_tbl[] = { - LANE("otg-0", XUSB_PADCTL_USB2_PAD_MUX, 0, 0x3, -1, otg_mux), - LANE("otg-1", XUSB_PADCTL_USB2_PAD_MUX, 2, 0x3, -1, otg_mux), - LANE("otg-2", XUSB_PADCTL_USB2_PAD_MUX, 4, 0x3, -1, otg_mux), - LANE("ulpi-0", XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, -1, usb_mux), - LANE("hsic-0", XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, -1, usb_mux), - LANE("hsic-1", XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, -1, usb_mux), - LANE("pcie-0", XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, 1, pci_mux), - LANE("pcie-1", XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, 2, pci_mux), - LANE("pcie-2", XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, 3, pci_mux), - LANE("pcie-3", XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, 4, pci_mux), - LANE("pcie-4", XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, 5, pci_mux), - LANE("sata-0", XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3, 6, pci_mux), + /* Runtime data. */ + phandle_t xref; + bool enabled; + regulator_t supply_vbus; /* USB2, USB3 */ + bool internal; /* ULPI, USB2, USB3 */ + uint32_t companion; /* USB3 */ + struct padctl_lane *lane; }; -static int -xusbpadctl_mux_function(const struct padctl_lane *lane, char *fnc_name) -{ - int i; +static int usb3_port_init(struct padctl_softc *sc, struct padctl_port *port); - for (i = 0; i < lane->nmux; i++) { - if (strcmp(fnc_name, lane->mux[i]) == 0) - return (i); - } - - return (-1); +#define PORT(t, n, p, i) { \ + .type = t, \ + .name = n "-" #p, \ + .base_name = n, \ + .idx = p, \ + .init = i, \ } +static struct padctl_port ports_tbl[] = { + PORT(PADCTL_PORT_USB2, "usb2", 0, NULL), + PORT(PADCTL_PORT_USB2, "usb2", 1, NULL), + PORT(PADCTL_PORT_USB2, "usb2", 2, NULL), + PORT(PADCTL_PORT_ULPI, "ulpi", 0, NULL), + PORT(PADCTL_PORT_HSIC, "hsic", 0, NULL), + PORT(PADCTL_PORT_HSIC, "hsic", 1, NULL), + PORT(PADCTL_PORT_USB3, "usb3", 0, usb3_port_init), + PORT(PADCTL_PORT_USB3, "usb3", 1, usb3_port_init), +}; -static int -xusbpadctl_config_lane(struct xusbpadctl_softc *sc, char *lane_name, - const struct padctl_lane *lane, struct lane_cfg *cfg) -{ +/* Pads - a group of lannes. */ +enum padctl_pad_type { + PADCTL_PAD_USB2, + PADCTL_PAD_ULPI, + PADCTL_PAD_HSIC, + PADCTL_PAD_PCIE, + PADCTL_PAD_SATA, +}; - int tmp; - uint32_t reg; +struct padctl_lane; +struct padctl_pad { + const char *name; + enum padctl_pad_type type; + int (*powerup)(struct padctl_softc *sc, + struct padctl_lane *lane); + int (*powerdown)(struct padctl_softc *sc, + struct padctl_lane *lane); + /* Runtime data. */ + bool enabled; + struct padctl_lane *lanes[8]; /* Safe maximum value. */ + int nlanes; +}; - reg = bus_read_4(sc->mem_res, lane->reg); - if (cfg->function != NULL) { - tmp = xusbpadctl_mux_function(lane, cfg->function); - if (tmp == -1) { - device_printf(sc->dev, - "Unknown function %s for lane %s\n", cfg->function, - lane_name); - return (EINVAL); - } - reg &= ~(lane->mask << lane->shift); - reg |= (tmp & lane->mask) << lane->shift; - } - if (cfg->iddq != -1) { - if (lane->iddq == -1) { - device_printf(sc->dev, "Invalid IDDQ for lane %s\n", - lane_name); - return (EINVAL); - } - if (cfg->iddq != 0) - reg &= ~(1 << lane->iddq); - else - reg |= 1 << lane->iddq; - } +static int usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane); +static int usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane); +static int pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane); +static int pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane); +static int sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane); +static int sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane); - bus_write_4(sc->mem_res, lane->reg, reg); - return (0); +#define PAD(n, t, u, d) { \ + .name = n, \ + .type = t, \ + .powerup = u, \ + .powerdown = d, \ } +static struct padctl_pad pads_tbl[] = { + PAD("usb2", PADCTL_PAD_USB2, usb2_powerup, usb2_powerdown), + PAD("ulpi", PADCTL_PAD_ULPI, NULL, NULL), + PAD("hsic", PADCTL_PAD_HSIC, NULL, NULL), + PAD("pcie", PADCTL_PAD_PCIE, pcie_powerup, pcie_powerdown), + PAD("sata", PADCTL_PAD_SATA, sata_powerup, sata_powerdown), +}; -static const struct padctl_lane * -xusbpadctl_search_lane(char *lane_name) -{ - int i; +/* Lanes. */ +static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"}; +static char *usb_mux[] = {"snps", "xusb"}; +static char *pci_mux[] = {"pcie", "usb3-ss", "sata", "rsvd"}; - for (i = 0; i < nitems(lanes_tbl); i++) { - if (strcmp(lane_name, lanes_tbl[i].name) == 0) - return (&lanes_tbl[i]); - } +struct padctl_lane { + const char *name; + int idx; + bus_size_t reg; + uint32_t shift; + uint32_t mask; + char **mux; + int nmux; + /* Runtime data. */ + bool enabled; + phandle_t xref; + struct padctl_pad *pad; + struct padctl_port *port; + int mux_idx; - return (NULL); -} +}; -static int -xusbpadctl_config_node(struct xusbpadctl_softc *sc, char *lane_name, - struct lane_cfg *cfg) -{ - const struct padctl_lane *lane; - int rv; - - lane = xusbpadctl_search_lane(lane_name); - if (lane == NULL) { - device_printf(sc->dev, "Unknown lane: %s\n", lane_name); - return (ENXIO); - } - rv = xusbpadctl_config_lane(sc, lane_name, lane, cfg); - return (rv); +#define LANE(n, p, r, s, m, mx) { \ + .name = n "-" #p, \ + .idx = p, \ + .reg = r, \ + .shift = s, \ + .mask = m, \ + .mux = mx, \ + .nmux = nitems(mx), \ } +static struct padctl_lane lanes_tbl[] = { + LANE("usb2", 0, XUSB_PADCTL_USB2_PAD_MUX, 0, 0x3, otg_mux), + LANE("usb2", 1, XUSB_PADCTL_USB2_PAD_MUX, 2, 0x3, otg_mux), + LANE("usb2", 2, XUSB_PADCTL_USB2_PAD_MUX, 4, 0x3, otg_mux), + LANE("ulpi", 0, XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, usb_mux), + LANE("hsic", 0, XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, usb_mux), + LANE("hsic", 1, XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, usb_mux), + LANE("pcie", 0, XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, pci_mux), + LANE("pcie", 1, XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, pci_mux), + LANE("pcie", 2, XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, pci_mux), + LANE("pcie", 3, XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, pci_mux), + LANE("pcie", 4, XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, pci_mux), + LANE("sata", 0, XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3, pci_mux), +}; -static int -xusbpadctl_read_node(struct xusbpadctl_softc *sc, phandle_t node, - struct lane_cfg *cfg, char **lanes, int *llanes) -{ - int rv; +/* Define all possible mappings for USB3 port lanes */ +struct padctl_lane_map { + int port_idx; + enum padctl_pad_type pad_type; + int lane_idx; +}; - *llanes = OF_getprop_alloc(node, "nvidia,lanes", 1, (void **)lanes); - if (*llanes <= 0) - return (ENOENT); - - /* Read function (mux) settings. */ - rv = OF_getprop_alloc(node, "nvidia,function", 1, - (void **)&cfg->function); - if (rv <= 0) - cfg->function = NULL; - /* Read numeric properties. */ - rv = OF_getencprop(node, "nvidia,iddq", &cfg->iddq, - sizeof(cfg->iddq)); - if (rv <= 0) - cfg->iddq = -1; - return (0); +#define LANE_MAP(pi, pt, li) { \ + .port_idx = pi, \ + .pad_type = pt, \ + .lane_idx = li, \ } +static struct padctl_lane_map lane_map_tbl[] = { + LANE_MAP(0, PADCTL_PAD_PCIE, 0), /* port USB3-0 -> lane PCIE-0 */ + LANE_MAP(1, PADCTL_PAD_PCIE, 1), /* port USB3-1 -> lane PCIE-1 */ + /* -- or -- */ + LANE_MAP(1, PADCTL_PAD_SATA, 0), /* port USB3-1 -> lane SATA-0 */ +}; +static struct padctl_port *search_lane_port(struct padctl_softc *sc, + struct padctl_lane *lane); +/* ------------------------------------------------------------------------- + * + * PHY functions + */ static int -xusbpadctl_process_node(struct xusbpadctl_softc *sc, phandle_t node) +usb3_port_init(struct padctl_softc *sc, struct padctl_port *port) { - struct lane_cfg cfg; - char *lanes, *lname; - int i, len, llanes, rv; + uint32_t reg; - rv = xusbpadctl_read_node(sc, node, &cfg, &lanes, &llanes); - if (rv != 0) - return (rv); + reg = RD4(sc, XUSB_PADCTL_SS_PORT_MAP); + if (port->internal) + reg &= ~SS_PORT_MAP_PORT_INTERNAL(port->idx); + else + reg |= SS_PORT_MAP_PORT_INTERNAL(port->idx); + reg &= ~SS_PORT_MAP_PORT_MAP(port->idx, ~0); + reg |= SS_PORT_MAP_PORT_MAP(port->idx, port->companion); + WR4(sc, XUSB_PADCTL_SS_PORT_MAP, reg); - len = 0; - lname = lanes; - do { - i = strlen(lname) + 1; - rv = xusbpadctl_config_node(sc, lname, &cfg); - if (rv != 0) - device_printf(sc->dev, - "Cannot configure lane: %s: %d\n", lname, rv); + reg = RD4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx)); + reg &= ~IOPHY_USB3_PAD_CTL2_CDR_CNTL(~0); + reg &= ~IOPHY_USB3_PAD_CTL2_RX_EQ(~0); + reg &= ~IOPHY_USB3_PAD_CTL2_RX_WANDER(~0); + reg |= IOPHY_USB3_PAD_CTL2_CDR_CNTL(0x24); + reg |= IOPHY_USB3_PAD_CTL2_RX_EQ(0xF070); + reg |= IOPHY_USB3_PAD_CTL2_RX_WANDER(0xF); + WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL2(port->idx), reg); - len += i; - lname += i; - } while (len < llanes); + WR4(sc, XUSB_PADCTL_IOPHY_USB3_PAD_CTL4(port->idx), + 0x002008EE); - if (lanes != NULL) - OF_prop_free(lanes); - if (cfg.function != NULL) - OF_prop_free(cfg.function); - return (rv); -} + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); + reg &= ~ELPG_PROGRAM_SSP_ELPG_VCORE_DOWN(port->idx); + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); + DELAY(100); + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); + reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN_EARLY(port->idx); + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); + DELAY(100); -static int -xusbpadctl_pinctrl_cfg(device_t dev, phandle_t cfgxref) -{ - struct xusbpadctl_softc *sc; - phandle_t node, cfgnode; - int rv; + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); + reg &= ~ELPG_PROGRAM_SSP_ELPG_CLAMP_EN(port->idx); + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); + DELAY(100); - sc = device_get_softc(dev); - cfgnode = OF_node_from_xref(cfgxref); - - rv = 0; - for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) { - if (!fdt_is_enabled(node)) - continue; - rv = xusbpadctl_process_node(sc, node); - if (rv != 0) - return (rv); - } - - return (rv); + return (0); } static int -xusbpadctl_phy_pcie_powerup(struct xusbpadctl_softc *sc) +pcie_powerup(struct padctl_softc *sc, struct padctl_lane *lane) { uint32_t reg; int i; - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL(~0); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); reg |= IOPHY_PLL_P0_CTL2_REFCLKBUF_EN; reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_EN; reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); reg |= IOPHY_PLL_P0_CTL1_PLL_RST; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg); DELAY(100); - for (i = 0; i < 100; i++) { - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + for (i = 100; i > 0; i--) { + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); if (reg & IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) - return (0); + break; DELAY(10); } + if (i <= 0) { + device_printf(sc->dev, "Failed to power up PCIe phy\n"); + return (ETIMEDOUT); + } + reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX); + reg |= USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx); + WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg); - return (ETIMEDOUT); + return (0); } - static int -xusbpadctl_phy_pcie_powerdown(struct xusbpadctl_softc *sc) +pcie_powerdown(struct padctl_softc *sc, struct padctl_lane *lane) { uint32_t reg; - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX); + reg &= ~USB3_PAD_MUX_PCIE_IDDQ_DISABLE(lane->idx); + WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg); + + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); reg &= ~IOPHY_PLL_P0_CTL1_PLL_RST; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg); DELAY(100); + return (0); } static int -xusbpadctl_phy_sata_powerup(struct xusbpadctl_softc *sc) +sata_powerup(struct padctl_softc *sc, struct padctl_lane *lane) { uint32_t reg; int i; - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); reg &= ~IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; reg &= ~IOPHY_PLL_S0_CTL1_PLL_IDDQ; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); reg |= IOPHY_PLL_S0_CTL1_PLL1_MODE; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); for (i = 100; i >= 0; i--) { - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); if (reg & IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) break; DELAY(100); } if (i <= 0) { device_printf(sc->dev, "Failed to power up SATA phy\n"); return (ETIMEDOUT); } + reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX); + reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L; + WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg); + reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX); + reg |= USB3_PAD_MUX_SATA_IDDQ_DISABLE; + WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg); + return (0); } static int -xusbpadctl_phy_sata_powerdown(struct xusbpadctl_softc *sc) +sata_powerdown(struct padctl_softc *sc, struct padctl_lane *lane) { uint32_t reg; - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_USB3_PAD_MUX); + reg &= ~USB3_PAD_MUX_SATA_IDDQ_DISABLE; + WR4(sc, XUSB_PADCTL_USB3_PAD_MUX, reg); + + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); reg &= ~IOPHY_PLL_S0_CTL1_PLL_RST_L; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); reg &= ~IOPHY_PLL_S0_CTL1_PLL1_MODE; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); reg |= IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; reg |= IOPHY_PLL_S0_CTL1_PLL_IDDQ; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + reg = RD4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ; - bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg); + WR4(sc, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg); DELAY(100); return (0); } static int -xusbpadctl_phy_powerup(struct xusbpadctl_softc *sc) +usb2_powerup(struct padctl_softc *sc, struct padctl_lane *lane) { uint32_t reg; + struct padctl_port *port; + int rv; - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM); + port = search_lane_port(sc, lane); + if (port == NULL) { + device_printf(sc->dev, "Cannot find port for lane: %s\n", + lane->name); + } + reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); + reg &= ~USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(~0); + reg &= ~USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(~0); + reg |= USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL(sc->hs_squelch_level); + reg |= USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL(5); + WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg); + + reg = RD4(sc, XUSB_PADCTL_USB2_PORT_CAP); + reg &= ~USB2_PORT_CAP_PORT_CAP(lane->idx, ~0); + reg |= USB2_PORT_CAP_PORT_CAP(lane->idx, USB2_PORT_CAP_PORT_CAP_HOST); + WR4(sc, XUSB_PADCTL_USB2_PORT_CAP, reg); + + reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx)); + reg &= ~USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(~0); + reg &= ~USB2_OTG_PAD_CTL0_HS_SLEW(~0); + reg &= ~USB2_OTG_PAD_CTL0_LS_RSLEW(~0); + reg &= ~USB2_OTG_PAD_CTL0_PD; + reg &= ~USB2_OTG_PAD_CTL0_PD2; + reg &= ~USB2_OTG_PAD_CTL0_PD_ZI; + + reg |= USB2_OTG_PAD_CTL0_HS_SLEW(14); + if (lane->idx == 0) { + reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_0); + reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(3); + } else { + reg |= USB2_OTG_PAD_CTL0_HS_CURR_LEVEL(sc->hs_curr_level_123); + reg |= USB2_OTG_PAD_CTL0_LS_RSLEW(0); + } + WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL0(lane->idx), reg); + + reg = RD4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx)); + reg &= ~USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(~0); + reg &= ~USB2_OTG_PAD_CTL1_HS_IREF_CAP(~0); + reg &= ~USB2_OTG_PAD_CTL1_PD_DR; + reg &= ~USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP; + reg &= ~USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP; + + reg |= USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ(sc->hs_term_range_adj); + reg |= USB2_OTG_PAD_CTL1_HS_IREF_CAP(sc->hs_iref_cap); + WR4(sc, XUSB_PADCTL_USB2_OTG_PAD_CTL1(lane->idx), reg); + + if (port != NULL && port->supply_vbus != NULL) { + rv = regulator_enable(port->supply_vbus); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable vbus regulator\n"); + return (rv); + } + } + reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); + reg &= ~USB2_BIAS_PAD_CTL0_PD; + WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg); + + return (0); +} + +static int +usb2_powerdown(struct padctl_softc *sc, struct padctl_lane *lane) +{ + uint32_t reg; + struct padctl_port *port; + int rv; + + port = search_lane_port(sc, lane); + if (port == NULL) { + device_printf(sc->dev, "Cannot find port for lane: %s\n", + lane->name); + } + reg = RD4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); + reg |= USB2_BIAS_PAD_CTL0_PD; + WR4(sc, XUSB_PADCTL_USB2_BIAS_PAD_CTL0, reg); + + if (port != NULL && port->supply_vbus != NULL) { + rv = regulator_enable(port->supply_vbus); + if (rv != 0) { + device_printf(sc->dev, + "Cannot disable vbus regulator\n"); + return (rv); + } + } + return (0); +} + + +static int +phy_powerup(struct padctl_softc *sc) +{ + uint32_t reg; + + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); + reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); + DELAY(100); + + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM); + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM); - reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); - DELAY(100); - return (0); } static int -xusbpadctl_phy_powerdown(struct xusbpadctl_softc *sc) +phy_powerdown(struct padctl_softc *sc) { uint32_t reg; - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM); - reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); - DELAY(100); - - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM); + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); DELAY(100); - reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM); + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg); + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); DELAY(100); + reg = RD4(sc, XUSB_PADCTL_ELPG_PROGRAM); + reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; + WR4(sc, XUSB_PADCTL_ELPG_PROGRAM, reg); + DELAY(100); + return (0); } static int xusbpadctl_phy_enable(device_t dev, intptr_t id, bool enable) { - struct xusbpadctl_softc *sc; + struct padctl_softc *sc; + struct padctl_lane *lane; + struct padctl_pad *pad; int rv; sc = device_get_softc(dev); - if ((id != TEGRA_XUSB_PADCTL_PCIE) && - (id != TEGRA_XUSB_PADCTL_SATA)) { + if (id < 0 || id >= nitems(lanes_tbl)) { device_printf(dev, "Unknown phy: %d\n", id); return (ENXIO); } - - rv = 0; + lane = lanes_tbl + id; + if (!lane->enabled) { + device_printf(dev, "Lane is not enabled/configured: %s\n", + lane->name); + return (ENXIO); + } + pad = lane->pad; if (enable) { if (sc->phy_ena_cnt == 0) { - rv = xusbpadctl_phy_powerup(sc); + rv = phy_powerup(sc); if (rv != 0) return (rv); } sc->phy_ena_cnt++; } - if (id == TEGRA_XUSB_PADCTL_PCIE) { - if (enable) - rv = xusbpadctl_phy_pcie_powerup(sc); - else - rv = xusbpadctl_phy_pcie_powerdown(sc); - if (rv != 0) - return (rv); - } else if (id == TEGRA_XUSB_PADCTL_SATA) { - if (enable) - rv = xusbpadctl_phy_sata_powerup(sc); - else - rv = xusbpadctl_phy_sata_powerdown(sc); - if (rv != 0) - return (rv); - } + if (enable) + rv = pad->powerup(sc, lane); + else + rv = pad->powerdown(sc, lane); + if (rv != 0) + return (rv); + if (!enable) { if (sc->phy_ena_cnt == 1) { - rv = xusbpadctl_phy_powerdown(sc); + rv = phy_powerdown(sc); if (rv != 0) return (rv); } sc->phy_ena_cnt--; } return (0); } static int +xusbpadctl_phy_map(device_t provider, phandle_t xref, int ncells, + pcell_t *cells, intptr_t *id) +{ + int i; + + if (ncells != 0) + return (ERANGE); + + for (i = 0; i < nitems(lanes_tbl); i++) { + if (lanes_tbl[i].xref == xref) { + *id = i; + return (0); + } + } + return (ENXIO); +} + +/* ------------------------------------------------------------------------- + * + * FDT processing + */ +static struct padctl_port * +search_port(struct padctl_softc *sc, char *port_name) +{ + int i; + + for (i = 0; i < nitems(ports_tbl); i++) { + if (strcmp(port_name, ports_tbl[i].name) == 0) + return (&ports_tbl[i]); + } + return (NULL); +} + +static struct padctl_port * +search_lane_port(struct padctl_softc *sc, struct padctl_lane *lane) +{ + int i; + + for (i = 0; i < nitems(ports_tbl); i++) { + if (!ports_tbl[i].enabled) + continue; + if (ports_tbl[i].lane == lane) + return (ports_tbl + i); + } + return (NULL); +} + +static struct padctl_lane * +search_lane(struct padctl_softc *sc, char *lane_name) +{ + int i; + + for (i = 0; i < nitems(lanes_tbl); i++) { + if (strcmp(lane_name, lanes_tbl[i].name) == 0) + return (lanes_tbl + i); + } + return (NULL); +} + +static struct padctl_lane * +search_pad_lane(struct padctl_softc *sc, enum padctl_pad_type type, int idx) +{ + int i; + + for (i = 0; i < nitems(lanes_tbl); i++) { + if (!lanes_tbl[i].enabled) + continue; + if (type == lanes_tbl[i].pad->type && idx == lanes_tbl[i].idx) + return (lanes_tbl + i); + } + return (NULL); +} + +static struct padctl_lane * +search_usb3_pad_lane(struct padctl_softc *sc, int idx) +{ + int i; + struct padctl_lane *lane, *tmp; + + lane = NULL; + for (i = 0; i < nitems(lane_map_tbl); i++) { + if (idx != lane_map_tbl[i].port_idx) + continue; + tmp = search_pad_lane(sc, lane_map_tbl[i].pad_type, + lane_map_tbl[i].lane_idx); + if (tmp == NULL) + continue; + if (strcmp(tmp->mux[tmp->mux_idx], "usb3-ss") != 0) + continue; + if (lane != NULL) { + device_printf(sc->dev, "Duplicated mappings found for" + " lanes: %s and %s\n", lane->name, tmp->name); + return (NULL); + } + lane = tmp; + } + return (lane); +} + +static struct padctl_pad * +search_pad(struct padctl_softc *sc, char *pad_name) +{ + int i; + + for (i = 0; i < nitems(pads_tbl); i++) { + if (strcmp(pad_name, pads_tbl[i].name) == 0) + return (pads_tbl + i); + } + return (NULL); +} + +static int +search_mux(struct padctl_softc *sc, struct padctl_lane *lane, char *fnc_name) +{ + int i; + + for (i = 0; i < lane->nmux; i++) { + if (strcmp(fnc_name, lane->mux[i]) == 0) + return (i); + } + return (-1); +} + +static int +config_lane(struct padctl_softc *sc, struct padctl_lane *lane) +{ + uint32_t reg; + + reg = RD4(sc, lane->reg); + reg &= ~(lane->mask << lane->shift); + reg |= (lane->mux_idx & lane->mask) << lane->shift; + WR4(sc, lane->reg, reg); + return (0); +} + +static int +process_lane(struct padctl_softc *sc, phandle_t node, struct padctl_pad *pad) +{ + struct padctl_lane *lane; + char *name; + char *function; + int rv; + + name = NULL; + function = NULL; + rv = OF_getprop_alloc(node, "name", 1, (void **)&name); + if (rv <= 0) { + device_printf(sc->dev, "Cannot read lane name.\n"); + return (ENXIO); + } + + lane = search_lane(sc, name); + if (lane == NULL) { + device_printf(sc->dev, "Unknown lane: %s\n", name); + rv = ENXIO; + goto end; + } + + /* Read function (mux) settings. */ + rv = OF_getprop_alloc(node, "nvidia,function", 1, (void **)&function); + if (rv <= 0) { + device_printf(sc->dev, "Cannot read lane function.\n"); + rv = ENXIO; + goto end; + } + + lane->mux_idx = search_mux(sc, lane, function); + if (lane->mux_idx == ~0) { + device_printf(sc->dev, "Unknown function %s for lane %s\n", + function, name); + rv = ENXIO; + goto end; + } + + rv = config_lane(sc, lane); + if (rv != 0) { + device_printf(sc->dev, "Cannot configure lane: %s: %d\n", + name, rv); + rv = ENXIO; + goto end; + } + lane->xref = OF_xref_from_node(node); + lane->pad = pad; + lane->enabled = true; + pad->lanes[pad->nlanes++] = lane; + rv = 0; + +end: + if (name != NULL) + OF_prop_free(name); + if (function != NULL) + OF_prop_free(function); + return (rv); +} + +static int +process_pad(struct padctl_softc *sc, phandle_t node) +{ + phandle_t xref; + struct padctl_pad *pad; + char *name; + int rv; + + name = NULL; + rv = OF_getprop_alloc(node, "name", 1, (void **)&name); + if (rv <= 0) { + device_printf(sc->dev, "Cannot read pad name.\n"); + return (ENXIO); + } + pad = search_pad(sc, name); + if (pad == NULL) { + device_printf(sc->dev, "Unknown pad: %s\n", name); + rv = ENXIO; + goto end; + } + + /* Read and process associated lanes. */ + node = ofw_bus_find_child(node, "lanes"); + if (node <= 0) { + device_printf(sc->dev, "Cannot find regulators subnode\n"); + rv = ENXIO; + goto end; + } + + for (node = OF_child(node); node != 0; node = OF_peer(node)) { + if (!fdt_is_enabled(node)) + continue; + + rv = process_lane(sc, node, pad); + if (rv != 0) + goto end; + + xref = OF_xref_from_node(node); + OF_device_register_xref(xref, sc->dev); + } + pad->enabled = true; + rv = 0; +end: + if (name != NULL) + OF_prop_free(name); + return (rv); +} + +static int +process_port(struct padctl_softc *sc, phandle_t node) +{ + + struct padctl_port *port; + char *name; + int rv; + + name = NULL; + rv = OF_getprop_alloc(node, "name", 1, (void **)&name); + if (rv <= 0) { + device_printf(sc->dev, "Cannot read port name.\n"); + return (ENXIO); + } + + port = search_port(sc, name); + if (port == NULL) { + device_printf(sc->dev, "Unknown port: %s\n", name); + rv = ENXIO; + goto end; + } + + if (port->type == PADCTL_PORT_USB3) { + rv = OF_getencprop(node, "nvidia,usb2-companion", + &(port->companion), sizeof(port->companion)); + if (rv <= 0) { + device_printf(sc->dev, + "Missing 'nvidia,usb2-companion' property " + "for port: %s\n", name); + rv = ENXIO; + goto end; + } + } + + if (OF_hasprop(node, "vbus-supply")) { + rv = regulator_get_by_ofw_property(sc->dev, 0, + "vbus-supply", &port->supply_vbus); + if (rv <= 0) { + device_printf(sc->dev, + "Cannot get 'vbus-supply' regulator " + "for port: %s\n", name); + rv = ENXIO; + goto end; + } + } + + if (OF_hasprop(node, "nvidia,internal")) + port->internal = true; + /* Find assigned lane */ + if (port->lane == NULL) { + switch(port->type) { + /* Routing is fixed for USB2, ULPI AND HSIC. */ + case PADCTL_PORT_USB2: + port->lane = search_pad_lane(sc, PADCTL_PAD_USB2, + port->idx); + break; + case PADCTL_PORT_ULPI: + port->lane = search_pad_lane(sc, PADCTL_PAD_ULPI, + port->idx); + break; + case PADCTL_PORT_HSIC: + port->lane = search_pad_lane(sc, PADCTL_PAD_HSIC, + port->idx); + break; + case PADCTL_PORT_USB3: + port->lane = search_usb3_pad_lane(sc, port->idx); + break; + } + } + if (port->lane == NULL) { + device_printf(sc->dev, "Cannot find lane for port: %s\n", name); + rv = ENXIO; + goto end; + } + port->enabled = true; + rv = 0; +end: + if (name != NULL) + OF_prop_free(name); + return (rv); +} + +static int +parse_fdt(struct padctl_softc *sc, phandle_t base_node) +{ + phandle_t node; + int rv; + + rv = 0; + node = ofw_bus_find_child(base_node, "pads"); + + if (node <= 0) { + device_printf(sc->dev, "Cannot find pads subnode.\n"); + return (ENXIO); + } + for (node = OF_child(node); node != 0; node = OF_peer(node)) { + if (!fdt_is_enabled(node)) + continue; + rv = process_pad(sc, node); + if (rv != 0) + return (rv); + } + + node = ofw_bus_find_child(base_node, "ports"); + if (node <= 0) { + device_printf(sc->dev, "Cannot find ports subnode.\n"); + return (ENXIO); + } + for (node = OF_child(node); node != 0; node = OF_peer(node)) { + if (!fdt_is_enabled(node)) + continue; + rv = process_port(sc, node); + if (rv != 0) + return (rv); + } + + return (0); +} + +static void +load_calibration(struct padctl_softc *sc) +{ + uint32_t reg; + + /* All XUSB pad calibrations are packed into single dword.*/ + reg = tegra_fuse_read_4(FUSE_XUSB_CALIB); + sc->hs_curr_level_0 = FUSE_XUSB_CALIB_HS_CURR_LEVEL_0(reg); + sc->hs_curr_level_123 = FUSE_XUSB_CALIB_HS_CURR_LEVEL_123(reg); + sc->hs_iref_cap = FUSE_XUSB_CALIB_HS_IREF_CAP(reg); + sc->hs_squelch_level = FUSE_XUSB_CALIB_HS_SQUELCH_LEVEL(reg); + sc->hs_term_range_adj = FUSE_XUSB_CALIB_HS_TERM_RANGE_ADJ(reg); +} + +/* ------------------------------------------------------------------------- + * + * BUS functions + */ +static int xusbpadctl_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) return (ENXIO); device_set_desc(dev, "Tegra XUSB phy"); return (BUS_PROBE_DEFAULT); } static int xusbpadctl_detach(device_t dev) { /* This device is always present. */ return (EBUSY); } static int xusbpadctl_attach(device_t dev) { - struct xusbpadctl_softc * sc; - int rid, rv; + struct padctl_softc * sc; + int i, rid, rv; + struct padctl_port *port; phandle_t node; sc = device_get_softc(dev); sc->dev = dev; + node = ofw_bus_get_node(dev); rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { device_printf(dev, "Cannot allocate memory resources\n"); return (ENXIO); } - node = ofw_bus_get_node(dev); rv = hwreset_get_by_ofw_name(dev, 0, "padctl", &sc->rst); if (rv != 0) { device_printf(dev, "Cannot get 'padctl' reset: %d\n", rv); return (rv); } rv = hwreset_deassert(sc->rst); if (rv != 0) { device_printf(dev, "Cannot unreset 'padctl' reset: %d\n", rv); return (rv); } - /* Register as a pinctrl device and use default configuration */ - fdt_pinctrl_register(dev, NULL); - fdt_pinctrl_configure_by_name(dev, "default"); - phy_register_provider(dev); + load_calibration(sc); + rv = parse_fdt(sc, node); + if (rv != 0) { + device_printf(dev, "Cannot parse fdt configuration: %d\n", rv); + return (rv); + } + for (i = 0; i < nitems(ports_tbl); i++) { + port = ports_tbl + i; + if (!port->enabled) + continue; + if (port->init == NULL) + continue; + rv = port->init(sc, port); + if (rv != 0) { + device_printf(dev, "Cannot init port '%s'\n", + port->name); + return (rv); + } + } return (0); } static device_method_t tegra_xusbpadctl_methods[] = { /* Device interface */ DEVMETHOD(device_probe, xusbpadctl_probe), DEVMETHOD(device_attach, xusbpadctl_attach), DEVMETHOD(device_detach, xusbpadctl_detach), - /* fdt_pinctrl interface */ - DEVMETHOD(fdt_pinctrl_configure, xusbpadctl_pinctrl_cfg), - /* phy interface */ DEVMETHOD(phy_enable, xusbpadctl_phy_enable), + DEVMETHOD(phy_map, xusbpadctl_phy_map), DEVMETHOD_END }; static devclass_t tegra_xusbpadctl_devclass; static DEFINE_CLASS_0(xusbpadctl, tegra_xusbpadctl_driver, - tegra_xusbpadctl_methods, sizeof(struct xusbpadctl_softc)); + tegra_xusbpadctl_methods, sizeof(struct padctl_softc)); EARLY_DRIVER_MODULE(tegra_xusbpadctl, simplebus, tegra_xusbpadctl_driver, tegra_xusbpadctl_devclass, NULL, NULL, 73); Index: stable/11/sys/arm/nvidia/tegra_ahci.c =================================================================== --- stable/11/sys/arm/nvidia/tegra_ahci.c (revision 332009) +++ stable/11/sys/arm/nvidia/tegra_ahci.c (revision 332010) @@ -1,625 +1,625 @@ /*- * Copyright (c) 2016 Michal Meloun * 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 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 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 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 __FBSDID("$FreeBSD$"); /* * AHCI driver for Tegra SoCs. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define AHCI_WR4(_sc, _r, _v) bus_write_4((_sc)->ctlr.r_mem, (_r), (_v)) #define AHCI_RD4(_sc, _r) bus_read_4((_sc)->ctlr.r_mem, (_r)) #define SATA_WR4(_sc, _r, _v) bus_write_4((_sc)->sata_mem, (_r), (_v)) #define SATA_RD4(_sc, _r) bus_read_4((_sc)->sata_mem, (_r)) static struct ofw_compat_data compat_data[] = { {"nvidia,tegra124-ahci", 1}, {NULL, 0} }; struct tegra_ahci_sc { struct ahci_controller ctlr; /* Must be first */ device_t dev; struct resource *sata_mem; clk_t clk_sata; clk_t clk_sata_oob; clk_t clk_pll_e; clk_t clk_cml; hwreset_t hwreset_sata; hwreset_t hwreset_sata_oob; hwreset_t hwreset_sata_cold; regulator_t supply_hvdd; regulator_t supply_vddio; regulator_t supply_avdd; regulator_t supply_target_5v; regulator_t supply_target_12v; phy_t phy; }; struct sata_pad_calibration { uint32_t gen1_tx_amp; uint32_t gen1_tx_peak; uint32_t gen2_tx_amp; uint32_t gen2_tx_peak; }; static const struct sata_pad_calibration tegra124_pad_calibration[] = { {0x18, 0x04, 0x18, 0x0a}, {0x0e, 0x04, 0x14, 0x0a}, {0x0e, 0x07, 0x1a, 0x0e}, {0x14, 0x0e, 0x1a, 0x0e}, }; #define SATA_CONFIGURATION 0x180 #define SATA_CONFIGURATION_EN_FPCI (1 << 0) #define SATA_FPCI_BAR5 0x94 #define SATA_FPCI_BAR5_START_SHIFT 4 #define SATA_INTR_MASK 0x188 #define SATA_INTR_MASK_IP_INT_MASK (1 << 16) #define SCFG_OFFSET 0x1000 #define T_SATA0_CFG_1 0x04 #define T_SATA0_CFG_1_IO_SPACE (1 << 0) #define T_SATA0_CFG_1_MEMORY_SPACE (1 << 1) #define T_SATA0_CFG_1_BUS_MASTER (1 << 2) #define T_SATA0_CFG_1_SERR (1 << 8) #define T_SATA0_CFG_9 0x24 #define T_SATA0_CFG_9_BASE_ADDRESS_SHIFT 13 #define T_SATA0_AHCI_HBA_CAP_BKDR 0x300 #define T_SATA0_BKDOOR_CC 0x4a4 #define T_SATA0_CFG_SATA 0x54c #define T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN (1 << 12) #define T_SATA0_CFG_MISC 0x550 #define T_SATA0_INDEX 0x680 #define T_SATA0_CHX_PHY_CTRL1_GEN1 0x690 #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK 0xff #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT 8 #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK 0xff #define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT 0 #define T_SATA0_CHX_PHY_CTRL1_GEN2 0x694 #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK 0xff #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT 12 #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK 0xff #define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT 0 #define T_SATA0_CHX_PHY_CTRL2 0x69c #define T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1 0x23 #define T_SATA0_CHX_PHY_CTRL11 0x6d0 #define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ (0x2800 << 16) #define FUSE_SATA_CALIB 0x124 #define FUSE_SATA_CALIB_MASK 0x3 #define SATA_AUX_MISC_CNTL 0x1108 #define SATA_AUX_PAD_PLL_CTRL_0 0x1120 #define SATA_AUX_PAD_PLL_CTRL_1 0x1124 #define SATA_AUX_PAD_PLL_CTRL_2 0x1128 #define SATA_AUX_PAD_PLL_CTRL_3 0x112c #define T_AHCI_HBA_CCC_PORTS 0x0018 #define T_AHCI_HBA_CAP_BKDR 0x00A0 #define T_AHCI_HBA_CAP_BKDR_S64A (1 << 31) #define T_AHCI_HBA_CAP_BKDR_SNCQ (1 << 30) #define T_AHCI_HBA_CAP_BKDR_SSNTF (1 << 29) #define T_AHCI_HBA_CAP_BKDR_SMPS (1 << 28) #define T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP (1 << 27) #define T_AHCI_HBA_CAP_BKDR_SALP (1 << 26) #define T_AHCI_HBA_CAP_BKDR_SAL (1 << 25) #define T_AHCI_HBA_CAP_BKDR_SUPP_CLO (1 << 24) #define T_AHCI_HBA_CAP_BKDR_INTF_SPD_SUPP(x) (((x) & 0xF) << 20) #define T_AHCI_HBA_CAP_BKDR_SUPP_NONZERO_OFFSET (1 << 19) #define T_AHCI_HBA_CAP_BKDR_SUPP_AHCI_ONLY (1 << 18) #define T_AHCI_HBA_CAP_BKDR_SUPP_PM (1 << 17) #define T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING (1 << 16) #define T_AHCI_HBA_CAP_BKDR_PIO_MULT_DRQ_BLK (1 << 15) #define T_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP (1 << 14) #define T_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP (1 << 13) #define T_AHCI_HBA_CAP_BKDR_NUM_CMD_SLOTS(x) (((x) & 0x1F) << 8) #define T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING (1 << 7) #define T_AHCI_HBA_CAP_BKDR_ENCL_MGMT_SUPP (1 << 6) #define T_AHCI_HBA_CAP_BKDR_EXT_SATA (1 << 5) #define T_AHCI_HBA_CAP_BKDR_NUM_PORTS(x) (((x) & 0xF) << 0) #define T_AHCI_PORT_BKDR 0x0170 #define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE_VAL(x) (((x) & 0xFF) << 24) #define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE_VAL(x) (((x) & 0x1F) << 16) #define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE (1 << 15) #define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE (1 << 14) #define T_AHCI_PORT_BKDR_PXDEVSLP_DM(x) (((x) & 0xF) << 10) #define T_AHCI_PORT_BKDR_PORT_UNCONNECTED (1 << 9) #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_CLAMP_THIS_CH (1 << 8) #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_UNCLAMP (1 << 7) #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_CLAMP (1 << 6) #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_UNCLAMP (1 << 5) #define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_CLAMP (1 << 4) #define T_AHCI_PORT_BKDR_HOTPLUG_CAP (1 << 3) #define T_AHCI_PORT_BKDR_MECH_SWITCH (1 << 2) #define T_AHCI_PORT_BKDR_COLD_PRSN_DET (1 << 1) #define T_AHCI_PORT_BKDR_EXT_SATA_SUPP (1 << 0) static int get_fdt_resources(struct tegra_ahci_sc *sc, phandle_t node) { int rv; rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-supply", &sc->supply_hvdd ); if (rv != 0) { device_printf(sc->dev, "Cannot get 'hvdd' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "vddio-supply", &sc->supply_vddio); if (rv != 0) { device_printf(sc->dev, "Cannot get 'vddio' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-supply", &sc->supply_avdd); if (rv != 0) { device_printf(sc->dev, "Cannot get 'avdd' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "target-5v-supply", &sc->supply_target_5v); if (rv != 0) { device_printf(sc->dev, "Cannot get 'target-5v' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "target-12v-supply", &sc->supply_target_12v); if (rv != 0) { device_printf(sc->dev, "Cannot get 'target-12v' regulator\n"); return (ENXIO); } rv = hwreset_get_by_ofw_name(sc->dev, 0, "sata", &sc->hwreset_sata ); if (rv != 0) { device_printf(sc->dev, "Cannot get 'sata' reset\n"); return (ENXIO); } rv = hwreset_get_by_ofw_name(sc->dev, 0, "sata-oob", &sc->hwreset_sata_oob); if (rv != 0) { device_printf(sc->dev, "Cannot get 'sata oob' reset\n"); return (ENXIO); } rv = hwreset_get_by_ofw_name(sc->dev, 0, "sata-cold", &sc->hwreset_sata_cold); if (rv != 0) { device_printf(sc->dev, "Cannot get 'sata cold' reset\n"); return (ENXIO); } - rv = phy_get_by_ofw_name(sc->dev, 0, "sata-phy", &sc->phy); + rv = phy_get_by_ofw_name(sc->dev, 0, "sata-0", &sc->phy); if (rv != 0) { device_printf(sc->dev, "Cannot get 'sata' phy\n"); return (ENXIO); } rv = clk_get_by_ofw_name(sc->dev, 0, "sata", &sc->clk_sata); if (rv != 0) { device_printf(sc->dev, "Cannot get 'sata' clock\n"); return (ENXIO); } rv = clk_get_by_ofw_name(sc->dev, 0, "sata-oob", &sc->clk_sata_oob); if (rv != 0) { device_printf(sc->dev, "Cannot get 'sata oob' clock\n"); return (ENXIO); } rv = clk_get_by_ofw_name(sc->dev, 0, "cml1", &sc->clk_cml); if (rv != 0) { device_printf(sc->dev, "Cannot get 'cml1' clock\n"); return (ENXIO); } rv = clk_get_by_ofw_name(sc->dev, 0, "pll_e", &sc->clk_pll_e); if (rv != 0) { device_printf(sc->dev, "Cannot get 'pll_e' clock\n"); return (ENXIO); } return (0); } static int enable_fdt_resources(struct tegra_ahci_sc *sc) { int rv; rv = regulator_enable(sc->supply_hvdd); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'hvdd' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_vddio); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'vddio' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_avdd); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'avdd' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_target_5v); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'target-5v' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_target_12v); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'sc->target-12v' regulator\n"); return (rv); } /* Stop clocks */ clk_stop(sc->clk_sata); clk_stop(sc->clk_sata_oob); tegra_powergate_power_off(TEGRA_POWERGATE_SAX); rv = hwreset_assert(sc->hwreset_sata); if (rv != 0) { device_printf(sc->dev, "Cannot assert 'sata' reset\n"); return (rv); } rv = hwreset_assert(sc->hwreset_sata_oob); if (rv != 0) { device_printf(sc->dev, "Cannot assert 'sata oob' reset\n"); return (rv); } rv = hwreset_assert(sc->hwreset_sata_cold); if (rv != 0) { device_printf(sc->dev, "Cannot assert 'sata cold' reset\n"); return (rv); } rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_SAX, sc->clk_sata, sc->hwreset_sata); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'SAX' powergate\n"); return (rv); } rv = clk_enable(sc->clk_sata_oob); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'sata oob' clock\n"); return (rv); } rv = clk_enable(sc->clk_cml); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'cml' clock\n"); return (rv); } rv = clk_enable(sc->clk_pll_e); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'pll e' clock\n"); return (rv); } rv = hwreset_deassert(sc->hwreset_sata_cold); if (rv != 0) { device_printf(sc->dev, "Cannot unreset 'sata cold' reset\n"); return (rv); } rv = hwreset_deassert(sc->hwreset_sata_oob); if (rv != 0) { device_printf(sc->dev, "Cannot unreset 'sata oob' reset\n"); return (rv); } rv = phy_enable(sc->dev, sc->phy); if (rv != 0) { device_printf(sc->dev, "Cannot enable SATA phy\n"); return (rv); } return (0); } static int tegra_ahci_ctrl_init(struct tegra_ahci_sc *sc) { uint32_t val; const struct sata_pad_calibration *calib; val = SATA_RD4(sc, SATA_CONFIGURATION); val |= SATA_CONFIGURATION_EN_FPCI; SATA_WR4(sc, SATA_CONFIGURATION, val); /* Pad calibration. */ val = tegra_fuse_read_4(FUSE_SATA_CALIB); calib = tegra124_pad_calibration + (val & FUSE_SATA_CALIB_MASK); SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 1); val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1); val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT); val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT); val |= calib->gen1_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT; val |= calib->gen1_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT; SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1, val); val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2); val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT); val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT); val |= calib->gen2_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT; val |= calib->gen2_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT; SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2, val); SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11, T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ); SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2, T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1); SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 0); /* Set device ID. */ val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA); val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val); SATA_WR4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC, 0x01060100); val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA); val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN; SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val); /* Enable IO & memory access, bus master mode */ val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_1); val |= T_SATA0_CFG_1_IO_SPACE; val |= T_SATA0_CFG_1_MEMORY_SPACE; val |= T_SATA0_CFG_1_BUS_MASTER; val |= T_SATA0_CFG_1_SERR; SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_1, val); /* SATA MMIO. */ SATA_WR4(sc, SATA_FPCI_BAR5, 0x10000 << SATA_FPCI_BAR5_START_SHIFT); /* AHCI bar */ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_9, 0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT); /* Unmask interrupts. */ val = SATA_RD4(sc, SATA_INTR_MASK); val |= SATA_INTR_MASK_IP_INT_MASK; SATA_WR4(sc, SATA_INTR_MASK, val); return (0); } static int tegra_ahci_ctlr_reset(device_t dev) { struct tegra_ahci_sc *sc; int rv; uint32_t reg; sc = device_get_softc(dev); rv = ahci_ctlr_reset(dev); if (rv != 0) return (0); AHCI_WR4(sc, T_AHCI_HBA_CCC_PORTS, 1); /* Overwrite AHCI capabilites. */ reg = AHCI_RD4(sc, T_AHCI_HBA_CAP_BKDR); reg &= ~T_AHCI_HBA_CAP_BKDR_NUM_PORTS(~0); reg |= T_AHCI_HBA_CAP_BKDR_NUM_PORTS(0); reg |= T_AHCI_HBA_CAP_BKDR_EXT_SATA; reg |= T_AHCI_HBA_CAP_BKDR_ENCL_MGMT_SUPP; reg |= T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING; reg |= T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING; reg |= T_AHCI_HBA_CAP_BKDR_SUPP_PM; reg |= T_AHCI_HBA_CAP_BKDR_SUPP_CLO; reg |= T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP; AHCI_WR4(sc, T_AHCI_HBA_CAP_BKDR, reg); /* Overwrite AHCI portcapabilites. */ reg = AHCI_RD4(sc, T_AHCI_PORT_BKDR); reg |= T_AHCI_PORT_BKDR_COLD_PRSN_DET; reg |= T_AHCI_PORT_BKDR_HOTPLUG_CAP; reg |= T_AHCI_PORT_BKDR_EXT_SATA_SUPP; AHCI_WR4(sc, T_AHCI_PORT_BKDR, reg); return (0); } static int tegra_ahci_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) return (ENXIO); device_set_desc_copy(dev, "AHCI SATA controller"); return (BUS_PROBE_DEFAULT); } static int tegra_ahci_attach(device_t dev) { struct tegra_ahci_sc *sc; struct ahci_controller *ctlr; phandle_t node; int rv, rid; sc = device_get_softc(dev); sc->dev = dev; ctlr = &sc->ctlr; node = ofw_bus_get_node(dev); ctlr->r_rid = 0; ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &ctlr->r_rid, RF_ACTIVE); if (ctlr->r_mem == NULL) return (ENXIO); rid = 1; sc->sata_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sata_mem == NULL) { rv = ENXIO; goto fail; } rv = get_fdt_resources(sc, node); if (rv != 0) { device_printf(sc->dev, "Failed to allocate FDT resource(s)\n"); goto fail; } rv = enable_fdt_resources(sc); if (rv != 0) { device_printf(sc->dev, "Failed to enable FDT resource(s)\n"); goto fail; } rv = tegra_ahci_ctrl_init(sc); if (rv != 0) { device_printf(sc->dev, "Failed to initialize controller)\n"); goto fail; } /* Setup controller defaults. */ ctlr->msi = 0; ctlr->numirqs = 1; ctlr->ccc = 0; /* Reset controller. */ rv = tegra_ahci_ctlr_reset(dev); if (rv != 0) goto fail; rv = ahci_attach(dev); return (rv); fail: /* XXX FDT stuff */ if (sc->sata_mem != NULL) bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->sata_mem); if (ctlr->r_mem != NULL) bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); return (rv); } static int tegra_ahci_detach(device_t dev) { ahci_detach(dev); return (0); } static int tegra_ahci_suspend(device_t dev) { struct tegra_ahci_sc *sc = device_get_softc(dev); bus_generic_suspend(dev); /* Disable interupts, so the state change(s) doesn't trigger. */ ATA_OUTL(sc->ctlr.r_mem, AHCI_GHC, ATA_INL(sc->ctlr.r_mem, AHCI_GHC) & (~AHCI_GHC_IE)); return (0); } static int tegra_ahci_resume(device_t dev) { int res; if ((res = tegra_ahci_ctlr_reset(dev)) != 0) return (res); ahci_ctlr_setup(dev); return (bus_generic_resume(dev)); } static device_method_t tegra_ahci_methods[] = { DEVMETHOD(device_probe, tegra_ahci_probe), DEVMETHOD(device_attach, tegra_ahci_attach), DEVMETHOD(device_detach, tegra_ahci_detach), DEVMETHOD(device_suspend, tegra_ahci_suspend), DEVMETHOD(device_resume, tegra_ahci_resume), DEVMETHOD(bus_print_child, ahci_print_child), DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), DEVMETHOD(bus_release_resource, ahci_release_resource), DEVMETHOD(bus_setup_intr, ahci_setup_intr), DEVMETHOD(bus_teardown_intr, ahci_teardown_intr), DEVMETHOD(bus_child_location_str, ahci_child_location_str), DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag), DEVMETHOD_END }; static DEFINE_CLASS_0(ahci, tegra_ahci_driver, tegra_ahci_methods, sizeof(struct tegra_ahci_sc)); DRIVER_MODULE(tegra_ahci, simplebus, tegra_ahci_driver, ahci_devclass, NULL, NULL); Index: stable/11/sys/arm/nvidia/tegra_pcie.c =================================================================== --- stable/11/sys/arm/nvidia/tegra_pcie.c (revision 332009) +++ stable/11/sys/arm/nvidia/tegra_pcie.c (revision 332010) @@ -1,1628 +1,1636 @@ /*- * Copyright (c) 2016 Michal Meloun * 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 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 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 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 __FBSDID("$FreeBSD$"); /* * Nvidia Integrated PCI/PCI-Express controller driver. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ofw_bus_if.h" #include "msi_if.h" #include "pcib_if.h" #include "pic_if.h" #define AFI_AXI_BAR0_SZ 0x000 #define AFI_AXI_BAR1_SZ 0x004 #define AFI_AXI_BAR2_SZ 0x008 #define AFI_AXI_BAR3_SZ 0x00c #define AFI_AXI_BAR4_SZ 0x010 #define AFI_AXI_BAR5_SZ 0x014 #define AFI_AXI_BAR0_START 0x018 #define AFI_AXI_BAR1_START 0x01c #define AFI_AXI_BAR2_START 0x020 #define AFI_AXI_BAR3_START 0x024 #define AFI_AXI_BAR4_START 0x028 #define AFI_AXI_BAR5_START 0x02c #define AFI_FPCI_BAR0 0x030 #define AFI_FPCI_BAR1 0x034 #define AFI_FPCI_BAR2 0x038 #define AFI_FPCI_BAR3 0x03c #define AFI_FPCI_BAR4 0x040 #define AFI_FPCI_BAR5 0x044 #define AFI_MSI_BAR_SZ 0x060 #define AFI_MSI_FPCI_BAR_ST 0x064 #define AFI_MSI_AXI_BAR_ST 0x068 #define AFI_MSI_VEC(x) (0x06c + 4 * (x)) #define AFI_MSI_EN_VEC(x) (0x08c + 4 * (x)) #define AFI_MSI_INTR_IN_REG 32 #define AFI_MSI_REGS 8 #define AFI_CONFIGURATION 0x0ac #define AFI_CONFIGURATION_EN_FPCI (1 << 0) #define AFI_FPCI_ERROR_MASKS 0x0b0 #define AFI_INTR_MASK 0x0b4 #define AFI_INTR_MASK_MSI_MASK (1 << 8) #define AFI_INTR_MASK_INT_MASK (1 << 0) #define AFI_INTR_CODE 0x0b8 #define AFI_INTR_CODE_MASK 0xf #define AFI_INTR_CODE_INT_CODE_INI_SLVERR 1 #define AFI_INTR_CODE_INT_CODE_INI_DECERR 2 #define AFI_INTR_CODE_INT_CODE_TGT_SLVERR 3 #define AFI_INTR_CODE_INT_CODE_TGT_DECERR 4 #define AFI_INTR_CODE_INT_CODE_TGT_WRERR 5 #define AFI_INTR_CODE_INT_CODE_SM_MSG 6 #define AFI_INTR_CODE_INT_CODE_DFPCI_DECERR 7 #define AFI_INTR_CODE_INT_CODE_AXI_DECERR 8 #define AFI_INTR_CODE_INT_CODE_FPCI_TIMEOUT 9 #define AFI_INTR_CODE_INT_CODE_PE_PRSNT_SENSE 10 #define AFI_INTR_CODE_INT_CODE_PE_CLKREQ_SENSE 11 #define AFI_INTR_CODE_INT_CODE_CLKCLAMP_SENSE 12 #define AFI_INTR_CODE_INT_CODE_RDY4PD_SENSE 13 #define AFI_INTR_CODE_INT_CODE_P2P_ERROR 14 #define AFI_INTR_SIGNATURE 0x0bc #define AFI_UPPER_FPCI_ADDRESS 0x0c0 #define AFI_SM_INTR_ENABLE 0x0c4 #define AFI_SM_INTR_RP_DEASSERT (1 << 14) #define AFI_SM_INTR_RP_ASSERT (1 << 13) #define AFI_SM_INTR_HOTPLUG (1 << 12) #define AFI_SM_INTR_PME (1 << 11) #define AFI_SM_INTR_FATAL_ERROR (1 << 10) #define AFI_SM_INTR_UNCORR_ERROR (1 << 9) #define AFI_SM_INTR_CORR_ERROR (1 << 8) #define AFI_SM_INTR_INTD_DEASSERT (1 << 7) #define AFI_SM_INTR_INTC_DEASSERT (1 << 6) #define AFI_SM_INTR_INTB_DEASSERT (1 << 5) #define AFI_SM_INTR_INTA_DEASSERT (1 << 4) #define AFI_SM_INTR_INTD_ASSERT (1 << 3) #define AFI_SM_INTR_INTC_ASSERT (1 << 2) #define AFI_SM_INTR_INTB_ASSERT (1 << 1) #define AFI_SM_INTR_INTA_ASSERT (1 << 0) #define AFI_AFI_INTR_ENABLE 0x0c8 #define AFI_AFI_INTR_ENABLE_CODE(code) (1 << (code)) #define AFI_PCIE_CONFIG 0x0f8 #define AFI_PCIE_CONFIG_PCIE_DISABLE(x) (1 << ((x) + 1)) #define AFI_PCIE_CONFIG_PCIE_DISABLE_ALL 0x6 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK (0xf << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR2_1 (0x0 << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR4_1 (0x1 << 20) #define AFI_FUSE 0x104 #define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) #define AFI_PEX0_CTRL 0x110 #define AFI_PEX1_CTRL 0x118 #define AFI_PEX2_CTRL 0x128 #define AFI_PEX_CTRL_OVERRIDE_EN (1 << 4) #define AFI_PEX_CTRL_REFCLK_EN (1 << 3) #define AFI_PEX_CTRL_CLKREQ_EN (1 << 1) #define AFI_PEX_CTRL_RST_L (1 << 0) #define AFI_AXI_BAR6_SZ 0x134 #define AFI_AXI_BAR7_SZ 0x138 #define AFI_AXI_BAR8_SZ 0x13c #define AFI_AXI_BAR6_START 0x140 #define AFI_AXI_BAR7_START 0x144 #define AFI_AXI_BAR8_START 0x148 #define AFI_FPCI_BAR6 0x14c #define AFI_FPCI_BAR7 0x150 #define AFI_FPCI_BAR8 0x154 #define AFI_PLLE_CONTROL 0x160 #define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9) #define AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL (1 << 8) #define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1) #define AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN (1 << 0) #define AFI_PEXBIAS_CTRL 0x168 /* FPCI Address space */ #define FPCI_MAP_IO 0xfdfc000000ULL #define FPCI_MAP_TYPE0_CONFIG 0xfdfc000000ULL #define FPCI_MAP_TYPE1_CONFIG 0xfdff000000ULL #define FPCI_MAP_EXT_TYPE0_CONFIG 0xfe00000000ULL #define FPCI_MAP_EXT_TYPE1_CONFIG 0xfe10000000ULL /* Configuration space */ #define RP_VEND_XP 0x00000F00 #define RP_VEND_XP_DL_UP (1 << 30) #define RP_PRIV_MISC 0x00000FE0 #define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0) #define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0) #define RP_LINK_CONTROL_STATUS 0x00000090 #define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000 #define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000 /* Wait 50 ms (per port) for link. */ #define TEGRA_PCIE_LINKUP_TIMEOUT 50000 #define TEGRA_PCIB_MSI_ENABLE #define DEBUG #ifdef DEBUG #define debugf(fmt, args...) do { printf(fmt,##args); } while (0) #else #define debugf(fmt, args...) #endif /* * Configuration space format: * [27:24] extended register * [23:16] bus * [15:11] slot (device) * [10: 8] function * [ 7: 0] register */ #define PCI_CFG_EXT_REG(reg) ((((reg) >> 8) & 0x0f) << 24) #define PCI_CFG_BUS(bus) (((bus) & 0xff) << 16) #define PCI_CFG_DEV(dev) (((dev) & 0x1f) << 11) #define PCI_CFG_FUN(fun) (((fun) & 0x07) << 8) #define PCI_CFG_BASE_REG(reg) ((reg) & 0xff) #define PADS_WR4(_sc, _r, _v) bus_write_4((_sc)-pads_mem_res, (_r), (_v)) #define PADS_RD4(_sc, _r) bus_read_4((_sc)->pads_mem_res, (_r)) #define AFI_WR4(_sc, _r, _v) bus_write_4((_sc)->afi_mem_res, (_r), (_v)) #define AFI_RD4(_sc, _r) bus_read_4((_sc)->afi_mem_res, (_r)) static struct { bus_size_t axi_start; bus_size_t fpci_start; bus_size_t size; } bars[] = { {AFI_AXI_BAR0_START, AFI_FPCI_BAR0, AFI_AXI_BAR0_SZ}, /* BAR 0 */ {AFI_AXI_BAR1_START, AFI_FPCI_BAR1, AFI_AXI_BAR1_SZ}, /* BAR 1 */ {AFI_AXI_BAR2_START, AFI_FPCI_BAR2, AFI_AXI_BAR2_SZ}, /* BAR 2 */ {AFI_AXI_BAR3_START, AFI_FPCI_BAR3, AFI_AXI_BAR3_SZ}, /* BAR 3 */ {AFI_AXI_BAR4_START, AFI_FPCI_BAR4, AFI_AXI_BAR4_SZ}, /* BAR 4 */ {AFI_AXI_BAR5_START, AFI_FPCI_BAR5, AFI_AXI_BAR5_SZ}, /* BAR 5 */ {AFI_AXI_BAR6_START, AFI_FPCI_BAR6, AFI_AXI_BAR6_SZ}, /* BAR 6 */ {AFI_AXI_BAR7_START, AFI_FPCI_BAR7, AFI_AXI_BAR7_SZ}, /* BAR 7 */ {AFI_AXI_BAR8_START, AFI_FPCI_BAR8, AFI_AXI_BAR8_SZ}, /* BAR 8 */ {AFI_MSI_AXI_BAR_ST, AFI_MSI_FPCI_BAR_ST, AFI_MSI_BAR_SZ}, /* MSI 9 */ }; /* Compatible devices. */ static struct ofw_compat_data compat_data[] = { {"nvidia,tegra124-pcie", 1}, {NULL, 0}, }; #define TEGRA_FLAG_MSI_USED 0x0001 struct tegra_pcib_irqsrc { struct intr_irqsrc isrc; u_int irq; u_int flags; }; struct tegra_pcib_port { int enabled; int port_idx; /* chip port index */ int num_lanes; /* number of lanes */ bus_size_t afi_pex_ctrl; /* offset of afi_pex_ctrl */ + phy_t phy; /* port phy */ /* Config space properties. */ bus_addr_t rp_base_addr; /* PA of config window */ bus_size_t rp_size; /* size of config window */ bus_space_handle_t cfg_handle; /* handle of config window */ }; #define TEGRA_PCIB_MAX_PORTS 3 #define TEGRA_PCIB_MAX_MSI AFI_MSI_INTR_IN_REG * AFI_MSI_REGS struct tegra_pcib_softc { struct ofw_pci_softc ofw_pci; device_t dev; struct mtx mtx; struct resource *pads_mem_res; struct resource *afi_mem_res; struct resource *cfg_mem_res; struct resource *irq_res; struct resource *msi_irq_res; void *intr_cookie; void *msi_intr_cookie; struct ofw_pci_range mem_range; struct ofw_pci_range pref_mem_range; struct ofw_pci_range io_range; - phy_t phy; clk_t clk_pex; clk_t clk_afi; clk_t clk_pll_e; clk_t clk_cml; hwreset_t hwreset_pex; hwreset_t hwreset_afi; hwreset_t hwreset_pcie_x; regulator_t supply_avddio_pex; regulator_t supply_dvddio_pex; regulator_t supply_avdd_pex_pll; regulator_t supply_hvdd_pex; regulator_t supply_hvdd_pex_pll_e; regulator_t supply_vddio_pex_ctl; regulator_t supply_avdd_pll_erefe; vm_offset_t msi_page; /* VA of MSI page */ bus_addr_t cfg_base_addr; /* base address of config */ bus_size_t cfg_cur_offs; /* currently mapped window */ bus_space_handle_t cfg_handle; /* handle of config window */ bus_space_tag_t bus_tag; /* tag of config window */ int lanes_cfg; int num_ports; struct tegra_pcib_port *ports[TEGRA_PCIB_MAX_PORTS]; struct tegra_pcib_irqsrc *isrcs; }; static int tegra_pcib_maxslots(device_t dev) { return (16); } static int tegra_pcib_route_interrupt(device_t bus, device_t dev, int pin) { struct tegra_pcib_softc *sc; u_int irq; sc = device_get_softc(bus); irq = intr_map_clone_irq(rman_get_start(sc->irq_res)); device_printf(bus, "route pin %d for device %d.%d to %u\n", pin, pci_get_slot(dev), pci_get_function(dev), irq); return (irq); } static int tegra_pcbib_map_cfg(struct tegra_pcib_softc *sc, u_int bus, u_int slot, u_int func, u_int reg) { bus_size_t offs; int rv; offs = sc->cfg_base_addr; offs |= PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) | PCI_CFG_FUN(func) | PCI_CFG_EXT_REG(reg); if ((sc->cfg_handle != 0) && (sc->cfg_cur_offs == offs)) return (0); if (sc->cfg_handle != 0) bus_space_unmap(sc->bus_tag, sc->cfg_handle, 0x800); rv = bus_space_map(sc->bus_tag, offs, 0x800, 0, &sc->cfg_handle); if (rv != 0) device_printf(sc->dev, "Cannot map config space\n"); else sc->cfg_cur_offs = offs; return (rv); } static uint32_t tegra_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int bytes) { struct tegra_pcib_softc *sc; bus_space_handle_t hndl; uint32_t off; uint32_t val; int rv, i; sc = device_get_softc(dev); if (bus == 0) { if (func != 0) return (0xFFFFFFFF); for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) { if ((sc->ports[i] != NULL) && (sc->ports[i]->port_idx == slot)) { hndl = sc->ports[i]->cfg_handle; off = reg & 0xFFF; break; } } if (i >= TEGRA_PCIB_MAX_PORTS) return (0xFFFFFFFF); } else { rv = tegra_pcbib_map_cfg(sc, bus, slot, func, reg); if (rv != 0) return (0xFFFFFFFF); hndl = sc->cfg_handle; off = PCI_CFG_BASE_REG(reg); } val = bus_space_read_4(sc->bus_tag, hndl, off & ~3); switch (bytes) { case 4: break; case 2: if (off & 3) val >>= 16; val &= 0xffff; break; case 1: val >>= ((off & 3) << 3); val &= 0xff; break; } return val; } static void tegra_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int bytes) { struct tegra_pcib_softc *sc; bus_space_handle_t hndl; uint32_t off; uint32_t val2; int rv, i; sc = device_get_softc(dev); if (bus == 0) { if (func != 0) return; for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) { if ((sc->ports[i] != NULL) && (sc->ports[i]->port_idx == slot)) { hndl = sc->ports[i]->cfg_handle; off = reg & 0xFFF; break; } } if (i >= TEGRA_PCIB_MAX_PORTS) return; } else { rv = tegra_pcbib_map_cfg(sc, bus, slot, func, reg); if (rv != 0) return; hndl = sc->cfg_handle; off = PCI_CFG_BASE_REG(reg); } switch (bytes) { case 4: bus_space_write_4(sc->bus_tag, hndl, off, val); break; case 2: val2 = bus_space_read_4(sc->bus_tag, hndl, off & ~3); val2 &= ~(0xffff << ((off & 3) << 3)); val2 |= ((val & 0xffff) << ((off & 3) << 3)); bus_space_write_4(sc->bus_tag, hndl, off & ~3, val2); break; case 1: val2 = bus_space_read_4(sc->bus_tag, hndl, off & ~3); val2 &= ~(0xff << ((off & 3) << 3)); val2 |= ((val & 0xff) << ((off & 3) << 3)); bus_space_write_4(sc->bus_tag, hndl, off & ~3, val2); break; } } static int tegra_pci_intr(void *arg) { struct tegra_pcib_softc *sc = arg; uint32_t code, signature; code = bus_read_4(sc->afi_mem_res, AFI_INTR_CODE) & AFI_INTR_CODE_MASK; signature = bus_read_4(sc->afi_mem_res, AFI_INTR_SIGNATURE); bus_write_4(sc->afi_mem_res, AFI_INTR_CODE, 0); if (code == AFI_INTR_CODE_INT_CODE_SM_MSG) return(FILTER_STRAY); printf("tegra_pci_intr: code %x sig %x\n", code, signature); return (FILTER_HANDLED); } /* ----------------------------------------------------------------------- * * PCI MSI interface */ static int tegra_pcib_alloc_msi(device_t pci, device_t child, int count, int maxcount, int *irqs) { phandle_t msi_parent; /* XXXX ofw_bus_msimap() don't works for Tegra DT. ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent, NULL); */ msi_parent = OF_xref_from_node(ofw_bus_get_node(pci)); return (intr_alloc_msi(pci, child, msi_parent, count, maxcount, irqs)); } static int tegra_pcib_release_msi(device_t pci, device_t child, int count, int *irqs) { phandle_t msi_parent; /* XXXX ofw_bus_msimap() don't works for Tegra DT. ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent, NULL); */ msi_parent = OF_xref_from_node(ofw_bus_get_node(pci)); return (intr_release_msi(pci, child, msi_parent, count, irqs)); } static int tegra_pcib_map_msi(device_t pci, device_t child, int irq, uint64_t *addr, uint32_t *data) { phandle_t msi_parent; /* XXXX ofw_bus_msimap() don't works for Tegra DT. ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent, NULL); */ msi_parent = OF_xref_from_node(ofw_bus_get_node(pci)); return (intr_map_msi(pci, child, msi_parent, irq, addr, data)); } #ifdef TEGRA_PCIB_MSI_ENABLE /* -------------------------------------------------------------------------- * * Interrupts * */ static inline void tegra_pcib_isrc_mask(struct tegra_pcib_softc *sc, struct tegra_pcib_irqsrc *tgi, uint32_t val) { uint32_t reg; int offs, bit; offs = tgi->irq / AFI_MSI_INTR_IN_REG; bit = 1 << (tgi->irq % AFI_MSI_INTR_IN_REG); if (val != 0) AFI_WR4(sc, AFI_MSI_VEC(offs), bit); reg = AFI_RD4(sc, AFI_MSI_EN_VEC(offs)); if (val != 0) reg |= bit; else reg &= ~bit; AFI_WR4(sc, AFI_MSI_EN_VEC(offs), reg); } static int tegra_pcib_msi_intr(void *arg) { u_int irq, i, bit, reg; struct tegra_pcib_softc *sc; struct trapframe *tf; struct tegra_pcib_irqsrc *tgi; sc = (struct tegra_pcib_softc *)arg; tf = curthread->td_intr_frame; for (i = 0; i < AFI_MSI_REGS; i++) { reg = AFI_RD4(sc, AFI_MSI_VEC(i)); /* Handle one vector. */ while (reg != 0) { bit = ffs(reg) - 1; /* Send EOI */ AFI_WR4(sc, AFI_MSI_VEC(i), 1 << bit); irq = i * AFI_MSI_INTR_IN_REG + bit; tgi = &sc->isrcs[irq]; if (intr_isrc_dispatch(&tgi->isrc, tf) != 0) { /* Disable stray. */ tegra_pcib_isrc_mask(sc, tgi, 0); device_printf(sc->dev, "Stray irq %u disabled\n", irq); } reg = AFI_RD4(sc, AFI_MSI_VEC(i)); } } return (FILTER_HANDLED); } static int tegra_pcib_msi_attach(struct tegra_pcib_softc *sc) { int error; uint32_t irq; const char *name; sc->isrcs = malloc(sizeof(*sc->isrcs) * TEGRA_PCIB_MAX_MSI, M_DEVBUF, M_WAITOK | M_ZERO); name = device_get_nameunit(sc->dev); for (irq = 0; irq < TEGRA_PCIB_MAX_MSI; irq++) { sc->isrcs[irq].irq = irq; error = intr_isrc_register(&sc->isrcs[irq].isrc, sc->dev, 0, "%s,%u", name, irq); if (error != 0) return (error); /* XXX deregister ISRCs */ } if (intr_msi_register(sc->dev, OF_xref_from_node(ofw_bus_get_node(sc->dev))) != 0) return (ENXIO); return (0); } static int tegra_pcib_msi_detach(struct tegra_pcib_softc *sc) { /* * There has not been established any procedure yet * how to detach PIC from living system correctly. */ device_printf(sc->dev, "%s: not implemented yet\n", __func__); return (EBUSY); } static void tegra_pcib_msi_disable_intr(device_t dev, struct intr_irqsrc *isrc) { struct tegra_pcib_softc *sc; struct tegra_pcib_irqsrc *tgi; sc = device_get_softc(dev); tgi = (struct tegra_pcib_irqsrc *)isrc; tegra_pcib_isrc_mask(sc, tgi, 0); } static void tegra_pcib_msi_enable_intr(device_t dev, struct intr_irqsrc *isrc) { struct tegra_pcib_softc *sc; struct tegra_pcib_irqsrc *tgi; sc = device_get_softc(dev); tgi = (struct tegra_pcib_irqsrc *)isrc; tegra_pcib_isrc_mask(sc, tgi, 1); } /* MSI interrupts are edge trigered -> do nothing */ static void tegra_pcib_msi_post_filter(device_t dev, struct intr_irqsrc *isrc) { } static void tegra_pcib_msi_post_ithread(device_t dev, struct intr_irqsrc *isrc) { } static void tegra_pcib_msi_pre_ithread(device_t dev, struct intr_irqsrc *isrc) { } static int tegra_pcib_msi_setup_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { struct tegra_pcib_softc *sc; struct tegra_pcib_irqsrc *tgi; sc = device_get_softc(dev); tgi = (struct tegra_pcib_irqsrc *)isrc; if (data == NULL || data->type != INTR_MAP_DATA_MSI) return (ENOTSUP); if (isrc->isrc_handlers == 0) tegra_pcib_msi_enable_intr(dev, isrc); return (0); } static int tegra_pcib_msi_teardown_intr(device_t dev, struct intr_irqsrc *isrc, struct resource *res, struct intr_map_data *data) { struct tegra_pcib_softc *sc; struct tegra_pcib_irqsrc *tgi; sc = device_get_softc(dev); tgi = (struct tegra_pcib_irqsrc *)isrc; if (isrc->isrc_handlers == 0) tegra_pcib_isrc_mask(sc, tgi, 0); return (0); } static int tegra_pcib_msi_alloc_msi(device_t dev, device_t child, int count, int maxcount, device_t *pic, struct intr_irqsrc **srcs) { struct tegra_pcib_softc *sc; int i, irq, end_irq; bool found; KASSERT(powerof2(count), ("%s: bad count", __func__)); KASSERT(powerof2(maxcount), ("%s: bad maxcount", __func__)); sc = device_get_softc(dev); mtx_lock(&sc->mtx); found = false; for (irq = 0; (irq + count - 1) < TEGRA_PCIB_MAX_MSI; irq++) { /* Start on an aligned interrupt */ if ((irq & (maxcount - 1)) != 0) continue; /* Assume we found a valid range until shown otherwise */ found = true; /* Check this range is valid */ for (end_irq = irq; end_irq < irq + count; end_irq++) { /* This is already used */ if ((sc->isrcs[end_irq].flags & TEGRA_FLAG_MSI_USED) == TEGRA_FLAG_MSI_USED) { found = false; break; } } if (found) break; } /* Not enough interrupts were found */ if (!found || irq == (TEGRA_PCIB_MAX_MSI - 1)) { mtx_unlock(&sc->mtx); return (ENXIO); } for (i = 0; i < count; i++) { /* Mark the interrupt as used */ sc->isrcs[irq + i].flags |= TEGRA_FLAG_MSI_USED; } mtx_unlock(&sc->mtx); for (i = 0; i < count; i++) srcs[i] = (struct intr_irqsrc *)&sc->isrcs[irq + i]; *pic = device_get_parent(dev); return (0); } static int tegra_pcib_msi_release_msi(device_t dev, device_t child, int count, struct intr_irqsrc **isrc) { struct tegra_pcib_softc *sc; struct tegra_pcib_irqsrc *ti; int i; sc = device_get_softc(dev); mtx_lock(&sc->mtx); for (i = 0; i < count; i++) { ti = (struct tegra_pcib_irqsrc *)isrc[i]; KASSERT((ti->flags & TEGRA_FLAG_MSI_USED) == TEGRA_FLAG_MSI_USED, ("%s: Trying to release an unused MSI-X interrupt", __func__)); ti->flags &= ~TEGRA_FLAG_MSI_USED; } mtx_unlock(&sc->mtx); return (0); } static int tegra_pcib_msi_map_msi(device_t dev, device_t child, struct intr_irqsrc *isrc, uint64_t *addr, uint32_t *data) { struct tegra_pcib_softc *sc = device_get_softc(dev); struct tegra_pcib_irqsrc *ti = (struct tegra_pcib_irqsrc *)isrc; *addr = vtophys(sc->msi_page); *data = ti->irq; return (0); } #endif /* ------------------------------------------------------------------- */ static bus_size_t tegra_pcib_pex_ctrl(struct tegra_pcib_softc *sc, int port) { if (port >= TEGRA_PCIB_MAX_PORTS) panic("invalid port number: %d\n", port); if (port == 0) return (AFI_PEX0_CTRL); else if (port == 1) return (AFI_PEX1_CTRL); else if (port == 2) return (AFI_PEX2_CTRL); else panic("invalid port number: %d\n", port); } static int tegra_pcib_enable_fdt_resources(struct tegra_pcib_softc *sc) { int rv; rv = hwreset_assert(sc->hwreset_pcie_x); if (rv != 0) { device_printf(sc->dev, "Cannot assert 'pcie_x' reset\n"); return (rv); } rv = hwreset_assert(sc->hwreset_afi); if (rv != 0) { device_printf(sc->dev, "Cannot assert 'afi' reset\n"); return (rv); } rv = hwreset_assert(sc->hwreset_pex); if (rv != 0) { device_printf(sc->dev, "Cannot assert 'pex' reset\n"); return (rv); } tegra_powergate_power_off(TEGRA_POWERGATE_PCX); /* Power supplies. */ rv = regulator_enable(sc->supply_avddio_pex); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'avddio_pex' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_dvddio_pex); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'dvddio_pex' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_avdd_pex_pll); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'avdd-pex-pll' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_hvdd_pex); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'hvdd-pex-supply' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_hvdd_pex_pll_e); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'hvdd-pex-pll-e-supply' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_vddio_pex_ctl); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'vddio-pex-ctl' regulator\n"); return (rv); } rv = regulator_enable(sc->supply_avdd_pll_erefe); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'avdd-pll-erefe-supply' regulator\n"); return (rv); } rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCX, sc->clk_pex, sc->hwreset_pex); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'PCX' powergate\n"); return (rv); } rv = hwreset_deassert(sc->hwreset_afi); if (rv != 0) { device_printf(sc->dev, "Cannot unreset 'afi' reset\n"); return (rv); } rv = clk_enable(sc->clk_afi); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'afi' clock\n"); return (rv); } rv = clk_enable(sc->clk_cml); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'cml' clock\n"); return (rv); } rv = clk_enable(sc->clk_pll_e); if (rv != 0) { device_printf(sc->dev, "Cannot enable 'pll_e' clock\n"); return (rv); } return (0); } static struct tegra_pcib_port * tegra_pcib_parse_port(struct tegra_pcib_softc *sc, phandle_t node) { struct tegra_pcib_port *port; uint32_t tmp[5]; char tmpstr[6]; int rv; port = malloc(sizeof(struct tegra_pcib_port), M_DEVBUF, M_WAITOK); rv = OF_getprop(node, "status", tmpstr, sizeof(tmpstr)); if (rv <= 0 || strcmp(tmpstr, "okay") == 0 || strcmp(tmpstr, "ok") == 0) port->enabled = 1; else port->enabled = 0; rv = OF_getencprop(node, "assigned-addresses", tmp, sizeof(tmp)); if (rv != sizeof(tmp)) { device_printf(sc->dev, "Cannot parse assigned-address: %d\n", rv); goto fail; } port->rp_base_addr = tmp[2]; port->rp_size = tmp[4]; port->port_idx = OFW_PCI_PHYS_HI_DEVICE(tmp[0]) - 1; if (port->port_idx >= TEGRA_PCIB_MAX_PORTS) { device_printf(sc->dev, "Invalid port index: %d\n", port->port_idx); goto fail; } /* XXX - TODO: * Implement proper function for parsing pci "reg" property: * - it have PCI bus format * - its relative to matching "assigned-addresses" */ rv = OF_getencprop(node, "reg", tmp, sizeof(tmp)); if (rv != sizeof(tmp)) { device_printf(sc->dev, "Cannot parse reg: %d\n", rv); goto fail; } port->rp_base_addr += tmp[2]; rv = OF_getencprop(node, "nvidia,num-lanes", &port->num_lanes, sizeof(port->num_lanes)); if (rv != sizeof(port->num_lanes)) { device_printf(sc->dev, "Cannot parse nvidia,num-lanes: %d\n", rv); goto fail; } if (port->num_lanes > 4) { device_printf(sc->dev, "Invalid nvidia,num-lanes: %d\n", port->num_lanes); goto fail; } port->afi_pex_ctrl = tegra_pcib_pex_ctrl(sc, port->port_idx); sc->lanes_cfg |= port->num_lanes << (4 * port->port_idx); + /* Phy. */ + rv = phy_get_by_ofw_name(sc->dev, node, "pcie-0", &port->phy); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'pcie-0' phy for port %d\n", + port->port_idx); + goto fail; + } + return (port); fail: free(port, M_DEVBUF); return (NULL); } static int tegra_pcib_parse_fdt_resources(struct tegra_pcib_softc *sc, phandle_t node) { phandle_t child; struct tegra_pcib_port *port; int rv; /* Power supplies. */ rv = regulator_get_by_ofw_property(sc->dev, 0, "avddio-pex-supply", &sc->supply_avddio_pex); if (rv != 0) { device_printf(sc->dev, "Cannot get 'avddio-pex' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "dvddio-pex-supply", &sc->supply_dvddio_pex); if (rv != 0) { device_printf(sc->dev, "Cannot get 'dvddio-pex' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pex-pll-supply", &sc->supply_avdd_pex_pll); if (rv != 0) { device_printf(sc->dev, "Cannot get 'avdd-pex-pll' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-pex-supply", &sc->supply_hvdd_pex); if (rv != 0) { device_printf(sc->dev, "Cannot get 'hvdd-pex' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-pex-pll-e-supply", &sc->supply_hvdd_pex_pll_e); if (rv != 0) { device_printf(sc->dev, "Cannot get 'hvdd-pex-pll-e' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "vddio-pex-ctl-supply", &sc->supply_vddio_pex_ctl); if (rv != 0) { device_printf(sc->dev, "Cannot get 'vddio-pex-ctl' regulator\n"); return (ENXIO); } rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-erefe-supply", &sc->supply_avdd_pll_erefe); if (rv != 0) { device_printf(sc->dev, "Cannot get 'avdd-pll-erefe' regulator\n"); return (ENXIO); } /* Resets. */ rv = hwreset_get_by_ofw_name(sc->dev, 0, "pex", &sc->hwreset_pex); if (rv != 0) { device_printf(sc->dev, "Cannot get 'pex' reset\n"); return (ENXIO); } rv = hwreset_get_by_ofw_name(sc->dev, 0, "afi", &sc->hwreset_afi); if (rv != 0) { device_printf(sc->dev, "Cannot get 'afi' reset\n"); return (ENXIO); } rv = hwreset_get_by_ofw_name(sc->dev, 0, "pcie_x", &sc->hwreset_pcie_x); if (rv != 0) { device_printf(sc->dev, "Cannot get 'pcie_x' reset\n"); return (ENXIO); } /* Clocks. */ rv = clk_get_by_ofw_name(sc->dev, 0, "pex", &sc->clk_pex); if (rv != 0) { device_printf(sc->dev, "Cannot get 'pex' clock\n"); return (ENXIO); } rv = clk_get_by_ofw_name(sc->dev, 0, "afi", &sc->clk_afi); if (rv != 0) { device_printf(sc->dev, "Cannot get 'afi' clock\n"); return (ENXIO); } rv = clk_get_by_ofw_name(sc->dev, 0, "pll_e", &sc->clk_pll_e); if (rv != 0) { device_printf(sc->dev, "Cannot get 'pll_e' clock\n"); return (ENXIO); } rv = clk_get_by_ofw_name(sc->dev, 0, "cml", &sc->clk_cml); if (rv != 0) { device_printf(sc->dev, "Cannot get 'cml' clock\n"); return (ENXIO); } - /* Phy. */ - rv = phy_get_by_ofw_name(sc->dev, 0, "pcie", &sc->phy); - if (rv != 0) { - device_printf(sc->dev, "Cannot get 'pcie' phy\n"); - return (ENXIO); - } - /* Ports */ sc->num_ports = 0; for (child = OF_child(node); child != 0; child = OF_peer(child)) { port = tegra_pcib_parse_port(sc, child); if (port == NULL) { device_printf(sc->dev, "Cannot parse PCIe port node\n"); return (ENXIO); } sc->ports[sc->num_ports++] = port; } return (0); } static int tegra_pcib_decode_ranges(struct tegra_pcib_softc *sc, struct ofw_pci_range *ranges, int nranges) { int i; for (i = 2; i < nranges; i++) { if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == OFW_PCI_PHYS_HI_SPACE_IO) { if (sc->io_range.size != 0) { device_printf(sc->dev, "Duplicated IO range found in DT\n"); return (ENXIO); } sc->io_range = ranges[i]; } if (((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == OFW_PCI_PHYS_HI_SPACE_MEM32)) { if (ranges[i].pci_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) { if (sc->pref_mem_range.size != 0) { device_printf(sc->dev, "Duplicated memory range found " "in DT\n"); return (ENXIO); } sc->pref_mem_range = ranges[i]; } else { if (sc->mem_range.size != 0) { device_printf(sc->dev, "Duplicated memory range found " "in DT\n"); return (ENXIO); } sc->mem_range = ranges[i]; } } } if ((sc->io_range.size == 0) || (sc->mem_range.size == 0) || (sc->pref_mem_range.size == 0)) { device_printf(sc->dev, " Not all required ranges are found in DT\n"); return (ENXIO); } return (0); } /* * Hardware config. */ static int tegra_pcib_wait_for_link(struct tegra_pcib_softc *sc, struct tegra_pcib_port *port) { uint32_t reg; int i; /* Setup link detection. */ reg = tegra_pcib_read_config(sc->dev, 0, port->port_idx, 0, RP_PRIV_MISC, 4); reg &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT; reg |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT; tegra_pcib_write_config(sc->dev, 0, port->port_idx, 0, RP_PRIV_MISC, reg, 4); for (i = TEGRA_PCIE_LINKUP_TIMEOUT; i > 0; i--) { reg = tegra_pcib_read_config(sc->dev, 0, port->port_idx, 0, RP_VEND_XP, 4); if (reg & RP_VEND_XP_DL_UP) break; DELAY(1); } if (i <= 0) return (ETIMEDOUT); for (i = TEGRA_PCIE_LINKUP_TIMEOUT; i > 0; i--) { reg = tegra_pcib_read_config(sc->dev, 0, port->port_idx, 0, RP_LINK_CONTROL_STATUS, 4); if (reg & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE) break; DELAY(1); } if (i <= 0) return (ETIMEDOUT); return (0); } static void tegra_pcib_port_enable(struct tegra_pcib_softc *sc, int port_num) { struct tegra_pcib_port *port; uint32_t reg; int rv; port = sc->ports[port_num]; /* Put port to reset. */ reg = AFI_RD4(sc, port->afi_pex_ctrl); reg &= ~AFI_PEX_CTRL_RST_L; AFI_WR4(sc, port->afi_pex_ctrl, reg); AFI_RD4(sc, port->afi_pex_ctrl); DELAY(10); /* Enable clocks. */ reg |= AFI_PEX_CTRL_REFCLK_EN; reg |= AFI_PEX_CTRL_CLKREQ_EN; reg |= AFI_PEX_CTRL_OVERRIDE_EN; AFI_WR4(sc, port->afi_pex_ctrl, reg); AFI_RD4(sc, port->afi_pex_ctrl); DELAY(100); /* Release reset. */ reg |= AFI_PEX_CTRL_RST_L; AFI_WR4(sc, port->afi_pex_ctrl, reg); rv = tegra_pcib_wait_for_link(sc, port); if (bootverbose) device_printf(sc->dev, " port %d (%d lane%s): Link is %s\n", port->port_idx, port->num_lanes, port->num_lanes > 1 ? "s": "", rv == 0 ? "up": "down"); } static void tegra_pcib_port_disable(struct tegra_pcib_softc *sc, uint32_t port_num) { struct tegra_pcib_port *port; uint32_t reg; port = sc->ports[port_num]; /* Put port to reset. */ reg = AFI_RD4(sc, port->afi_pex_ctrl); reg &= ~AFI_PEX_CTRL_RST_L; AFI_WR4(sc, port->afi_pex_ctrl, reg); AFI_RD4(sc, port->afi_pex_ctrl); DELAY(10); /* Disable clocks. */ reg &= ~AFI_PEX_CTRL_CLKREQ_EN; reg &= ~AFI_PEX_CTRL_REFCLK_EN; AFI_WR4(sc, port->afi_pex_ctrl, reg); if (bootverbose) device_printf(sc->dev, " port %d (%d lane%s): Disabled\n", port->port_idx, port->num_lanes, port->num_lanes > 1 ? "s": ""); } static void tegra_pcib_set_bar(struct tegra_pcib_softc *sc, int bar, uint32_t axi, uint64_t fpci, uint32_t size, int is_memory) { uint32_t fpci_reg; uint32_t axi_reg; uint32_t size_reg; axi_reg = axi & ~0xFFF; size_reg = size >> 12; fpci_reg = (uint32_t)(fpci >> 8) & ~0xF; fpci_reg |= is_memory ? 0x1 : 0x0; AFI_WR4(sc, bars[bar].axi_start, axi_reg); AFI_WR4(sc, bars[bar].size, size_reg); AFI_WR4(sc, bars[bar].fpci_start, fpci_reg); } static int tegra_pcib_enable(struct tegra_pcib_softc *sc) { int rv; int i; uint32_t reg; rv = tegra_pcib_enable_fdt_resources(sc); if (rv != 0) { device_printf(sc->dev, "Cannot enable FDT resources\n"); return (rv); } /* Enable PLLE control. */ reg = AFI_RD4(sc, AFI_PLLE_CONTROL); reg &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL; reg |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN; AFI_WR4(sc, AFI_PLLE_CONTROL, reg); /* Set bias pad. */ AFI_WR4(sc, AFI_PEXBIAS_CTRL, 0); /* Configure mode and ports. */ reg = AFI_RD4(sc, AFI_PCIE_CONFIG); reg &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK; if (sc->lanes_cfg == 0x14) { if (bootverbose) device_printf(sc->dev, "Using x1,x4 configuration\n"); reg |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR4_1; } else if (sc->lanes_cfg == 0x12) { if (bootverbose) device_printf(sc->dev, "Using x1,x2 configuration\n"); reg |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR2_1; } else { device_printf(sc->dev, "Unsupported lanes configuration: 0x%X\n", sc->lanes_cfg); } reg |= AFI_PCIE_CONFIG_PCIE_DISABLE_ALL; for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) { if ((sc->ports[i] != NULL)) reg &= ~AFI_PCIE_CONFIG_PCIE_DISABLE(sc->ports[i]->port_idx); } AFI_WR4(sc, AFI_PCIE_CONFIG, reg); /* Enable Gen2 support. */ reg = AFI_RD4(sc, AFI_FUSE); reg &= ~AFI_FUSE_PCIE_T0_GEN2_DIS; AFI_WR4(sc, AFI_FUSE, reg); - /* Enable PCIe phy. */ - rv = phy_enable(sc->dev, sc->phy); - if (rv != 0) { - device_printf(sc->dev, "Cannot enable phy\n"); - return (rv); + for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) { + if (sc->ports[i] != NULL) { + rv = phy_enable(sc->dev, sc->ports[i]->phy); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable phy for port %d\n", + sc->ports[i]->port_idx); + return (rv); + } + } } + rv = hwreset_deassert(sc->hwreset_pcie_x); if (rv != 0) { device_printf(sc->dev, "Cannot unreset 'pci_x' reset\n"); return (rv); } /* Enable config space. */ reg = AFI_RD4(sc, AFI_CONFIGURATION); reg |= AFI_CONFIGURATION_EN_FPCI; AFI_WR4(sc, AFI_CONFIGURATION, reg); /* Enable AFI errors. */ reg = 0; reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_INI_SLVERR); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_INI_DECERR); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_TGT_SLVERR); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_TGT_DECERR); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_TGT_WRERR); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_SM_MSG); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_DFPCI_DECERR); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_AXI_DECERR); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_FPCI_TIMEOUT); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_PE_PRSNT_SENSE); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_PE_CLKREQ_SENSE); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_CLKCLAMP_SENSE); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_RDY4PD_SENSE); reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_P2P_ERROR); AFI_WR4(sc, AFI_AFI_INTR_ENABLE, reg); AFI_WR4(sc, AFI_SM_INTR_ENABLE, 0xffffffff); /* Enable INT, disable MSI. */ AFI_WR4(sc, AFI_INTR_MASK, AFI_INTR_MASK_INT_MASK); /* Mask all FPCI errors. */ AFI_WR4(sc, AFI_FPCI_ERROR_MASKS, 0); /* Setup AFI translation windows. */ /* BAR 0 - type 1 extended configuration. */ tegra_pcib_set_bar(sc, 0, rman_get_start(sc->cfg_mem_res), FPCI_MAP_EXT_TYPE1_CONFIG, rman_get_size(sc->cfg_mem_res), 0); /* BAR 1 - downstream I/O. */ tegra_pcib_set_bar(sc, 1, sc->io_range.host, FPCI_MAP_IO, sc->io_range.size, 0); /* BAR 2 - downstream prefetchable memory 1:1. */ tegra_pcib_set_bar(sc, 2, sc->pref_mem_range.host, sc->pref_mem_range.host, sc->pref_mem_range.size, 1); /* BAR 3 - downstream not prefetchable memory 1:1 .*/ tegra_pcib_set_bar(sc, 3, sc->mem_range.host, sc->mem_range.host, sc->mem_range.size, 1); /* BAR 3-8 clear. */ tegra_pcib_set_bar(sc, 4, 0, 0, 0, 0); tegra_pcib_set_bar(sc, 5, 0, 0, 0, 0); tegra_pcib_set_bar(sc, 6, 0, 0, 0, 0); tegra_pcib_set_bar(sc, 7, 0, 0, 0, 0); tegra_pcib_set_bar(sc, 8, 0, 0, 0, 0); /* MSI BAR - clear. */ tegra_pcib_set_bar(sc, 9, 0, 0, 0, 0); return(0); } #ifdef TEGRA_PCIB_MSI_ENABLE static int tegra_pcib_attach_msi(device_t dev) { struct tegra_pcib_softc *sc; uint32_t reg; int i, rv; sc = device_get_softc(dev); sc->msi_page = kmem_alloc_contig(kernel_arena, PAGE_SIZE, M_WAITOK, 0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); /* MSI BAR */ tegra_pcib_set_bar(sc, 9, vtophys(sc->msi_page), vtophys(sc->msi_page), PAGE_SIZE, 0); /* Disble and clear all interrupts. */ for (i = 0; i < AFI_MSI_REGS; i++) { AFI_WR4(sc, AFI_MSI_EN_VEC(i), 0); AFI_WR4(sc, AFI_MSI_VEC(i), 0xFFFFFFFF); } rv = bus_setup_intr(dev, sc->msi_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, tegra_pcib_msi_intr, NULL, sc, &sc->msi_intr_cookie); if (rv != 0) { device_printf(dev, "cannot setup MSI interrupt handler\n"); rv = ENXIO; goto out; } if (tegra_pcib_msi_attach(sc) != 0) { device_printf(dev, "WARNING: unable to attach PIC\n"); tegra_pcib_msi_detach(sc); goto out; } /* Unmask MSI interrupt. */ reg = AFI_RD4(sc, AFI_INTR_MASK); reg |= AFI_INTR_MASK_MSI_MASK; AFI_WR4(sc, AFI_INTR_MASK, reg); out: return (rv); } #endif static int tegra_pcib_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { device_set_desc(dev, "Nvidia Integrated PCI/PCI-E Controller"); return (BUS_PROBE_DEFAULT); } return (ENXIO); } static int tegra_pcib_attach(device_t dev) { struct tegra_pcib_softc *sc; phandle_t node; int rv; int rid; struct tegra_pcib_port *port; int i; sc = device_get_softc(dev); sc->dev = dev; mtx_init(&sc->mtx, "msi_mtx", NULL, MTX_DEF); node = ofw_bus_get_node(dev); rv = tegra_pcib_parse_fdt_resources(sc, node); if (rv != 0) { device_printf(dev, "Cannot get FDT resources\n"); return (rv); } /* Allocate bus_space resources. */ rid = 0; sc->pads_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->pads_mem_res == NULL) { device_printf(dev, "Cannot allocate PADS register\n"); rv = ENXIO; goto out; } /* * XXX - FIXME * tag for config space is not filled when RF_ALLOCATED flag is used. */ sc->bus_tag = rman_get_bustag(sc->pads_mem_res); rid = 1; sc->afi_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->afi_mem_res == NULL) { device_printf(dev, "Cannot allocate AFI register\n"); rv = ENXIO; goto out; } rid = 2; sc->cfg_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ALLOCATED); if (sc->cfg_mem_res == NULL) { device_printf(dev, "Cannot allocate config space memory\n"); rv = ENXIO; goto out; } sc->cfg_base_addr = rman_get_start(sc->cfg_mem_res); /* Map RP slots */ for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) { if (sc->ports[i] == NULL) continue; port = sc->ports[i]; rv = bus_space_map(sc->bus_tag, port->rp_base_addr, port->rp_size, 0, &port->cfg_handle); if (rv != 0) { device_printf(sc->dev, "Cannot allocate memory for " "port: %d\n", i); rv = ENXIO; goto out; } } /* * Get PCI interrupt */ rid = 0; sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | RF_SHAREABLE); if (sc->irq_res == NULL) { device_printf(dev, "Cannot allocate IRQ resources\n"); rv = ENXIO; goto out; } rid = 1; sc->msi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (sc->irq_res == NULL) { device_printf(dev, "Cannot allocate MSI IRQ resources\n"); rv = ENXIO; goto out; } sc->ofw_pci.sc_range_mask = 0x3; rv = ofw_pci_init(dev); if (rv != 0) goto out; rv = tegra_pcib_decode_ranges(sc, sc->ofw_pci.sc_range, sc->ofw_pci.sc_nrange); if (rv != 0) goto out; if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE, tegra_pci_intr, NULL, sc, &sc->intr_cookie)) { device_printf(dev, "cannot setup interrupt handler\n"); rv = ENXIO; goto out; } /* * Enable PCIE device. */ rv = tegra_pcib_enable(sc); if (rv != 0) goto out; for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) { if (sc->ports[i] == NULL) continue; if (sc->ports[i]->enabled) tegra_pcib_port_enable(sc, i); else tegra_pcib_port_disable(sc, i); } #ifdef TEGRA_PCIB_MSI_ENABLE rv = tegra_pcib_attach_msi(dev); if (rv != 0) goto out; #endif device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); out: return (rv); } static device_method_t tegra_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, tegra_pcib_probe), DEVMETHOD(device_attach, tegra_pcib_attach), /* Bus interface */ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), /* pcib interface */ DEVMETHOD(pcib_maxslots, tegra_pcib_maxslots), DEVMETHOD(pcib_read_config, tegra_pcib_read_config), DEVMETHOD(pcib_write_config, tegra_pcib_write_config), DEVMETHOD(pcib_route_interrupt, tegra_pcib_route_interrupt), DEVMETHOD(pcib_alloc_msi, tegra_pcib_alloc_msi), DEVMETHOD(pcib_release_msi, tegra_pcib_release_msi), DEVMETHOD(pcib_map_msi, tegra_pcib_map_msi), #ifdef TEGRA_PCIB_MSI_ENABLE /* MSI/MSI-X */ DEVMETHOD(msi_alloc_msi, tegra_pcib_msi_alloc_msi), DEVMETHOD(msi_release_msi, tegra_pcib_msi_release_msi), DEVMETHOD(msi_map_msi, tegra_pcib_msi_map_msi), /* Interrupt controller interface */ DEVMETHOD(pic_disable_intr, tegra_pcib_msi_disable_intr), DEVMETHOD(pic_enable_intr, tegra_pcib_msi_enable_intr), DEVMETHOD(pic_setup_intr, tegra_pcib_msi_setup_intr), DEVMETHOD(pic_teardown_intr, tegra_pcib_msi_teardown_intr), DEVMETHOD(pic_post_filter, tegra_pcib_msi_post_filter), DEVMETHOD(pic_post_ithread, tegra_pcib_msi_post_ithread), DEVMETHOD(pic_pre_ithread, tegra_pcib_msi_pre_ithread), #endif /* OFW bus interface */ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), DEVMETHOD_END }; static devclass_t pcib_devclass; DEFINE_CLASS_1(pcib, tegra_pcib_driver, tegra_pcib_methods, sizeof(struct tegra_pcib_softc), ofw_pci_driver); DRIVER_MODULE(pcib, simplebus, tegra_pcib_driver, pcib_devclass, NULL, NULL); Index: stable/11/sys/arm/nvidia/tegra_sdhci.c =================================================================== --- stable/11/sys/arm/nvidia/tegra_sdhci.c (revision 332009) +++ stable/11/sys/arm/nvidia/tegra_sdhci.c (revision 332010) @@ -1,457 +1,467 @@ /*- * Copyright (c) 2016 Michal Meloun * 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 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 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 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 __FBSDID("$FreeBSD$"); /* * SDHCI driver glue for NVIDIA Tegra family * */ #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include "sdhci_if.h" /* Tegra SDHOST controller vendor register definitions */ #define SDMMC_VENDOR_CLOCK_CNTRL 0x100 #define VENDOR_CLOCK_CNTRL_CLK_SHIFT 8 #define VENDOR_CLOCK_CNTRL_CLK_MASK 0xFF #define SDMMC_VENDOR_SYS_SW_CNTRL 0x104 #define SDMMC_VENDOR_CAP_OVERRIDES 0x10C #define SDMMC_VENDOR_BOOT_CNTRL 0x110 #define SDMMC_VENDOR_BOOT_ACK_TIMEOUT 0x114 #define SDMMC_VENDOR_BOOT_DAT_TIMEOUT 0x118 #define SDMMC_VENDOR_DEBOUNCE_COUNT 0x11C #define SDMMC_VENDOR_MISC_CNTRL 0x120 #define VENDOR_MISC_CTRL_ENABLE_SDR104 0x8 #define VENDOR_MISC_CTRL_ENABLE_SDR50 0x10 #define VENDOR_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 #define VENDOR_MISC_CTRL_ENABLE_DDR50 0x200 #define SDMMC_MAX_CURRENT_OVERRIDE 0x124 #define SDMMC_MAX_CURRENT_OVERRIDE_HI 0x128 #define SDMMC_VENDOR_CLK_GATE_HYSTERESIS_COUNT 0x1D0 #define SDMMC_VENDOR_PHWRESET_VAL0 0x1D4 #define SDMMC_VENDOR_PHWRESET_VAL1 0x1D8 #define SDMMC_VENDOR_PHWRESET_VAL2 0x1DC #define SDMMC_SDMEMCOMPPADCTRL_0 0x1E0 #define SDMMC_AUTO_CAL_CONFIG 0x1E4 #define SDMMC_AUTO_CAL_INTERVAL 0x1E8 #define SDMMC_AUTO_CAL_STATUS 0x1EC #define SDMMC_SDMMC_MCCIF_FIFOCTRL 0x1F4 #define SDMMC_TIMEOUT_WCOAL_SDMMC 0x1F8 /* Compatible devices. */ static struct ofw_compat_data compat_data[] = { {"nvidia,tegra124-sdhci", 1}, {NULL, 0}, }; struct tegra_sdhci_softc { device_t dev; struct resource * mem_res; struct resource * irq_res; void * intr_cookie; u_int quirks; /* Chip specific quirks */ u_int caps; /* If we override SDHCI_CAPABILITIES */ uint32_t max_clk; /* Max possible freq */ clk_t clk; hwreset_t reset; - gpio_pin_t gpio_cd; - gpio_pin_t gpio_wp; gpio_pin_t gpio_power; + struct sdhci_fdt_gpio *gpio; int force_card_present; struct sdhci_slot slot; }; static inline uint32_t RD4(struct tegra_sdhci_softc *sc, bus_size_t off) { return (bus_read_4(sc->mem_res, off)); } static uint8_t tegra_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off) { struct tegra_sdhci_softc *sc; sc = device_get_softc(dev); return (bus_read_1(sc->mem_res, off)); } static uint16_t tegra_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off) { struct tegra_sdhci_softc *sc; sc = device_get_softc(dev); return (bus_read_2(sc->mem_res, off)); } static uint32_t tegra_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off) { struct tegra_sdhci_softc *sc; uint32_t val32; sc = device_get_softc(dev); val32 = bus_read_4(sc->mem_res, off); /* Force the card-present state if necessary. */ if (off == SDHCI_PRESENT_STATE && sc->force_card_present) val32 |= SDHCI_CARD_PRESENT; return (val32); } static void tegra_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t *data, bus_size_t count) { struct tegra_sdhci_softc *sc; sc = device_get_softc(dev); bus_read_multi_4(sc->mem_res, off, data, count); } static void tegra_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint8_t val) { struct tegra_sdhci_softc *sc; sc = device_get_softc(dev); bus_write_1(sc->mem_res, off, val); } static void tegra_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val) { struct tegra_sdhci_softc *sc; sc = device_get_softc(dev); bus_write_2(sc->mem_res, off, val); } static void tegra_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val) { struct tegra_sdhci_softc *sc; sc = device_get_softc(dev); bus_write_4(sc->mem_res, off, val); } static void tegra_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t *data, bus_size_t count) { struct tegra_sdhci_softc *sc; sc = device_get_softc(dev); bus_write_multi_4(sc->mem_res, off, data, count); } static void tegra_sdhci_intr(void *arg) { struct tegra_sdhci_softc *sc = arg; sdhci_generic_intr(&sc->slot); RD4(sc, SDHCI_INT_STATUS); } static int -tegra_generic_get_ro(device_t brdev, device_t reqdev) +tegra_sdhci_get_ro(device_t brdev, device_t reqdev) { + struct tegra_sdhci_softc *sc = device_get_softc(brdev); - return (0); + return (sdhci_fdt_gpio_get_readonly(sc->gpio)); } +static bool +tegra_sdhci_get_card_present(device_t dev, struct sdhci_slot *slot) +{ + struct tegra_sdhci_softc *sc = device_get_softc(dev); + + return (sdhci_fdt_gpio_get_present(sc->gpio)); +} + static int tegra_sdhci_probe(device_t dev) { struct tegra_sdhci_softc *sc; phandle_t node; pcell_t cid; const struct ofw_compat_data *cd; sc = device_get_softc(dev); if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_is_compatible(dev, "nvidia,tegra124-sdhci")) { device_set_desc(dev, "Tegra SDHCI controller"); } else return (ENXIO); cd = ofw_bus_search_compatible(dev, compat_data); if (cd->ocd_data == 0) return (ENXIO); node = ofw_bus_get_node(dev); /* Allow dts to patch quirks, slots, and max-frequency. */ if ((OF_getencprop(node, "quirks", &cid, sizeof(cid))) > 0) sc->quirks = cid; if ((OF_getencprop(node, "max-frequency", &cid, sizeof(cid))) > 0) sc->max_clk = cid; return (BUS_PROBE_DEFAULT); } static int tegra_sdhci_attach(device_t dev) { struct tegra_sdhci_softc *sc; int rid, rv; uint64_t freq; phandle_t node, prop; sc = device_get_softc(dev); sc->dev = dev; node = ofw_bus_get_node(dev); rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (!sc->mem_res) { device_printf(dev, "cannot allocate memory window\n"); rv = ENXIO; goto fail; } rid = 0; sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (!sc->irq_res) { device_printf(dev, "cannot allocate interrupt\n"); rv = ENXIO; goto fail; } if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE, NULL, tegra_sdhci_intr, sc, &sc->intr_cookie)) { device_printf(dev, "cannot setup interrupt handler\n"); rv = ENXIO; goto fail; } rv = hwreset_get_by_ofw_name(sc->dev, 0, "sdhci", &sc->reset); if (rv != 0) { device_printf(sc->dev, "Cannot get 'sdhci' reset\n"); goto fail; } rv = hwreset_deassert(sc->reset); if (rv != 0) { device_printf(dev, "Cannot unreset 'sdhci' reset\n"); goto fail; } - gpio_pin_get_by_ofw_property(sc->dev, node, "cd-gpios", &sc->gpio_cd); gpio_pin_get_by_ofw_property(sc->dev, node, "power-gpios", &sc->gpio_power); - gpio_pin_get_by_ofw_property(sc->dev, node, "wp-gpios", &sc->gpio_wp); rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); if (rv != 0) { device_printf(dev, "Cannot get clock\n"); goto fail; } rv = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); if (rv != 0) { device_printf(dev, "Cannot get clock\n"); goto fail; } rv = clk_enable(sc->clk); if (rv != 0) { device_printf(dev, "Cannot enable clock\n"); goto fail; } rv = clk_set_freq(sc->clk, 48000000, CLK_SET_ROUND_DOWN); if (rv != 0) { device_printf(dev, "Cannot set clock\n"); } rv = clk_get_freq(sc->clk, &freq); if (rv != 0) { device_printf(dev, "Cannot get clock frequency\n"); goto fail; } if (bootverbose) device_printf(dev, " Base MMC clock: %lld\n", freq); /* Fill slot information. */ sc->max_clk = (int)freq; sc->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_MISSING_CAPS; /* Limit real slot capabilities. */ sc->caps = RD4(sc, SDHCI_CAPABILITIES); if (OF_getencprop(node, "bus-width", &prop, sizeof(prop)) > 0) { sc->caps &= ~(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA); switch (prop) { case 8: sc->caps |= MMC_CAP_8_BIT_DATA; /* FALLTHROUGH */ case 4: sc->caps |= MMC_CAP_4_BIT_DATA; break; case 1: break; default: device_printf(dev, "Bad bus-width value %u\n", prop); break; } } if (OF_hasprop(node, "non-removable")) sc->force_card_present = 1; /* * Clear clock field, so SDHCI driver uses supplied frequency. * in sc->slot.max_clk */ sc->caps &= ~SDHCI_CLOCK_V3_BASE_MASK; sc->slot.quirks = sc->quirks; sc->slot.max_clk = sc->max_clk; sc->slot.caps = sc->caps; rv = sdhci_init_slot(dev, &sc->slot, 0); if (rv != 0) { goto fail; } + sc->gpio = sdhci_fdt_gpio_setup(sc->dev, &sc->slot); + bus_generic_probe(dev); bus_generic_attach(dev); sdhci_start_slot(&sc->slot); return (0); fail: - if (sc->gpio_cd != NULL) - gpio_pin_release(sc->gpio_cd); - if (sc->gpio_wp != NULL) - gpio_pin_release(sc->gpio_wp); + if (sc->gpio != NULL) + sdhci_fdt_gpio_teardown(sc->gpio); + if (sc->intr_cookie != NULL) + bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie); if (sc->gpio_power != NULL) gpio_pin_release(sc->gpio_power); if (sc->clk != NULL) clk_release(sc->clk); if (sc->reset != NULL) hwreset_release(sc->reset); - if (sc->intr_cookie != NULL) - bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie); if (sc->irq_res != NULL) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); if (sc->mem_res != NULL) bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); return (rv); } static int tegra_sdhci_detach(device_t dev) { struct tegra_sdhci_softc *sc = device_get_softc(dev); struct sdhci_slot *slot = &sc->slot; bus_generic_detach(dev); + sdhci_fdt_gpio_teardown(sc->gpio); clk_release(sc->clk); bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie); bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res), sc->irq_res); sdhci_cleanup_slot(slot); bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res), sc->mem_res); return (0); } static device_method_t tegra_sdhci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, tegra_sdhci_probe), DEVMETHOD(device_attach, tegra_sdhci_attach), DEVMETHOD(device_detach, tegra_sdhci_detach), /* Bus interface */ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar), DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar), /* MMC bridge interface */ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios), DEVMETHOD(mmcbr_request, sdhci_generic_request), - DEVMETHOD(mmcbr_get_ro, tegra_generic_get_ro), + DEVMETHOD(mmcbr_get_ro, tegra_sdhci_get_ro), DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host), DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host), /* SDHCI registers accessors */ DEVMETHOD(sdhci_read_1, tegra_sdhci_read_1), DEVMETHOD(sdhci_read_2, tegra_sdhci_read_2), DEVMETHOD(sdhci_read_4, tegra_sdhci_read_4), DEVMETHOD(sdhci_read_multi_4, tegra_sdhci_read_multi_4), DEVMETHOD(sdhci_write_1, tegra_sdhci_write_1), DEVMETHOD(sdhci_write_2, tegra_sdhci_write_2), DEVMETHOD(sdhci_write_4, tegra_sdhci_write_4), DEVMETHOD(sdhci_write_multi_4, tegra_sdhci_write_multi_4), + DEVMETHOD(sdhci_get_card_present, tegra_sdhci_get_card_present), DEVMETHOD_END }; static devclass_t tegra_sdhci_devclass; static DEFINE_CLASS_0(sdhci, tegra_sdhci_driver, tegra_sdhci_methods, sizeof(struct tegra_sdhci_softc)); DRIVER_MODULE(sdhci_tegra, simplebus, tegra_sdhci_driver, tegra_sdhci_devclass, NULL, NULL); MODULE_DEPEND(sdhci_tegra, sdhci, 1, 1, 1); MMC_DECLARE_BRIDGE(sdhci); Index: stable/11/sys/arm/nvidia/tegra_xhci.c =================================================================== --- stable/11/sys/arm/nvidia/tegra_xhci.c (nonexistent) +++ stable/11/sys/arm/nvidia/tegra_xhci.c (revision 332010) @@ -0,0 +1,1160 @@ +/*- + * Copyright (c) 2016 Michal Meloun + * 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 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 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 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 +__FBSDID("$FreeBSD$"); + +/* + * XHCI driver for Tegra SoCs. + */ +#include "opt_bus.h" +#include "opt_platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "usbdevs.h" + +/* FPCI address space */ +#define T_XUSB_CFG_0 0x000 +#define T_XUSB_CFG_1 0x004 +#define CFG_1_BUS_MASTER (1 << 2) +#define CFG_1_MEMORY_SPACE (1 << 1) +#define CFG_1_IO_SPACE (1 << 0) + +#define T_XUSB_CFG_2 0x008 +#define T_XUSB_CFG_3 0x00C +#define T_XUSB_CFG_4 0x010 +#define CFG_4_BASE_ADDRESS(x) (((x) & 0x1FFFF) << 15) + +#define T_XUSB_CFG_5 0x014 +#define T_XUSB_CFG_ARU_MAILBOX_CMD 0x0E4 +#define ARU_MAILBOX_CMD_INT_EN (1U << 31) +#define ARU_MAILBOX_CMD_DEST_XHCI (1 << 30) +#define ARU_MAILBOX_CMD_DEST_SMI (1 << 29) +#define ARU_MAILBOX_CMD_DEST_PME (1 << 28) +#define ARU_MAILBOX_CMD_DEST_FALC (1 << 27) + +#define T_XUSB_CFG_ARU_MAILBOX_DATA_IN 0x0E8 +#define ARU_MAILBOX_DATA_IN_DATA(x) (((x) & 0xFFFFFF) << 0) +#define ARU_MAILBOX_DATA_IN_TYPE(x) (((x) & 0x0000FF) << 24) + +#define T_XUSB_CFG_ARU_MAILBOX_DATA_OUT 0x0EC +#define ARU_MAILBOX_DATA_OUT_DATA(x) (((x) >> 0) & 0xFFFFFF) +#define ARU_MAILBOX_DATA_OUT_TYPE(x) (((x) >> 24) & 0x0000FF) + +#define T_XUSB_CFG_ARU_MAILBOX_OWNER 0x0F0 +#define ARU_MAILBOX_OWNER_SW 2 +#define ARU_MAILBOX_OWNER_FW 1 +#define ARU_MAILBOX_OWNER_NONE 0 + +#define XUSB_CFG_ARU_C11_CSBRANGE 0x41C /* ! UNDOCUMENTED ! */ +#define ARU_C11_CSBRANGE_PAGE(x) ((x) >> 9) +#define ARU_C11_CSBRANGE_ADDR(x) (0x800 + ((x) & 0x1FF)) +#define XUSB_CFG_ARU_SMI_INTR 0x428 /* ! UNDOCUMENTED ! */ +#define ARU_SMI_INTR_EN (1 << 3) +#define ARU_SMI_INTR_FW_HANG (1 << 1) +#define XUSB_CFG_ARU_RST 0x42C /* ! UNDOCUMENTED ! */ +#define ARU_RST_RESET (1 << 0) + +#define XUSB_HOST_CONFIGURATION 0x180 +#define CONFIGURATION_CLKEN_OVERRIDE (1U<< 31) +#define CONFIGURATION_PW_NO_DEVSEL_ERR_CYA (1 << 19) +#define CONFIGURATION_INITIATOR_READ_IDLE (1 << 18) +#define CONFIGURATION_INITIATOR_WRITE_IDLE (1 << 17) +#define CONFIGURATION_WDATA_LEAD_CYA (1 << 15) +#define CONFIGURATION_WR_INTRLV_CYA (1 << 14) +#define CONFIGURATION_TARGET_READ_IDLE (1 << 11) +#define CONFIGURATION_TARGET_WRITE_IDLE (1 << 10) +#define CONFIGURATION_MSI_VEC_EMPTY (1 << 9) +#define CONFIGURATION_UFPCI_MSIAW (1 << 7) +#define CONFIGURATION_UFPCI_PWPASSPW (1 << 6) +#define CONFIGURATION_UFPCI_PASSPW (1 << 5) +#define CONFIGURATION_UFPCI_PWPASSNPW (1 << 4) +#define CONFIGURATION_DFPCI_PWPASSNPW (1 << 3) +#define CONFIGURATION_DFPCI_RSPPASSPW (1 << 2) +#define CONFIGURATION_DFPCI_PASSPW (1 << 1) +#define CONFIGURATION_EN_FPCI (1 << 0) + +/* IPFS address space */ +#define XUSB_HOST_FPCI_ERROR_MASKS 0x184 +#define FPCI_ERROR_MASTER_ABORT (1 << 2) +#define FPCI_ERRORI_DATA_ERROR (1 << 1) +#define FPCI_ERROR_TARGET_ABORT (1 << 0) + +#define XUSB_HOST_INTR_MASK 0x188 +#define INTR_IP_INT_MASK (1 << 16) +#define INTR_MSI_MASK (1 << 8) +#define INTR_INT_MASK (1 << 0) + +#define XUSB_HOST_CLKGATE_HYSTERESIS 0x1BC + + /* CSB Falcon CPU */ +#define XUSB_FALCON_CPUCTL 0x100 +#define CPUCTL_STOPPED (1 << 5) +#define CPUCTL_HALTED (1 << 4) +#define CPUCTL_HRESET (1 << 3) +#define CPUCTL_SRESET (1 << 2) +#define CPUCTL_STARTCPU (1 << 1) +#define CPUCTL_IINVAL (1 << 0) + +#define XUSB_FALCON_BOOTVEC 0x104 +#define XUSB_FALCON_DMACTL 0x10C +#define XUSB_FALCON_IMFILLRNG1 0x154 +#define IMFILLRNG1_TAG_HI(x) (((x) & 0xFFF) << 16) +#define IMFILLRNG1_TAG_LO(x) (((x) & 0xFFF) << 0) +#define XUSB_FALCON_IMFILLCTL 0x158 + +/* CSB mempool */ +#define XUSB_CSB_MEMPOOL_APMAP 0x10181C +#define APMAP_BOOTPATH (1U << 31) + +#define XUSB_CSB_MEMPOOL_ILOAD_ATTR 0x101A00 +#define XUSB_CSB_MEMPOOL_ILOAD_BASE_LO 0x101A04 +#define XUSB_CSB_MEMPOOL_ILOAD_BASE_HI 0x101A08 +#define XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE 0x101A10 +#define L2IMEMOP_SIZE_OFFSET(x) (((x) & 0x3FF) << 8) +#define L2IMEMOP_SIZE_SIZE(x) (((x) & 0x0FF) << 24) + +#define XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG 0x101A14 +#define L2IMEMOP_INVALIDATE_ALL (0x40 << 24) +#define L2IMEMOP_LOAD_LOCKED_RESULT (0x11 << 24) + +#define XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT 0x101A18 +#define L2IMEMOP_RESULT_VLD (1U << 31) + +#define XUSB_CSB_IMEM_BLOCK_SIZE 256 + +#define TEGRA_XHCI_SS_HIGH_SPEED 120000000 +#define TEGRA_XHCI_SS_LOW_SPEED 12000000 + +/* MBOX commands. */ +#define MBOX_CMD_MSG_ENABLED 1 +#define MBOX_CMD_INC_FALC_CLOCK 2 +#define MBOX_CMD_DEC_FALC_CLOCK 3 +#define MBOX_CMD_INC_SSPI_CLOCK 4 +#define MBOX_CMD_DEC_SSPI_CLOCK 5 +#define MBOX_CMD_SET_BW 6 +#define MBOX_CMD_SET_SS_PWR_GATING 7 +#define MBOX_CMD_SET_SS_PWR_UNGATING 8 +#define MBOX_CMD_SAVE_DFE_CTLE_CTX 9 +#define MBOX_CMD_AIRPLANE_MODE_ENABLED 10 +#define MBOX_CMD_AIRPLANE_MODE_DISABLED 11 +#define MBOX_CMD_START_HSIC_IDLE 12 +#define MBOX_CMD_STOP_HSIC_IDLE 13 +#define MBOX_CMD_DBC_WAKE_STACK 14 +#define MBOX_CMD_HSIC_PRETEND_CONNECT 15 +#define MBOX_CMD_RESET_SSPI 16 +#define MBOX_CMD_DISABLE_SS_LFPS_DETECTION 17 +#define MBOX_CMD_ENABLE_SS_LFPS_DETECTION 18 + +/* MBOX responses. */ +#define MBOX_CMD_ACK (0x80 + 0) +#define MBOX_CMD_NAK (0x80 + 1) + + +#define IPFS_WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res_ipfs, (_r), (_v)) +#define IPFS_RD4(_sc, _r) bus_read_4((_sc)->mem_res_ipfs, (_r)) +#define FPCI_WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res_fpci, (_r), (_v)) +#define FPCI_RD4(_sc, _r) bus_read_4((_sc)->mem_res_fpci, (_r)) + +#define LOCK(_sc) mtx_lock(&(_sc)->mtx) +#define UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) +#define SLEEP(_sc, timeout) \ + mtx_sleep(sc, &sc->mtx, 0, "tegra_xhci", timeout); +#define LOCK_INIT(_sc) \ + mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_xhci", MTX_DEF) +#define LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx) +#define ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED) +#define ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED) + +struct tegra_xusb_fw_hdr { + uint32_t boot_loadaddr_in_imem; + uint32_t boot_codedfi_offset; + uint32_t boot_codetag; + uint32_t boot_codesize; + + uint32_t phys_memaddr; + uint16_t reqphys_memsize; + uint16_t alloc_phys_memsize; + + uint32_t rodata_img_offset; + uint32_t rodata_section_start; + uint32_t rodata_section_end; + uint32_t main_fnaddr; + + uint32_t fwimg_cksum; + uint32_t fwimg_created_time; + + uint32_t imem_resident_start; + uint32_t imem_resident_end; + uint32_t idirect_start; + uint32_t idirect_end; + uint32_t l2_imem_start; + uint32_t l2_imem_end; + uint32_t version_id; + uint8_t init_ddirect; + uint8_t reserved[3]; + uint32_t phys_addr_log_buffer; + uint32_t total_log_entries; + uint32_t dequeue_ptr; + uint32_t dummy[2]; + uint32_t fwimg_len; + uint8_t magic[8]; + uint32_t ss_low_power_entry_timeout; + uint8_t num_hsic_port; + uint8_t ss_portmap; + uint8_t build; + uint8_t padding[137]; /* Pad to 256 bytes */ +}; + +/* Compatible devices. */ +static struct ofw_compat_data compat_data[] = { + {"nvidia,tegra124-xusb", 1}, + {NULL, 0} +}; + +struct tegra_xhci_softc { + struct xhci_softc xhci_softc; + device_t dev; + struct mtx mtx; + struct resource *mem_res_fpci; + struct resource *mem_res_ipfs; + struct resource *irq_res_mbox; + void *irq_hdl_mbox; + + clk_t clk_xusb_host; + clk_t clk_xusb_gate; + clk_t clk_xusb_falcon_src; + clk_t clk_xusb_ss; + clk_t clk_xusb_hs_src; + clk_t clk_xusb_fs_src; + hwreset_t hwreset_xusb_host; + hwreset_t hwreset_xusb_ss; + regulator_t supply_avddio_pex; + regulator_t supply_dvddio_pex; + regulator_t supply_avdd_usb; + regulator_t supply_avdd_pll_utmip; + regulator_t supply_avdd_pll_erefe; + regulator_t supply_avdd_usb_ss_pll; + regulator_t supply_hvdd_usb_ss; + regulator_t supply_hvdd_usb_ss_pll_e; + phy_t phy_usb2_0; + phy_t phy_usb2_1; + phy_t phy_usb2_2; + phy_t phy_usb3_0; + + struct intr_config_hook irq_hook; + bool xhci_inited; + char *fw_name; + vm_offset_t fw_vaddr; + vm_size_t fw_size; +}; + +static uint32_t +CSB_RD4(struct tegra_xhci_softc *sc, uint32_t addr) +{ + + FPCI_WR4(sc, XUSB_CFG_ARU_C11_CSBRANGE, ARU_C11_CSBRANGE_PAGE(addr)); + return (FPCI_RD4(sc, ARU_C11_CSBRANGE_ADDR(addr))); +} + +static void +CSB_WR4(struct tegra_xhci_softc *sc, uint32_t addr, uint32_t val) +{ + + FPCI_WR4(sc, XUSB_CFG_ARU_C11_CSBRANGE, ARU_C11_CSBRANGE_PAGE(addr)); + FPCI_WR4(sc, ARU_C11_CSBRANGE_ADDR(addr), val); +} + +static int +get_fdt_resources(struct tegra_xhci_softc *sc, phandle_t node) +{ + int rv; + + rv = regulator_get_by_ofw_property(sc->dev, 0, "avddio-pex-supply", + &sc->supply_avddio_pex); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'avddio-pex' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, "dvddio-pex-supply", + &sc->supply_dvddio_pex); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'dvddio-pex' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-usb-supply", + &sc->supply_avdd_usb); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'avdd-usb' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-utmip-supply", + &sc->supply_avdd_pll_utmip); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'avdd-pll-utmip' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-pll-erefe-supply", + &sc->supply_avdd_pll_erefe); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'avdd-pll-erefe' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, "avdd-usb-ss-pll-supply", + &sc->supply_avdd_usb_ss_pll); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'avdd-usb-ss-pll' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, "hvdd-usb-ss-supply", + &sc->supply_hvdd_usb_ss); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'hvdd-usb-ss' regulator\n"); + return (ENXIO); + } + rv = regulator_get_by_ofw_property(sc->dev, 0, + "hvdd-usb-ss-pll-e-supply", &sc->supply_hvdd_usb_ss_pll_e); + if (rv != 0) { + device_printf(sc->dev, + "Cannot get 'hvdd-usb-ss-pll-e' regulator\n"); + return (ENXIO); + } + + rv = hwreset_get_by_ofw_name(sc->dev, 0, "xusb_host", + &sc->hwreset_xusb_host); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_host' reset\n"); + return (ENXIO); + } + rv = hwreset_get_by_ofw_name(sc->dev, 0, "xusb_ss", + &sc->hwreset_xusb_ss); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_ss' reset\n"); + return (ENXIO); + } + + rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-0", &sc->phy_usb2_0); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'usb2-0' phy\n"); + return (ENXIO); + } + rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-1", &sc->phy_usb2_1); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'usb2-1' phy\n"); + return (ENXIO); + } + rv = phy_get_by_ofw_name(sc->dev, 0, "usb2-2", &sc->phy_usb2_2); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'usb2-2' phy\n"); + return (ENXIO); + } + rv = phy_get_by_ofw_name(sc->dev, 0, "usb3-0", &sc->phy_usb3_0); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'usb3-0' phy\n"); + return (ENXIO); + } + + rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_host", + &sc->clk_xusb_host); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_host' clock\n"); + return (ENXIO); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_falcon_src", + &sc->clk_xusb_falcon_src); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_falcon_src' clock\n"); + return (ENXIO); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_ss", + &sc->clk_xusb_ss); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_ss' clock\n"); + return (ENXIO); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_hs_src", + &sc->clk_xusb_hs_src); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_hs_src' clock\n"); + return (ENXIO); + } + rv = clk_get_by_ofw_name(sc->dev, 0, "xusb_fs_src", + &sc->clk_xusb_fs_src); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_fs_src' clock\n"); + return (ENXIO); + } + rv = clk_get_by_ofw_index_prop(sc->dev, 0, "freebsd,clock-xusb-gate", 0, + &sc->clk_xusb_gate); + if (rv != 0) { + device_printf(sc->dev, "Cannot get 'xusb_gate' clock\n"); + return (ENXIO); + } + return (0); +} + +static int +enable_fdt_resources(struct tegra_xhci_softc *sc) +{ + int rv; + + rv = hwreset_assert(sc->hwreset_xusb_host); + if (rv != 0) { + device_printf(sc->dev, "Cannot reset 'xusb_host' reset\n"); + return (rv); + } + rv = hwreset_assert(sc->hwreset_xusb_ss); + if (rv != 0) { + device_printf(sc->dev, "Cannot reset 'xusb_ss' reset\n"); + return (rv); + } + + rv = regulator_enable(sc->supply_avddio_pex); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'avddio_pex' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_dvddio_pex); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'dvddio_pex' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_avdd_usb); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'avdd_usb' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_avdd_pll_utmip); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'avdd_pll_utmip-5v' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_avdd_pll_erefe); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'avdd_pll_erefe' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_avdd_usb_ss_pll); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'avdd_usb_ss_pll' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_hvdd_usb_ss); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'hvdd_usb_ss' regulator\n"); + return (rv); + } + rv = regulator_enable(sc->supply_hvdd_usb_ss_pll_e); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'hvdd_usb_ss_pll_e' regulator\n"); + return (rv); + } + + /* Power off XUSB host and XUSB SS domains. */ + rv = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA); + if (rv != 0) { + device_printf(sc->dev, "Cannot powerdown 'xusba' domain\n"); + return (rv); + } + rv = tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC); + if (rv != 0) { + device_printf(sc->dev, "Cannot powerdown 'xusbc' domain\n"); + return (rv); + } + + /* Setup XUSB ss_src clock first */ + clk_set_freq(sc->clk_xusb_ss, TEGRA_XHCI_SS_HIGH_SPEED, 0); + if (rv != 0) + return (rv); + + /* The XUSB gate clock must be enabled before XUSBA can be powered. */ + rv = clk_enable(sc->clk_xusb_gate); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'xusb_gate' clock\n"); + return (rv); + } + + /* Power on XUSB host and XUSB SS domains. */ + rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBC, + sc->clk_xusb_host, sc->hwreset_xusb_host); + if (rv != 0) { + device_printf(sc->dev, "Cannot powerup 'xusbc' domain\n"); + return (rv); + } + rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_XUSBA, + sc->clk_xusb_ss, sc->hwreset_xusb_ss); + if (rv != 0) { + device_printf(sc->dev, "Cannot powerup 'xusba' domain\n"); + return (rv); + } + + /* Enable rest of clocks */ + rv = clk_enable(sc->clk_xusb_falcon_src); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'xusb_falcon_src' clock\n"); + return (rv); + } + rv = clk_enable(sc->clk_xusb_fs_src); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'xusb_fs_src' clock\n"); + return (rv); + } + rv = clk_enable(sc->clk_xusb_hs_src); + if (rv != 0) { + device_printf(sc->dev, + "Cannot enable 'xusb_hs_src' clock\n"); + return (rv); + } + + rv = phy_enable(sc->dev, sc->phy_usb2_0); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable USB2_0 phy\n"); + return (rv); + } + rv = phy_enable(sc->dev, sc->phy_usb2_1); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable USB2_1 phy\n"); + return (rv); + } + rv = phy_enable(sc->dev, sc->phy_usb2_2); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable USB2_2 phy\n"); + return (rv); + } + rv = phy_enable(sc->dev, sc->phy_usb3_0); + if (rv != 0) { + device_printf(sc->dev, "Cannot enable USB3_0 phy\n"); + return (rv); + } + + return (0); +} + +/* Respond by ACK/NAK back to FW */ +static void +mbox_send_ack(struct tegra_xhci_softc *sc, uint32_t cmd, uint32_t data) +{ + uint32_t reg; + + reg = ARU_MAILBOX_DATA_IN_TYPE(cmd) | ARU_MAILBOX_DATA_IN_DATA(data); + FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_IN, reg); + + reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD); + reg |= ARU_MAILBOX_CMD_DEST_FALC | ARU_MAILBOX_CMD_INT_EN; + FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg); +} + +/* Sent command to FW */ +static int +mbox_send_cmd(struct tegra_xhci_softc *sc, uint32_t cmd, uint32_t data) +{ + uint32_t reg; + int i; + + reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER); + if (reg != ARU_MAILBOX_OWNER_NONE) { + device_printf(sc->dev, + "CPU mailbox is busy: 0x%08X\n", reg); + return (EBUSY); + } + /* XXX Is this right? Retry loop? Wait before send? */ + FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER, ARU_MAILBOX_OWNER_SW); + reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER); + if (reg != ARU_MAILBOX_OWNER_SW) { + device_printf(sc->dev, + "Cannot acquire CPU mailbox: 0x%08X\n", reg); + return (EBUSY); + } + reg = ARU_MAILBOX_DATA_IN_TYPE(cmd) | ARU_MAILBOX_DATA_IN_DATA(data); + FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_IN, reg); + + reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD); + reg |= ARU_MAILBOX_CMD_DEST_FALC | ARU_MAILBOX_CMD_INT_EN; + FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg); + + for (i = 250; i > 0; i--) { + reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER); + if (reg == ARU_MAILBOX_OWNER_NONE) + break; + DELAY(100); + } + if (i <= 0) { + device_printf(sc->dev, + "Command response timeout: 0x%08X\n", reg); + return (ETIMEDOUT); + } + + return(0); +} + +static void +process_msg(struct tegra_xhci_softc *sc, uint32_t req_cmd, uint32_t req_data, + uint32_t *resp_cmd, uint32_t *resp_data) +{ + uint64_t freq; + int rv; + + /* In most cases, data are echoed back. */ + *resp_data = req_data; + switch (req_cmd) { + case MBOX_CMD_INC_FALC_CLOCK: + case MBOX_CMD_DEC_FALC_CLOCK: + rv = clk_set_freq(sc->clk_xusb_falcon_src, req_data * 1000ULL, + 0); + if (rv == 0) { + rv = clk_get_freq(sc->clk_xusb_falcon_src, &freq); + *resp_data = (uint32_t)(freq / 1000); + } + *resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK; + break; + + case MBOX_CMD_INC_SSPI_CLOCK: + case MBOX_CMD_DEC_SSPI_CLOCK: + rv = clk_set_freq(sc->clk_xusb_ss, req_data * 1000ULL, + 0); + if (rv == 0) { + rv = clk_get_freq(sc->clk_xusb_ss, &freq); + *resp_data = (uint32_t)(freq / 1000); + } + *resp_cmd = rv == 0 ? MBOX_CMD_ACK: MBOX_CMD_NAK; + break; + + case MBOX_CMD_SET_BW: + /* No respense is expected. */ + *resp_cmd = 0; + break; + + case MBOX_CMD_SET_SS_PWR_GATING: + case MBOX_CMD_SET_SS_PWR_UNGATING: + *resp_cmd = MBOX_CMD_NAK; + break; + + case MBOX_CMD_SAVE_DFE_CTLE_CTX: + /* Not implemented yet. */ + *resp_cmd = MBOX_CMD_ACK; + break; + + + case MBOX_CMD_START_HSIC_IDLE: + case MBOX_CMD_STOP_HSIC_IDLE: + /* Not implemented yet. */ + *resp_cmd = MBOX_CMD_NAK; + break; + + case MBOX_CMD_DISABLE_SS_LFPS_DETECTION: + case MBOX_CMD_ENABLE_SS_LFPS_DETECTION: + /* Not implemented yet. */ + *resp_cmd = MBOX_CMD_NAK; + break; + + case MBOX_CMD_AIRPLANE_MODE_ENABLED: + case MBOX_CMD_AIRPLANE_MODE_DISABLED: + case MBOX_CMD_DBC_WAKE_STACK: + case MBOX_CMD_HSIC_PRETEND_CONNECT: + case MBOX_CMD_RESET_SSPI: + device_printf(sc->dev, + "Received unused/unexpected command: %u\n", req_cmd); + *resp_cmd = 0; + break; + + default: + device_printf(sc->dev, + "Received unknown command: %u\n", req_cmd); + } +} + +static void +intr_mbox(void *arg) +{ + struct tegra_xhci_softc *sc; + uint32_t reg, msg, resp_cmd, resp_data; + + sc = (struct tegra_xhci_softc *)arg; + + /* Clear interrupt first */ + reg = FPCI_RD4(sc, XUSB_CFG_ARU_SMI_INTR); + FPCI_WR4(sc, XUSB_CFG_ARU_SMI_INTR, reg); + if (reg & ARU_SMI_INTR_FW_HANG) { + device_printf(sc->dev, + "XUSB CPU firmware hang!!! CPUCTL: 0x%08X\n", + CSB_RD4(sc, XUSB_FALCON_CPUCTL)); + } + + msg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_DATA_OUT); + resp_cmd = 0; + process_msg(sc, ARU_MAILBOX_DATA_OUT_TYPE(msg), + ARU_MAILBOX_DATA_OUT_DATA(msg), &resp_cmd, &resp_data); + if (resp_cmd != 0) + mbox_send_ack(sc, resp_cmd, resp_data); + else + FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_OWNER, + ARU_MAILBOX_OWNER_NONE); + + reg = FPCI_RD4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD); + reg &= ~ARU_MAILBOX_CMD_DEST_SMI; + FPCI_WR4(sc, T_XUSB_CFG_ARU_MAILBOX_CMD, reg); + +} + +static int +load_fw(struct tegra_xhci_softc *sc) +{ + const struct firmware *fw; + const struct tegra_xusb_fw_hdr *fw_hdr; + vm_paddr_t fw_paddr, fw_base; + vm_offset_t fw_vaddr; + vm_size_t fw_size; + uint32_t code_tags, code_size; + struct clocktime fw_clock; + struct timespec fw_timespec; + int i; + + /* Reset ARU */ + FPCI_WR4(sc, XUSB_CFG_ARU_RST, ARU_RST_RESET); + DELAY(3000); + + /* Check if FALCON already runs */ + if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO) != 0) { + device_printf(sc->dev, + "XUSB CPU is already loaded, CPUCTL: 0x%08X\n", + CSB_RD4(sc, XUSB_FALCON_CPUCTL)); + return (0); + } + + fw = firmware_get(sc->fw_name); + if (fw == NULL) { + device_printf(sc->dev, "Cannot read xusb firmware\n"); + return (ENOENT); + } + + /* Allocate uncached memory and copy firmware into. */ + fw_hdr = (const struct tegra_xusb_fw_hdr *)fw->data; + fw_size = fw_hdr->fwimg_len; + + fw_vaddr = kmem_alloc_contig(kernel_arena, fw_size, + M_WAITOK, 0, -1UL, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE); + fw_paddr = vtophys(fw_vaddr); + fw_hdr = (const struct tegra_xusb_fw_hdr *)fw_vaddr; + memcpy((void *)fw_vaddr, fw->data, fw_size); + + firmware_put(fw, FIRMWARE_UNLOAD); + sc->fw_vaddr = fw_vaddr; + sc->fw_size = fw_size; + + /* Setup firmware physical address and size. */ + fw_base = fw_paddr + sizeof(*fw_hdr); + CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_ATTR, fw_size); + CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO, fw_base & 0xFFFFFFFF); + CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI, (uint64_t)fw_base >> 32); + CSB_WR4(sc, XUSB_CSB_MEMPOOL_APMAP, APMAP_BOOTPATH); + + /* Invalidate full L2IMEM context. */ + CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG, + L2IMEMOP_INVALIDATE_ALL); + + /* Program load of L2IMEM by boot code. */ + code_tags = howmany(fw_hdr->boot_codetag, XUSB_CSB_IMEM_BLOCK_SIZE); + code_size = howmany(fw_hdr->boot_codesize, XUSB_CSB_IMEM_BLOCK_SIZE); + CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE, + L2IMEMOP_SIZE_OFFSET(code_tags) | + L2IMEMOP_SIZE_SIZE(code_size)); + + /* Execute L2IMEM boot code fetch. */ + CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG, + L2IMEMOP_LOAD_LOCKED_RESULT); + + /* Program FALCON auto-fill range and block count */ + CSB_WR4(sc, XUSB_FALCON_IMFILLCTL, code_size); + CSB_WR4(sc, XUSB_FALCON_IMFILLRNG1, + IMFILLRNG1_TAG_LO(code_tags) | + IMFILLRNG1_TAG_HI(code_tags + code_size)); + + CSB_WR4(sc, XUSB_FALCON_DMACTL, 0); + /* Wait for CPU */ + for (i = 500; i > 0; i--) { + if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT) & + L2IMEMOP_RESULT_VLD) + break; + DELAY(100); + } + if (i <= 0) { + device_printf(sc->dev, "Timedout while wating for DMA, " + "state: 0x%08X\n", + CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT)); + return (ETIMEDOUT); + } + + /* Boot FALCON cpu */ + CSB_WR4(sc, XUSB_FALCON_BOOTVEC, fw_hdr->boot_codetag); + CSB_WR4(sc, XUSB_FALCON_CPUCTL, CPUCTL_STARTCPU); + + /* Wait for CPU */ + for (i = 50; i > 0; i--) { + if (CSB_RD4(sc, XUSB_FALCON_CPUCTL) == CPUCTL_STOPPED) + break; + DELAY(100); + } + if (i <= 0) { + device_printf(sc->dev, "Timedout while wating for FALCON cpu, " + "state: 0x%08X\n", CSB_RD4(sc, XUSB_FALCON_CPUCTL)); + return (ETIMEDOUT); + } + + fw_timespec.tv_sec = fw_hdr->fwimg_created_time; + fw_timespec.tv_nsec = 0; + clock_ts_to_ct(&fw_timespec, &fw_clock); + device_printf(sc->dev, + " Falcon firmware version: %02X.%02X.%04X," + " (%d/%d/%d %d:%02d:%02d UTC)\n", + (fw_hdr->version_id >> 24) & 0xFF,(fw_hdr->version_id >> 15) & 0xFF, + fw_hdr->version_id & 0xFFFF, + fw_clock.day, fw_clock.mon, fw_clock.year, + fw_clock.hour, fw_clock.min, fw_clock.sec); + + return (0); +} + +static int +init_hw(struct tegra_xhci_softc *sc) +{ + int rv; + uint32_t reg; + rman_res_t base_addr; + + base_addr = rman_get_start(sc->xhci_softc.sc_io_res); + + /* Enable FPCI access */ + reg = IPFS_RD4(sc, XUSB_HOST_CONFIGURATION); + reg |= CONFIGURATION_EN_FPCI; + IPFS_WR4(sc, XUSB_HOST_CONFIGURATION, reg); + IPFS_RD4(sc, XUSB_HOST_CONFIGURATION); + + + /* Program bar for XHCI base address */ + reg = FPCI_RD4(sc, T_XUSB_CFG_4); + reg &= ~CFG_4_BASE_ADDRESS(~0); + reg |= CFG_4_BASE_ADDRESS((uint32_t)base_addr >> 15); + FPCI_WR4(sc, T_XUSB_CFG_4, reg); + FPCI_WR4(sc, T_XUSB_CFG_5, (uint32_t)((uint64_t)(base_addr) >> 32)); + + /* Enable bus master */ + reg = FPCI_RD4(sc, T_XUSB_CFG_1); + reg |= CFG_1_IO_SPACE; + reg |= CFG_1_MEMORY_SPACE; + reg |= CFG_1_BUS_MASTER; + FPCI_WR4(sc, T_XUSB_CFG_1, reg); + + /* Enable Interrupts */ + reg = IPFS_RD4(sc, XUSB_HOST_INTR_MASK); + reg |= INTR_IP_INT_MASK; + IPFS_WR4(sc, XUSB_HOST_INTR_MASK, reg); + + /* Set hysteresis */ + IPFS_WR4(sc, XUSB_HOST_CLKGATE_HYSTERESIS, 128); + + rv = load_fw(sc); + if (rv != 0) + return rv; + return (0); +} + +static int +tegra_xhci_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) { + device_set_desc(dev, "Nvidia Tegra XHCI controller"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +tegra_xhci_detach(device_t dev) +{ + struct tegra_xhci_softc *sc; + struct xhci_softc *xsc; + + sc = device_get_softc(dev); + xsc = &sc->xhci_softc; + + /* during module unload there are lots of children leftover */ + device_delete_children(dev); + if (sc->xhci_inited) { + usb_callout_drain(&xsc->sc_callout); + xhci_halt_controller(xsc); + } + + if (xsc->sc_irq_res && xsc->sc_intr_hdl) { + bus_teardown_intr(dev, xsc->sc_irq_res, xsc->sc_intr_hdl); + xsc->sc_intr_hdl = NULL; + } + if (xsc->sc_irq_res) { + bus_release_resource(dev, SYS_RES_IRQ, + rman_get_rid(xsc->sc_irq_res), xsc->sc_irq_res); + xsc->sc_irq_res = NULL; + } + if (xsc->sc_io_res != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(xsc->sc_io_res), xsc->sc_io_res); + xsc->sc_io_res = NULL; + } + if (sc->xhci_inited) + xhci_uninit(xsc); + if (sc->irq_hdl_mbox != NULL) + bus_teardown_intr(dev, sc->irq_res_mbox, sc->irq_hdl_mbox); + if (sc->fw_vaddr != 0) + kmem_free(kernel_arena, sc->fw_vaddr, sc->fw_size); + LOCK_DESTROY(sc); + return (0); +} + +static int +tegra_xhci_attach(device_t dev) +{ + struct tegra_xhci_softc *sc; + struct xhci_softc *xsc; + int rv, rid; + phandle_t node; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->fw_name = "tegra124_xusb_fw"; + node = ofw_bus_get_node(dev); + xsc = &sc->xhci_softc; + LOCK_INIT(sc); + + rv = get_fdt_resources(sc, node); + if (rv != 0) { + rv = ENXIO; + goto error; + } + rv = enable_fdt_resources(sc); + if (rv != 0) { + rv = ENXIO; + goto error; + } + + /* Allocate resources. */ + rid = 0; + xsc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (xsc->sc_io_res == NULL) { + device_printf(dev, + "Could not allocate HCD memory resources\n"); + rv = ENXIO; + goto error; + } + rid = 1; + sc->mem_res_fpci = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res_fpci == NULL) { + device_printf(dev, + "Could not allocate FPCI memory resources\n"); + rv = ENXIO; + goto error; + } + rid = 2; + sc->mem_res_ipfs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (sc->mem_res_ipfs == NULL) { + device_printf(dev, + "Could not allocate IPFS memory resources\n"); + rv = ENXIO; + goto error; + } + + rid = 0; + xsc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (xsc->sc_irq_res == NULL) { + device_printf(dev, "Could not allocate HCD IRQ resources\n"); + rv = ENXIO; + goto error; + } + rid = 1; + sc->irq_res_mbox = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_ACTIVE); + if (sc->irq_res_mbox == NULL) { + device_printf(dev, "Could not allocate MBOX IRQ resources\n"); + rv = ENXIO; + goto error; + } + + rv = init_hw(sc); + if (rv != 0) { + device_printf(dev, "Could not initialize XUSB hardware\n"); + goto error; + } + + /* Wakeup and enable firmaware */ + rv = mbox_send_cmd(sc, MBOX_CMD_MSG_ENABLED, 0); + if (rv != 0) { + device_printf(sc->dev, "Could not enable XUSB firmware\n"); + goto error; + } + + /* Fill data for XHCI driver. */ + xsc->sc_bus.parent = dev; + xsc->sc_bus.devices = xsc->sc_devices; + xsc->sc_bus.devices_max = XHCI_MAX_DEVICES; + + xsc->sc_io_tag = rman_get_bustag(xsc->sc_io_res); + xsc->sc_io_hdl = rman_get_bushandle(xsc->sc_io_res); + xsc->sc_io_size = rman_get_size(xsc->sc_io_res); + strlcpy(xsc->sc_vendor, "Nvidia", sizeof(xsc->sc_vendor)); + + /* Add USB bus device. */ + xsc->sc_bus.bdev = device_add_child(sc->dev, "usbus", -1); + if (xsc->sc_bus.bdev == NULL) { + device_printf(sc->dev, "Could not add USB device\n"); + rv = ENXIO; + goto error; + } + device_set_ivars(xsc->sc_bus.bdev, &xsc->sc_bus); + device_set_desc(xsc->sc_bus.bdev, "Nvidia USB 3.0 controller"); + + rv = xhci_init(xsc, sc->dev, 1); + if (rv != 0) { + device_printf(sc->dev, "USB init failed: %d\n", rv); + goto error; + } + sc->xhci_inited = true; + rv = xhci_start_controller(xsc); + if (rv != 0) { + device_printf(sc->dev, + "Could not start XHCI controller: %d\n", rv); + goto error; + } + + rv = bus_setup_intr(dev, sc->irq_res_mbox, INTR_TYPE_MISC | INTR_MPSAFE, + NULL, intr_mbox, sc, &sc->irq_hdl_mbox); + if (rv != 0) { + device_printf(dev, "Could not setup error IRQ: %d\n",rv); + xsc->sc_intr_hdl = NULL; + goto error; + } + + rv = bus_setup_intr(dev, xsc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, + NULL, (driver_intr_t *)xhci_interrupt, xsc, &xsc->sc_intr_hdl); + if (rv != 0) { + device_printf(dev, "Could not setup error IRQ: %d\n",rv); + xsc->sc_intr_hdl = NULL; + goto error; + } + + /* Probe the bus. */ + rv = device_probe_and_attach(xsc->sc_bus.bdev); + if (rv != 0) { + device_printf(sc->dev, "Could not initialize USB: %d\n", rv); + goto error; + } + + return (0); + +error: +panic("XXXXX"); + tegra_xhci_detach(dev); + return (rv); +} + +static device_method_t xhci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, tegra_xhci_probe), + DEVMETHOD(device_attach, tegra_xhci_attach), + DEVMETHOD(device_detach, tegra_xhci_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + + DEVMETHOD_END +}; + +static devclass_t xhci_devclass; +static DEFINE_CLASS_0(xhci, xhci_driver, xhci_methods, + sizeof(struct tegra_xhci_softc)); +DRIVER_MODULE(tegra_xhci, simplebus, xhci_driver, xhci_devclass, NULL, NULL); +MODULE_DEPEND(tegra_xhci, usb, 1, 1, 1); Property changes on: stable/11/sys/arm/nvidia/tegra_xhci.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: stable/11/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts =================================================================== --- stable/11/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts (revision 332009) +++ stable/11/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts (revision 332010) @@ -1,46 +1,48 @@ /*- * Copyright (c) 2016 Michal Meloun * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * 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 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 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 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. * * $FreeBSD$ */ #include "tegra124-jetson-tk1.dts" / { chosen { stdin = &uartd; stdout = &uartd; }; memory { /* reg = <0x0 0x80000000 0x0 0x80000000>; */ reg = <0x0 0x80000000 0x0 0x70000000>; }; - + usb@70090000 { + freebsd,clock-xusb-gate = <&tegra_car 143>; + }; }; Index: stable/11/sys/contrib/dev/nvidia/LICENCE.nvidia =================================================================== --- stable/11/sys/contrib/dev/nvidia/LICENCE.nvidia (nonexistent) +++ stable/11/sys/contrib/dev/nvidia/LICENCE.nvidia (revision 332010) @@ -0,0 +1,131 @@ + License For Customer Use of NVIDIA Software + + +IMPORTANT NOTICE -- READ CAREFULLY: This License For Customer Use of +NVIDIA Software ("LICENSE") is the agreement which governs use of +the software of NVIDIA Corporation and its subsidiaries ("NVIDIA") +downloadable herefrom, including computer software and associated +printed materials ("SOFTWARE"). By downloading, installing, copying, +or otherwise using the SOFTWARE, you agree to be bound by the terms +of this LICENSE. If you do not agree to the terms of this LICENSE, +do not download the SOFTWARE. + +RECITALS + +Use of NVIDIA's products requires three elements: the SOFTWARE, the +hardware, and a personal computer. The SOFTWARE is protected by copyright +laws and international copyright treaties, as well as other intellectual +property laws and treaties. The SOFTWARE may be protected by various +patents, and is not sold, and instead is only licensed for use, strictly +in accordance with this document. The hardware is protected by various +patents, and is sold, but this agreement does not cover that sale, since +it may not necessarily be sold as a package with the SOFTWARE. This +agreement sets forth the terms and conditions of the SOFTWARE LICENSE only. + +1. DEFINITIONS + +1.1 Customer. Customer means the entity or individual that +downloads or otherwise obtains the SOFTWARE. + +2. GRANT OF LICENSE + +2.1 Rights and Limitations of Grant. NVIDIA hereby grants Customer +the following non-exclusive, non-transferable right to use the +SOFTWARE, with the following limitations: + +2.1.1 Rights. Customer may install and use multiple copies of the +SOFTWARE on a shared computer or concurrently on different computers, +and make multiple back-up copies of the SOFTWARE, solely for Customer's +use within Customer's Enterprise. "Enterprise" shall mean individual use +by Customer or any legal entity (such as a corporation or university) +and the subsidiaries it owns by more than fifty percent (50%). + +2.1.2 Open Source Exception. Notwithstanding the foregoing terms +of Section 2.1.1, SOFTWARE may be copied and redistributed solely for +use on operating systems distributed under the terms of an OSI-approved +open source license as listed by the Open Source Initiative at +http://opensource.org, provided that the binary files thereof are not +modified, and Customer provides a copy of this license with the SOFTWARE. + +2.1.3 Limitations. + +No Reverse Engineering. Customer may not reverse engineer, +decompile, or disassemble the SOFTWARE, nor attempt in any other +manner to obtain the source code. + +Usage. SOFTWARE is licensed only for use with microprocessor(s) which have +been (i) designed by NVIDIA and (ii) either (a) sold by or (b) licensed by +NVIDIA. Customer shall not use SOFTWARE in conjunction with, nor cause +SOFTWARE to be executed by, any other microprocessor. + +No Translation. Customer shall not translate SOFTWARE, nor cause or permit +SOFTWARE to be translated, from the architecture or language in which it is +originally provided by NVIDIA, into any other architecture or language. + +No Rental. Customer may not rent or lease the SOFTWARE to someone +else. + +3. TERMINATION + +This LICENSE will automatically terminate if Customer fails to +comply with any of the terms and conditions hereof. In such event, +Customer must destroy all copies of the SOFTWARE and all of its +component parts. + +Defensive Suspension. If Customer commences or participates in any legal +proceeding against NVIDIA, then NVIDIA may, in its sole discretion, +suspend or terminate all license grants and any other rights provided +under this LICENSE during the pendency of such legal proceedings. + +4. COPYRIGHT + +All title and copyrights in and to the SOFTWARE (including but +not limited to all images, photographs, animations, video, audio, +music, text, and other information incorporated into the SOFTWARE), +the accompanying printed materials, and any copies of the SOFTWARE, +are owned by NVIDIA, or its suppliers. The SOFTWARE is protected +by copyright laws and international treaty provisions. Accordingly, +Customer is required to treat the SOFTWARE like any other copyrighted +material, except as otherwise allowed pursuant to this LICENSE +and that it may make one copy of the SOFTWARE solely for backup or +archive purposes. + +5. APPLICABLE LAW + +This agreement shall be deemed to have been made in, and shall be +construed pursuant to, the laws of the State of California. + +6. DISCLAIMER OF WARRANTIES AND LIMITATION ON LIABILITY + +6.1 No Warranties. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE +LAW, THE SOFTWARE IS PROVIDED "AS IS" AND NVIDIA AND ITS SUPPLIERS +DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. + +6.2 No Liability for Consequential Damages. TO THE MAXIMUM +EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL NVIDIA OR +ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, +DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS +OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT +OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF NVIDIA HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. MISCELLANEOUS + +The United Nations Convention on Contracts for the International +Sale of Goods is specifically disclaimed. If any provision of this +LICENSE is inconsistent with, or cannot be fully enforced under, +the law, such provision will be construed as limited to the extent +necessary to be consistent with and fully enforceable under the law. +This agreement is the final, complete and exclusive agreement between +the parties relating to the subject matter hereof, and supersedes +all prior or contemporaneous understandings and agreements relating +to such subject matter, whether oral or written. Customer agrees +that it will not ship, transfer or export the SOFTWARE into any +country, or use the SOFTWARE in any manner, prohibited by the +United States Bureau of Export Administration or any export laws, +restrictions or regulations. This LICENSE may only be modified in +writing signed by an authorized officer of NVIDIA. + Index: stable/11/sys/contrib/dev/nvidia/tegra124_xusb.bin.uu =================================================================== --- stable/11/sys/contrib/dev/nvidia/tegra124_xusb.bin.uu (nonexistent) +++ stable/11/sys/contrib/dev/nvidia/tegra124_xusb.bin.uu (revision 332010) @@ -0,0 +1,2996 @@ +begin 644 tegra124_xusb.bin +M`%L````(`@``"`(```4``````````````````````````````.$``+O4``#_ +MFQ=4`&\``&#$`````0``GFX```#%```U`0(``@!&10$````````````````` +M```````````````.`@!855-"1E<``$!"#P``_R`!`@0``(`@!0`````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````/0@<`#T($``]"#,`/0@ +M0`#T($``]"!``/0@H`#T($``]"!``/0@0`#T($``]"!``/0@0`#T($``]"!` +M`/0@0`#YD/F@^;#YP/G0^>#Y\/Z*`?F@?A!P`/R@_J@`]#(!_/#\X/S0_,#\ +ML/R@_)#X`0#YD/F@^;#YP/G0^>#Y\/Z*`?F@?NRI`/R@_J@`]#(!_/#\X/S0 +M_,#\L/R@_)#X`0#YD/F@^;#YP/G0^>#Y\/Z*`?F@?M9W`/R@_J@`_/#\X/S0 +M_,#\L/R@_)#X`?F0^:#YL/G`^=#YX/GP_HH!^:!^M+H`_*#^J`#T,@'\\/S@ +M_-#\P/RP_*#\D/@!^/CX^/CX`+:E&+/``$+?X!D``'_Y\)408/FSI!%NV0"I +M`0"FV?0;#M^)7```/_D^7P$`V0"G`0"FV?0;#M^)7```/_D^>@$`^`CX`+.D +M$3S9`*D!`*;9]!L4WXE<```_^?"5!/"4]SY]`0#9`*V1P:```\FKG9'QH``#R:N=G\&0``O)JY +M^`#9(AH``#WT/)^YV24:```\G[F]]-D4&@``O)^Y^`"8J0B5GQS'F6BVE`*S +M]``-WS1;```^X0$`WTQ;``"\G]"_V;.0`&8/\/V?!+B>`"``IJ[T&T*8KPG' +M^0'T"PN]E*#9/@P"`*#?F*D(O?0^(P(`IJGT&QN8J0FUZ0F8J0BUKPF/___] +M_9\$M:D(^`"RGCXZ`@"R_9CO"?_]E,?_`;B9`"``L_``S?@`V?`9``"\FJB8 +MJ3CQE/\/]!L)O=0^A@(`F+D!Q,__Y-[__PT!M:DZF+D"M:D[M:\\M:X]O[FU +MJ3FRVO@`^0*RT++ML+8(]`T%^`C?_`8``)+>`;SND+R>D+:4!+R?D`__-9\! +MLZ``%K/)!(X`L\D#@P"S!`!^/DD#`-DP&0``/YG$G_^FO_0(%=DN&0``/YGP +ME/^\GY"FN?0(7MDQ&0``WR\9```_F3__\)3_\/3_O+F2II_T"`7X"-\(:!$! +MMI0$O)^0N)\`"`"_G+__LP``#<3)#["6`_0,7L3)#["6`_0-$,3Y#["6`_0- +M$SZ"`P`*`3Y+`P"]I#Y+`P`*`KSND+R>D-[\!@``MI0$O)Z0-9H!V7@$``"4 +MKP2\^?`8^0'>``0``+S>T!"9`37Y`37;G#Z&`P"*__\`^P&\JI#?S`8``+R: +MD+:4!+R?D!B9`?"4_[.:_P`JE)\$V7@$``"\^?`8^0$SD``*$ID!-?D!WP`$ +M```)_[ROH#6IG/@`V1P:``#Y(CR:Z-D?&@``/)KXLJ"RLB;O]!@%^`C9R34` +M`#^9,Y``(MG(-0``/YDSE``7V#`$0`9"O0+^ID*H$H.FFK_0;]_@`F*DA +M]##\_D\!H/F8J2*@^9BI(Z#YF*DDH/F8J26@^?0P!/@`^``2N00PE@'T#0`9``!_ +MW_E2WO1@``"]E+_B\?3_W_0P_*#I8-^]!+T4U10:``#4/AH``-,8&@``LR`` +M<<0I`?0+6=[\&0``O!Z0OYRSP``KWSX:``"\#Y`_F<2?`?0;&MX(&@``O!Z0 +MOYVR"K#Q``L'O>1^-+D`LP0`(;]1^ +M-+D`D``!D!$$LP`#"[8E`3Z,!@#T,`3[4=DX%``!OYFSI``+QY]$/B<'`+.D +M`0W'GRR]I#XG!P#'GS"2J@()`;N:!/V?!/"L"_"F`?@`^1*8H`.)!_S?LJ%] +MM/\)E+W$M:D#?@`^`,<`PY@?`[8$`S.D`!Q)!_S_^93_"96R&K49`WY:N``* +M`3Z7!P#=X!D``'_>20?\O:3_^93QY0`0CP``(&#>_9\%_9`%M1D#^Q'9_&`` +M`/D"OYD^Q0<`E)H$V3!:``"\J:"8H`/'"17T"PM^-P<`LZ``&,<)P[.4?^'? +MX!D``'_Y\93_[V#Y^P'Y$K*_LL&RT,2I`_0+!?@(LJNR_`H%?I5X`+RA"?L1 +M^1+9+!D``#^?\*3_LKX)![++LM&\F@(S\``JL`8!]`T%^`B4&0*S!``-WS1; +M```^+P@`WTQ;``"\GY"_F;.0`&;'Z0+T"Q\)\/_IE+B9`"``F)\,WO____[] +M_@2UGPP^B@@`L`8!]`T%^`BS!``-V6@:```^=`@`V70:``"\D9@*\-S____^ +M_^JD_YS$#0Q^V`<`V?`9``"\D?@)`;N0!+7Y"/L1]##X^3*RH)BJ"_0P^+*S +M_D$!_D(!D!$2@&GX[P@"SI``&^`BS,`!(F`\+F`D,E?$8E9`;LAJR +M"W[^N`"SH``,?C<'`#XZ"0#9Y&$``+^9LY!_&Y0)$`K_E!T8LJO_G=6RK'X+ +MN``^.@D`^`CT,`C[-0B8KPCY`K*@Q_D1]`L3B0``$/_YE;6I"+VD/GP)`'[A +M>`"8#PC9\!D```X!LNK'_6B\G9BV]1R[[P2UG@C[`9BO!HG___V8K0K]^02U +MKP:SL`=VL[0"&-_)-0``/_D2F0$@^7Z>4P`^SPD`L[0%*=S(-0``V^`9```_ +MSW^^/=39RC4``!+_`?#E`B"=(,]@OKVD^`#'V5C$GP+T"Q[9+!D``#^9,Y`` +M,9BI!K:5&+.0`B=^0`D`^`#PE`3T"PK9RC4``""?W\@U```_^;VD$ID!(/GX +M`+VD^`"8KPR8K@>8K0B]E)BK"K6I";6I#MG____^_?D$B?__W[6O#/WI!(G_ +M__FUK@?]V02UK0C'N5CT"PL+`GY^"0#X`,>Y%_0+,YBI!K:5&+"6!_0-#YBI +M!K:5&+"6"_0-&]X`!```W>`9``"_Z7_?\)4"\/4"H.E@W_@`^3+9+!D``#^9 +M,Y``=+"F`?0-!?@(MK0"LZ0`#=DT6P``/KL*`-E,6P``O+D0OQ"S``!V`_"" +M___]_P.4N)\`(`"8_@BR^ICP"96/0+"WX8"@`^``L`M?D) +M_^*4LOJU^0A^_GD`QPD!]`O'O92@&3XV"P#>X!D``'_IW0`@``#?.QH``)C< +M`3S[^/&5``%@Z0D!NY\$_9P%M=D!^S'Y`K*PLZ0`*MDT6P``O)N8LY``"'Z1 +M"@#9:!H``)0.`KWTO.G@V31;```^B`L`V4Q;``"\FYBSD``(?I$*`-ET&@`` +ME`X"O?2\Z>#93%L``+R?";_IW_____[]GP2@Z?L!^8+9+!D``#^9]##\LK(S +ME``&^`CPI/^2J0:PE@'T#0GX"#[X#`#9/AH``#R2Z`L'#P&\NG*[]P3P]/\Y +M_P#]_@0\GRFS=``HV?P9``"\DOBS]``,LBN]I#[T#``)\+*X__F4N)8`(``^ +M'@P`V10:``"\DOBS^0#C``GP"`;_^92XE@`@`+)ZLBNR87Z'`0"]1+U4O328 +M&0:R&K:5&/0+%9@9!K"6`/0>#)@9",>9%/0+-G[#`0"R&G[A>`"S1``(LA6R +M%)@?#L49!+B9`"`"D#,!M5D."?"R%?WY!+CQ`"``/I,,`)@0#@GPLAK]"01^ +M&`H`N```(`"R`:86]!N9LT``6+A)`"`"Q9P$LW0`'=G\&0``O)PIV1P:```\ +MDRG9'QH``#[6#`#9%!H``+R<*=DB&@``/),IV24:```\DRG%R0BU60Z]E+*+ +ML)$`LBJ]U+WD?C2Y`+)ZLBM^.`L`]#`$^X$)_/VI!+.N0`0_E;D8LY`"-[.4 +M`RW9)!0``;^?N)DE%`+_N93T"PKP]00^,`T`"?O]^039)!0``:"?/D$-`+.4 +M`0;X"-D`$``!O*F@H*OX`/EBV +M_Z;>]`@6/RFY[P"\\+#PE/^\GI"FV?0((#])Q)[_IM[T"!T_.;GO`+SPL/"4 +M_[R>D*;9]!@*$`H!?H4T`)```9`1.#]I\)3_I@GT"*G[8;BJ``P"L*8#]`P? +MWN`9``#=``0``'_IO]_PE0+P]0%@Z:#??EZK`/@`V2`@``&_G]TD(``!O][T +M,/A)V2`@``%/?OS_C_2@G]GH&0``H,Z@G_#5 +M"MD@`!`!(+U/@0"@GWY2X0"TD`D0``&@-Z`6H%FTD`H@(*!)/DH3`,0I`?0; +M"3T4/OL0`,3O`<2)`?4+NP"S^0`A`=G`90``/YDSD`!VV1!B```_F3.0`![9 +M+AD``#^9W11B``"]Y-\(8!$!Q)O_/D$0`-T@6@``O]])__WE#@`$_^D$D/\! +MV1`!$`&@GZ#?/D80`+_9O_R0[@&0_X"0W13'F1GT&Q?$R0^SE`41#P'9H6`` +M`""?/D80`*;K]`C7V:%@```_GTG^_/V)!-D@(``!H)C9Z!D``*"8V20@``&@ +MD#/T`'U^30T`"?X]%/T)!#[G$`"S\``*/10^T!``2?_\_8D$V2`@``&@F-XX +M(``!\`4!H-"_Z=WL&0``/]_<,``0`?V;!*#IO\[P]0D@WPG[_>D$H,[9Z!D` +M`*"83X$`V2``$`$!`:"?V20```&_F=_\80``D)D!H/D^YQ``/13'*0P9```_G>4/ +M``C9)"```:"?2?S\W^@9``#_B92@^<6>@-D@(``!H)[$V0CT&PU/@0#9(``0 +M`:"?Q=\,V>P9```@GW[^5P`S$``="@%^!5$`V0`$``"_GT[_[_W^!*"?/H`1 +M`+VDO;2]Q'Z.2@!^4N$`,Q``#@H"?@51`#Y*$P!^LDL`/DH3`.2)``+U"ZH` +MV`9``"8Z0]_W_"5`O'U``2UZ0]@WTG__/V)!.2)``'T"WK$"0'T"Q*5 +M"0F5#PC]GP7PE`'T"R7=(%H``+_?V1`!$`'E#@`$D/\!H)_9)"```:">H-\^ +MP!(`WB0@``&_Z=_090``/_T/]_V?!/&5``&@Z3/0`0;X"-X`!```W>`9``"8 +MZ0]_W_"5`?'U``2UZ0]@WTG__OV)!.0I``CT"T;DB0`(]`LEV4!8``#>`%H` +M`+^?D)DXL/8"]`T'L_0,)Z:>]!OO/A`3`-]`6```W@!:``"_^9#_.+"6`O0, +M"*;^]!OSY"D`!/0+*.2)``3T"Q/?,``0`;_Y\)4@H/D^/!,`V3``$`&_GP[? +M_?X$H)_9Z!D``*"8V2`@``&@F/N%"/D"V>P9```_F;+-,Y``!O@(QZ]H#/_T +M"R6]Y$#_`,3Y`?0+#+P.E+F9`/W)!)#N"+/@(`NV]0$^:Q,`\*3_LZN``,\` +ML::``/0,$+.@!R*SK0C6`#[7$P"SJY``A`"SJI$`8+.O@0#"`#X]%`#9!"8` +M`;^?W@```$#]_@6@G_'T`$#U"Z,`/O$3`-D$)@`!OY_>````@/W^!:"?\?0` +M@'/Y`(8`V40`$`'>)"@``0\!H)^_Z?&4__^@Z3YR%`"RNK+;?N^G`-[L&0`` +M/^_$^0CT"Q3$^?<@Z3YR%`"RNK+;?OT,`$^!`-D@`!`!/E04`-D`(``!O+FP +MO[_9)``0`:"?3X``DID$H)\^@9``"_F?&4``3T"R+?```` +M`=D@7```M9\"CP"<`+*:M9\#?;3^3`%^`#X`]#`$^`#Y0K*BF*H(B0``#)@N +M!M___P'P_Z_T_?D%V2@:``"5\1R\DD$M2X& +MQ_MHQ"D/E+`"O,`PO-!`LY``!O@(WD`A``"S%`$/"0:UZ1H)`CZ#%0`)![7I +M&@D!M>D0"$``+,4`17? +M(AH``-KL80``//N8/B06`-\<&@``//N8VLQA``"\"@"UX#\0F0$\^;F_,]E` +M(0``#P&UDCRUDSJ_1+6?.+6=/KWTM90[M9P]M9\Y"BG[0=E`(0``F)D"F*\( +MLJW'GI#9__\?_/WY!)3I%?^?Q;6L",?)$_0;"VY!O?____![+:_9\$_>D%M=X' +M/LD6`+/T!!#'R13T"PE^&14`^``*`_@`V4`A``#T,/#Y@K*3]##XF)`4_D8! +MO138/AH``-0`!```U>`9``"'_W__D&8L/M0>`+,)$FP&L`82]`Q@LPD(`P.P +M!@CT#"RS"02;`;`&!/0,$;,)`:\`LPT#F08^XA<`LPD&>`*P!@;U#*<"/O,8 +M`+,)#A8'L`8.]`P1LPD,EP2S#0UP!CXB'`"S"1#[!;`&$/4,N`4^2QP`LPDC +MV`.P!B/T##&S"17B!K`&%?0,$;,)$S,&LPT4/`8^`AX`LPD7^0:P!A?U".(& +MLPT8)P8^GQX`LPDJBP.P!BKT#!&S"2AD`[,-*0X&/H<;`+,+CP`1!+,+(`/; +M`[,/C@#Y!3ZT&P"]E+(!M3D8M3D6/M(>`+W4"1+^G0ST,A+T,A+T,A*SU`$- +M#P'9*%H``*"?F#D8L)8!]`P6V=QA``"_G]GH80``OYFF^?0;0]SX8```/\X/ +M`=E`(0``M9\4,^``%=D$$!`!OY\]Y"#.\?4`"*"?"@&FVO4;GP:]]-DH6@`` +MH)_T,1*RVC[D'@"SU`$0O?39*%H``*"?]#$2V]QA``"_OM\,80``F#T8`0.\ +M[I"\GI"0G`&VE`*\GY"_GY#N`9#=`?#D#[4_`=\,80``O/S(M3T8``2U/`*8 +MF0*@OK4Y`S[4'@"8.0'PE!^SG00)!I@Y`O"4#[.0!B6PE@;T#!&2F0*PE@'U +M#.X%/N,8`+.=".8%`00`!3[4'@"R`0`//M0>`)@Y`9@Z%I6;&?0+#7[`4@"R +MH3XZ&0"8/R:S\``=Q?D$N)D`(`*R`;4Y+[4_+KV4M3DP/J49`-D$80``?YEP +ME@#U'Y<%Q)'_LQD`D`68.0+'GX<5^0'T&P4/`<3R_X\``!^4*1#]GP24'QC] +MGP6R&K4Y%WYYJP"SJ0!A!509!O&4P!_$+S_=#`0``/WY!;V4M3TM=3]9-3FP +MM3DNVO`A``!^9K0`LZ0`#+(!``8^U!X`L@$`!S[4'@"83P/D^0"```$'/M0>``$'`!8^U!X` +MF#HNF*X(Q^D-]1NU!+^OQ/D'LYT!K`28J0''FR.SN0&A!+.T`PO'Z1'U"Y4$ +MQ_F*]`L,`0A`(`,^U!X`F#\"Q/D/LY0"$-\````(_^^5/NT:`,?I&_4+:028 +MJ0K'F3CU&U\$L[0#?\?_D,?I$_0;6)BI!K:5&+"6!_0-3)BI!K:5&+"6"_0, +M0)BN!YBM")BL!MG___\'_>D$V?__`?#]V02)```*MO0;_=D%_?X%V?___P"R +ML/W)!+6O![6M"+6L!CZX'@"4^17?__\?_/_O]/V?!=\````$_9\%M:D(/M`> +M`'Y6%@"RH+.I`[X#F#DOQYD"]1NS`PD'`0@U.;`^*AL`F#DOQYD"]`L)L@$^ +MF1L`"0>R`34YL``J/M0>`-KP(0``L@%^"S<`LZD`F0,^F1L`F#H9F#X;"0$\ +MBOB[G@3]^00S\``:V?`9``"\FOB8.1RR`0`#M?D(/M0>`)@[&I@\+Y@],+V4 +MO>2PD0!^-+D`/LH>`-H@(@``L@%^*40`LZD`0@,!*0`C/M0>`)@Z+MM$(0`` +M02`#?N%#`+*@/M0>`)@Y+T&.`,>9`O0;(@D'08X`-3FP0(\`/M0>`-KP(0`` +ML@%^"S<`LZD`^@(`##[4'@"8/RZ]E-U@(@``M=D!H-G9````"K79`ICY#)C^ +M"[(!WP```/^VE1O][P2VE!#QY0"```W]G@6UV0,^U!X`F#DNVF`B``#<#`0` +M`)B;#;:U%GX`/@`SI``,`0T`#C[4'@`/#3Y-'@"8/@*8.0&8.A;'[625FQFS +MU`-:V3@`$`&_G\3]?S/0`!;$V?^FN?4;00+'^6BFFO4;.`+91!D``'^?MN40 +M?/[P8)\SU``;Q*D/MI0(CP``?_^_]?WY!=DX`!`!H)]^L:<```,!#S[4'@"_ +M/PD!NYT$_9\$]0L,`G[`4@"RH;.I``("?GFK`+.I`/D!M3$7L!8D]`PRO!&0 +MW=@&``"\D9"YF0&0F0&VE`2YF0&\G9!_GPG_9OGT"P^4^1:R`;4Y!C[\'0#$ +M&0&R`;4Y'P`1/M0>`)@Z%YA/,9A+,@G^_:D$O92PD0`)`K:D`S"1!+ROH-S` +M(0``#1#>**L```$1?CO"`+.I`(@!`!`^U!X`F$\#Y/D`@'.0`&7_]Y2R`;5) +M`P`2/M0>`)@_'[V4L)$`"0+>0"$``#"1!)3Y`[R>D+;T`YB;(=G`(0``O/GP +MO_K<4"$```U`WBBK``"R`7X[P@"SJ0`J`0`3/M0>`)A.`Y@_%^3I`(!SE``* +ML@$^U!X`_^>4M4D#`1.P]B3T#"B8/@:2_P'=V`8``+S_D+;E%KR?D+:4!+R= +MD'6>$%@^"@$3=9X1`!0^U!X`F#\"F#T#F#D7F#L&Q/[PM6T!MI08W0````'Q +ME0"8MO4(MO0(_>\%M6T"M6D#MK46H&ZR:MP,!```?@`^`#.D``P!%``5/M0> +M``\4V4`A``"UGQ0^XAX`F$X#Y.D`0/0+:G]?2?^_L@'_Z93Q]/?_M4D#8%\^ +MTAX`F#HN`!`-KP(0`` +M`1A^"S<`LZ``*C[2'@`!#S[2'@`!"#[4'@`!!C[4'@`!!#[2'@"R`3[2'@`! +M"``#IA#U&R[XV4`A``"UD12]I/0P"/N%$/DBO>3?!&`1`=(N&0``T?__`,[0 +M````"(H```(+[SXF'P"_^9#N`?V1!/V0!:#YO]F0_X#]F@7]FP2@V3\IDOT$ +MQ)S_INST"-R]Y-\`8!$!C0``!#YD'P"_^9#N`9#_@/V=!/0+%[WDWP!@$0'< +M+AD``(WO__T^@A\`INST"-R]I#Z.'P"_^9#N`?V=!*#YF/D"M?D"D/^`/\GP +ME/^FZ?0(Y@H%^R'9Y!```;^9MI4?LY0!=]DP&0``/Y_9+AD``#^;O=3P]/_> +M"&`1`<2Y_[R?P#[7'P"_Z9#_`9#N@/"4#Y*9`["6`_0,!I#=`:;\]`CGQ+G_ +MIMGT&R?9`%@``#^9,Y0`'=_$8```O_FSE``;V20```&_F9"9`:#Y^`"]]-G$ +M8```H)_X`+.Y`"P!L[0$%=X$8!$!E*D'O)Z0OYX^2B``E*X$L[0#$-\$:!$! +MO._@/D@@`-D$Z4J00^'R$`DKD!E*X$L)8!]`P1V01P$0&\Z>"@[3X1(0#?!&@1`;SO +MX*#MN.D`"`"@G3X1(0")P"("O*F@E*D'/@TA`+.T`Q*.@!81O*Z@E*D$/@TA +M`(X`%Q&2N0&\KO"PE@'T#0^)@!81O*F@E*D$H)R4^02@G/@`C@`7$8\`Z>Z\ +MKJ"4J02\KZ"_GI3/!4D?_O'TX`'_Z93P]1#_^<6SM`2E/LX@`/@`V3`9```_ +MF9"M`<2?_Z;?]`@DV2X9```_F<2>_[SOD*;9]!@2O*^2D)P!IL[T""@^DR$` +MV3$9``#?+QD``#^9/__PE/_P]/^\J9*0G`&FS_0(!?@(V01P$0&4S@2\Z="_ +MV=\$:!$!O._@CP`7$;S/P(\``/_]GP3PE8"@Z:#9E,T$O]E/'_Z2SH"VY`3Q +ME1`"_9\$\)6@H.F@V=DD```!OYZ4J0.4KP:[^0+90%@``+SY\)C]!)#N`3V4 +MM?X(D/X,->D#"=C_V92U^03QU``"]`L%^`CX`-DP&0``/YGT,/R0K0'$G_^F +MW_0()-DN&0``/YG$GO^\[Y"FV?08$KRODI";`::^]`@H/FPB`-DQ&0``WR\9 +M```_F3__\)3_\/3_O*F2D)L!IK_T"`7X")2Y!-X$ +MD-[__P#._?X$\/6QH)^@WXP``""0F02/`!<1H)R\O["XF0`(`*"!'`1`;S^\+_^ +MC0``"/_ME/0+*]G__P#.E*\$_^F4_9T%L[0#$-X$:!$!O/[PH/GX`-X$`9``"8Z11_W_&5`!#P]2"UZ11@W_@`V?__ +M_P#]J02_K__YY*;>]`L%^`BV]1C$^0'T&P7X",3Y_K/$``?PE0*VE!C]G@6@ +MJ?@`O_FFV?0;$[/$`!#?X&```#_Y\)3](/GX`-DP&0``/YFSL`!H\)3_DID! +MW418``"\FO"\_Y"4_@2\Z9*VE`*\G9`_F3.4`%>4^0:V]`.[GP+?0%@``+R? +MD)B9!/"4"/0;/-DD)``!O.G@O^_=#&`1`92I![R=D/#T_Y"=!*"?O^GQE`#_ +MH-GX`)2I!]\,8!$!O)^0H)N0F02@F_@`L*8/]`PFL*8%]`T%^`C9U&```'R: +M^-YL8```E*D"O)Z0Y/K__Z"Y^`"2JA"PI@7T#07X"-E<8```?)KXWH1@``"4 +MJ0*\GI#D^O__H+GX`/0P^/F"O23T,/S^1P&0=R@^?"8```&[`@3_"93U"R +MT&```+D)`/V?!*#IL"8/]`P\WS$9``#>+QD``#_Y/^^R+O#T__"4_Y*1`;P? +M4)0?`P0!E!D&NTX$O)\"$D8!WUA8``"\#P`^^R4`WC`9```_Z=XN&0``/^^2 +M+A`^H24`/PGPE/__293T"PZR&ODU/PG]E@0@"9`1`9``.*85]`CBL'$`LCJR +MBPPAW0```"'>OB,``'Z&1P"_>;.0``;X"+3P"][___\`O_G]G@0^!)#N`?V>!:#YD"(!LR`@$-_08```O_FSG0##_MG08``` +MOYGT,`2PE@#PK`OPI@'[A0CY0MDP&0``/YFRK)"M`<2?_Z;?]`@DV2X9```_ +MF<2>_[SOD*;9]!@2O*^2D)$!IA[T""@^]"8`V3$9``#?+QD``#^9/__PE/_P +M]/^\R9*0D0&F'_0(!?@(O20)$OZ2#/0R$O0R$O0R$K,D`0O9*%H``*"2V>!A +M``"_FI3$!I3#`WXI;@`)?L&```*#I\/3_DO`!E`D&E`\#LN:\GQ*] +M)-EH6```U2X9``"\&1#4)````0,!/@(H`+\?L_``&;])IOGT'0VR"GZ>)@`^ +M_"<`H&.R,I```9`1.#]9\)3_I@GT"-BR*OMA"@B]M-Q?C`$`?LM.``D#LZ`! +M#]G,8```#P&@G[V4LIKX``\!V>1@```*!*"?B\#4`=R=C`$`?LM.`+.D`2'> +M6&```-W@&0``O^E_WPH#\)40\?4`"*#I8-_X`+.D`!396&```+^?#N_]_@2@ +MG_@`^`B]I/@`V>`9``!_F?D2\90`"/0+!?@(V5A@``"_G]'`8```"0&@&<3P +M(/0;$7[J'@"SI`4*H!`^&BD`"@5+X"[<>(L!`'[+3@"SI`$CWEA@``#=X!D` +M`+_I?]\*`_"5(/'U``B@Z6#?/AHI`+.D`"K=6&```+_?V:1@``!.X"Z@G@G? +M_?D$H-_9/``0`4],':"?/AHI`/@(O:3[$?0P\-DP&0``^7(_GK*@LL?$ZO^F +M"O0(%]DN&0``/YD-,/"4_[R:D*8)]`@QV3$9```_F<2?_Z8/]`@5V2\9```_ +MF?"4_[R?D*8)]`@)^`@^-RX`#2"F"O0(']DN&0``/Y_$Z?_P]/^\^9"F"?08 +M"KP*(CZI*0#9,1D``-\O&0``/YD___"4__#T_[P)(J8O]`@%^`B2`0&SW3!A +M`HG__P'$OO__N32QYG\`]`T(L^[_`#.\$9"4'P2[^0+91%@``+;T`KSY\#_Y +M,Y0`*_#D_Y0I!]\,8!$!O)^0H)X^#RH`WA0D``&4"02\GI"_F<2>_\OCX+#F +M`/"<"_"6`<<^Z)26`;/@``?P902\$9"4'P2[^0+91%@``+;T`KSY\#_Y,Y0` +M%)3O")0I!]X08!$!O)Z0H)^S<``*O40^`"L`_DH!/;20JB`,$'ZL-P#9`"@` +M`=\P&0``OYD__Y"9`?#T_Y24!*8/]`@5V2X9```_F?"4_[R?D*8)]`@%^`C^ +M20''/^B0F2"V]`GP]4"RFZ"?O:0R+')-?DX"`)0?`Y09!K.D`"B\G_+93%@` +M`+SY\!CY`=[@&0``\)4"-?D!?^GPE2!@Z3X`*P"\G_+>3%@``+S^\!CY`;(J +M"P2]Q/"4_37Y`7X3(`#?%"0``90%!+Q?4+]9CP```?\YEOV?!/4+V0")00(0 +MO`D`E`D$OYF.O_WOO`X`QYD)]0NX`+-]`+0`_DH!/;20JB`,$'ZL-P"S1``1 +MV0`H``&_F9"9`924!-DP&0``/YG$G_^F#_0(%=DN&0``/YGPE/^\GY"F"?0( +M!?@(_DD!QS\0D)D@MO0)\/4@LIN@GW)-O:0R+'Y.`@"4&0:4'P.SI``HO)_R +MV4Q8``"\^?`8^0'>X!D``/"5`37Y`7_I\)4@8.D^\"L`O)_RWDQ8``"\_O`8 +M^0&R*@L$O<3PE/XU^0%^$R``/O`K`(G___[].02S8``>WP1@$0&4*0>\GY"_ +MG][__P#._?X$_V_UH)^@4SXW+@")00(0CK_][[P)`)0)!+^9O`X`WQ0D``&4 +M!`2\3T"_3I0?`\>59909!KN?`M],6```O)^0Q[80&)<#B0```?WI!/0+"S-@ +M`!D^-RX`,V``$3-0``W9^/\`\#YV+`#9^/\!\/^Y!)4#'/4+IP`S4`08V?__ +M_P_?````\/\)E/^?!3XC+0"S.0^+`+VD?KEM`-D$:!$!E"X$O.G@O^F/@!81 +MO"\@W___`,[]GP3QE0`(E"T$H.F_V4\?_HZ`Z>Z\+B#]GP3QE7`!H-G9)``` +M`;^?E!X#E!D&NYX"D/\!WD!8``"\GI"UGPO?____#_T/!`\.H)^\$?"UDPR4 +M&02[GP+?1%@``+:4`KR?D`\--9\!H$`S8`!L,UT`K0#'">CT"PW$FO]^2*L` +MQ*G_\)1_Y9H`$#-T`QN)D!81CG#I[KPI()0I!+PN(*":/G,M`(\0%Q&\+R"4 +M*02@FHGPZ.Z\*2"4'P.4&0;>0%@``+N?`KR>D)B?!/#U0+6?!#[6+0"4&0.4 +M'P:[^0+90%@``+SY\)CY!/"40/0++C-4`@^R*L1[_[W$?A,@`)09`]Y`6``` +ME!\&N_D"O/[PF/D$#K_]G@2U^03'"62PE@'T#0FR"S[N+0!)#___"93%FR`S +M8``3,W`##XG___[_N90^`RX`LKF4*@3?#&@1`;ROH*"IV?27[OZ\J:`S8``3 +M,W0##XG___[_N90^+2X`LKG>#'`1`;RNH*"I^W40V6`"$`'T,/SY@K^8LJ*R +MMK+%O:1^N6T`V3`9```_F[@A(`0"E1`$$`T!)MOT""O9+AD``#^9Q+S_Q-[_ +MQ)__O/R0INGT'Q.\[**FK_0>!?@(LJ0^N2X`V3$9```_G]DO&0``/YG$WO_P +M]/^\[Z+PE/^FJ?0>!?@(LJ0FV_0('=DN&0``/YG$O__$WO\#,/"4_[R?D*;I +M]!XKV3$9```_GR;?]0A@!=DO&0``/YGP]/_$WO\#(/"4_[R?D*;I]1]%!=D` +M(``!O"EPOW[_5K3$&0^SF03`!+.9#,@$LYT`)P4S-#`-V?+#_XX^+"\`V?+# +M=P[_N139``#^`/\9])7Y$?0;"[+B/50^32\`N?D`!0'_GB3_'I;'F5GU"[<` +MQQE9WO____&VE!G_+O3^2@'_^27]'@20JB0S-#!`W@1@$0&430>\WM"_V=__ +M_P#.W@````;_+N2@J;^I!0']GP2@J;^IW_____G]GP3]Z06@KK^IH-D^"C`` +ME$X$WP1H$0&\[]"_V=S__P#.V_____G?````!J"IOZG_+_35!'`1`;SEX/V< +M!*"IOZD%`?V;!/_YE:"IOZF@V;_IH*F_J?V0%@``)0)!KN?`KR> +MD!B?&+61!0X!\/4!-9\8V=!@``"_F3,T,`B.```!_^GUV=!@``"@G[/=`-8# +ME`D#E`\&N_D"V4!8``"\^?"8^02@_?&4`!#T"PNR2@L!?F`D`-Y$6```O`#P +ME`D$NY\"MI0"O)Z0&)X!E`\#E`D&NY\"WT!8``"\GY"]]+6?!!+N"S#F`?0, +M#]_N8```/_D2F0$@^=GN8```/YDPE@#T'P7X"+P`\)0)!-Y$6```NY\"#P&V +ME`*\GI`UGP$^-C0`\`3_L_0`/Y0)`Y0/!KOY`ME`6```O/GPO_FSD``&^`B4 +M"02\`/#>1%@``+N?`K:4`KR>D!B9`3.9`0<#^`@^-C0`O`"0E`\$N_D"V418 +M``"V]`*\^?`8^0$SF0KE`I1)!-X(`#,T,"V420??"&`1`;R?D+^9\)0/LYD$ +MB`+9T&```+^?C@```OW^!:"?/A$R`#,](&\"L^T!:@*4"0.4#P:[^0+90%@` +M`+SY\+_YLYT(4@+?T&```+_Y\)4$H/G>0%@``)0/`Y0)!KN?`KR>D+61!0X" +M&)D8,S`P!@X$E`\#_>D%E`D&NY\"WT!8``"\GY`UGA@)[_TI!#XZ-`#'&03T +M"WPS-"`DQ"D!]`MRL^0!;\-`"420?>"&`1 +M`;R>D+^?QRD$]!M%Q/D/LY`$/]G08```OY^.```(_?X%H)\^7C0`E`\#_=D% +ME`D&NY\"WT!8``"\GY#$+@$UG1@UG@X%`0G]_RF4Q9(1QQD0]0N5`)0)`Y0/ +M!KOY`ME`6```O/GPF/D$\90`$/0+"[)*"P%^8"0`E`\#WD!8``"4"0:[GP*\ +MGI"8GP2UD05.U^_]_@2UGP39T&````\(OYDS-#`(CP``$/WY!=G08```H)^4 +M#P.4"08.$+N?`M]`6```O)^0&)D8,S`P!@X(E`\#_>D%E`D&NY\"WT!8``"\ +MGY`UGA@S/3#/`)1)!]X(8!$!O)Z0OYJP%@#U'[H`QRD$]1NS`,2I#[.9!*P` +ME`\#E`D&NY\"WT!8``"\GY`8GQBUD07>T&```/#U!#6?&+_OV?W___[_*93% +MDA&)```$_?D%H.\^.C0`Q-K_O<1^'"D`/CPT`#,T(&3$V?_5%"0``;:4!+R5 +MD+^9CP```?V?!/0;2>2Y_S]/`,#_[_3_^;7'N6JPE@'T#0FROSX<-`!)_\/_ +MN93EGP`(E$D$W@1I$0&\GI"@G[*RN)D`"`"@GSXZ-``S4``&H'+$B0'T"T/? +M8`(0`;_Y\)4!H/D^@C0`V>W__W_]&00^4#(`E`\#E`D&NY\"WT!8``"\GY"U +MD04-`AB9&#,],#'^#0@^J#(`^X4$V20@``&_G[B9)"`"^2(RHMHP6```Q"'_ +MM:D"E!D8H*F)`(@`M:D#\/0!DA`!L_T`(P%]M-Q0!```?@`^`#.M`!,!E`D# +ME`\&N_D"V4!8``"\^?`8^0PSE`$0WZ!@```_^1*9`2#YV:!@```_F3"6`/0? +M!?@(E`\#E`D&NY\"WT!8``"\GY`]]#6?#-DP&0``/YTF+?0(*=DN&0``/YG$ +MWO_$G_^\_I"F&?0?%+P>DJ:?]!X%^`@\+>(^:#4`V3$9```_GMDO&0``/Y_$ +MZ?^\&9+P]/^FG_0>!?@(/"[B)BWT""?9+AD``#^9Q-__\)3_O)^0IAGT'Q+$ +MZ?_?!&`1`;:4!SZ[-0"4"0.4#P:[^0+93%@``+SY\!CY`\3O_S.4`Q"4^03? +M!&@1`3Z[-0"4^03?!'`1`;R?D+^?D)D$OYF)0@(0O`D`E`D$OYD^_C4`E`D& +ME`\#O)_BWT!8``"\[^`8Z0PSE``5"0'?H&```#7I##_Y$)D!(/G9)"```;^? +M#O?]_@3P]1"@G_LA\*,`Q*T_QZK&L-8?]`T%^`BPIB3T#0>]I/@`DJ\!O/^0 +MO)^0W]@&``"2W0&VE`2\GY`\G?@._SR>V=E`.```\/('"@&V]`:\^?"]E*#Y +M^`"PIB3T#"F2J0&\F?"\^?"4^03?V`8``+R?D)B?"K/P``^@OYB9"PH!H,GX +M`+VD^`#Y,N2I__^RL\>1QK`6)/0,:,22/[`F(/0-!?@(?OE[`+.@``H+0'Z_ +M-P#?0#@``#T$O_F0_T"SE``YV4`X``"R.\0*_PQ`MJ0&O*F@?E0W`)(?`0H! +MO/^0O)^0W]<&``"VE`2\*9"\GY`@D#X)-P`0``$S!$:_O:3[,?D"/ZGT,/BR +MH#.0`#DSD`<."@$SE`@O/D\W`)@)`9BJ`Y@+!)@,`K"1``D!#4`PD03>3;0` +M`'X[P@"SH``("0@@";VD]#`(^P'Y`L2I`[+`ML4"LY0`*\2Y`_0;)+WT/G@W +M`+_ND/\!D)D$H-Z\J="\N>"F_/0([K+)/HLW`+V4E)\"O+^PO*^0/J4W`#^^ +MD/\!D+L!()Z0F0&F\/0(\?L!O90^N#<`/*N9D)D!IIST"/CX`+*OE;X"Q*D# +M]`L)O90^YS<`O92]U#[@-P"@_9"9`9#_!*:>]`CVLNF4GP(]Y+ROD#[[-P`@ +MGI#_`9"9`:;[]`CV^``/`=GP8```()])``&]]*"?D)D$LYY``?OX`/D2LJ"R +ML;&F_Q_T#1O$J0/T&Q65N0;T"P_$J3^\N9*PEC_T#`NR"K(;/ILX`-GP8``` +M/YDSE``(?@(X`+(/O>0^93@`H/Z0_P3$^3_T&_B\`9"R^KN?`HX``02RFSZ& +M.`#Z_@:0_T"2NT"PMC_T#/2VE0:VE`:\J:#X`[.P``A^OS<`^Q&_KK*ME>D0 +M]`L@"@&FF_0+)_^^]8D``/_P\P#_Z92]I/WY!:#?^`"4N1#D[____9\%H*D* +M`?@`OZR5R1#T&P7X".3-___U"YD`E9X!O?0^*CD`D/\!_^V4]`LFN>\`B0`` +M___?]/_)E/WY!:"OL^`0.[/J``%*L^0(6#XV.0"VY0&P]A#T#07X"+/D`,F. +M`(``/O,X`-\`!```F/D#\94`!+7Y`SYQ.0#?``0``)CY"_&5``2U^0L^<3D` +MWP`$``"8^07QE0`$M?D%/G$Y`/@(W^`9``!_^;+M_9X%8/F_J93?$/&4___] +M^06@K_@`^``````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````#>``0``)CO$/0PW/F"]##X +M<_``-]DP*``!OYG40`0``-"@7```/62PD1'9-"@``;^9L)$2V3@H``&_GI"9 +M!+^9L)$3/GDZ`-E`)@`!OYF8[Q'41`0``-"P70``L)$1V40F``&_F08!L)$2 +MV4@F``&_GI"9!+^9L)$3Y/D`0/'T__^SE``O"?#_Z920##"PD0NPP0^0"1`] +M=+"1#+VDN`4``0#3``0``-C@&0``/FT]`/@(/H4Z`!@)(3.4`!K9Z!D``+^9 +M\)0!]`L,,V0`"0D$-0DAOTVTP`^)``#__]F4E=X0H$G'[\'DTO__E/D$\.0! +MD)D,MN0*O,G`D/\#L,$0MO0$L.$-O`_PL/$./F(]`,0I$/4+H@$8`2$)[_TI +M!#`6!O0,%S`6!?48J``S$`)@,QT#)0(^4CL`,QT('`*R"G[:L`"SK0#``0D' +M-0DA/E4]`%@)@[2@$;2P$K3`#+:4$`$"L)$`,!$$#1#>B+$``'X[P@"SI``1 +M?XD*`?"5`6")/E<]`#4!(3Y5/0"8#P58"0R8#@3<````@/W\!74)!;4/`3V4 +M??2@#C4)('4/!#-D`!'1`#]9,Y``7K3`$)@/`;\!6`V#O\G$_/^V +M]1^TH`[]G@2TX!#]GP6T\`WQU/\#H.FR&__]U7Z/L`"SH``4W^`9``!_^0H! +M\)4!/HD]`%@)!3]>D!\0H`]2F0$2[@%U"04@7@D$-0DA,V0`)[\^F#T+F#\4 +M?XQ)_]_]Z03]^03]V03PQ0*@/K4_%+4]"V","@$0=P$P=@7T#07X"+,M`*[] +MOTGDG___L_T`2?W9``0``%B9(G.4`!'?X!D``'_Y\93^_V#Y]#`(^X4D```` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````"?#T,-#Y@G*T]##XLJ;^3P&RQY#_/__Y%.2Y +M_P.0$A!SGOX#,-DX)@`!OYB0F0B_E9"9!+^9T+!=``"PD0O93"8``;^9V4@F +M``&_DSYW/@#9*"@``;^8D)D(OY60F02_F="@7```L)$+V3PH``&_F=DX*``! +MOY,,$+(JL@M^5#<`LAJR:PP0?E0W`+(*?BRQ`+.D`&&8+`&8&0-8+04._I7/ +M'_V>!/WY!;4?`\=&"I@;!%@D!'#6`?0-><0Y!V:4]!L5"?#_.?2FO_0,"Y"Y +M$*:?]`M?6`F#Q&T!\,3_MM0*\93_`[(:_=D%?H^P`+.@``HRK3X;0`!8*068 +M'P2R"K(K4ID!D/\0=2D%M1\$#!!^5#<`OWG?X!D``'_^/=3QE0!`H'G'F?#] +MG@5@^3X;0`!SW0&J`%@)@9`/,+(;#!#$D0PRD\0:_[:D!+SZH'Y4-P#D2?__ +MY(___Y"9`::?]!X+LEH"!CYR/P"VE`0"!;Q9H%@/@[2P"\1N`<09#+;D"+;T +M$+:4"?V?!?V>!;"1``D"#1`PD020#!#>B+$``'X[P@`-`[.@`':X#P`!`#_Y +M$!H!$)D!(/DSI`P&/:2_?\0Y\SW4_ZF5\?4`0*!_\)3_-0(A=0F!/AM``+(* +M?MJP``D(LZ0`!@D'-0DAW0`$``#;X!D``+_9F-X+F-P4?[_QE0`@\>4`(*#9 +M\/4RM=X+\<4`(&"_M=P4#0$RVO0P"/N%,+/$`%C9____`-\`Q@``_ZF4II_T +M&U*5J1@/`;.0$18/`K.0(1`/`[.000JSE%`/#P39`6(``""?^`#?`6(``+.4 +M8!$)!2#YV8@=``"@F_@`"08@^?@(^`"SQ`$-#P;9`F(``""?^`"]U`D2_IT, +M]#(2]#(2]#(2L]0!"]DH6@``H)W9@!H``+^?V7P:``"_F:;Y]!MDV=QA``"_ +MG]GH80``OYFF^?0;4=X,$!`!O^G?____?_V?!*#I#__9$!`0`:"?WHB(B(B2 +MF0R@GKWTV2@9``"@G]D($!`!H)[^B0'PE0+^F`"SU`$.V2A:``"@G_0Q$O0H +M`?@`?93?X!D```H!8/F]M+W$?HY*`+.@``;X"`\"V7D:```@GWX6W`!^O-P` +M?I/;`-T0%``!O]O>%!0``;VDO^R@VDD`$*#I#S#96!8``:"?H-N@[+B9'`(" +MOY_9^&$```T!()W]_039P&4``""?WA!B``#9ZF```#/P``P@FB#J/J%!`"#M +M()I^Z=X`O928F0GYE/@`F*\-Q_DTLY`!#+.4`U\^X$$`"?YFN?0;4XD```'_ +M^96/___/_9\$CP``(/V?!3X40@"8K@J)___^__F4CP``!/V?!>7O__^UKPJ/ +M___/_9\$CP``(/'D___]GP6/``#__9\$_9X%M:D-"@/X`)BO"IBM#9BL"(X` +M`/___I3QE?[_M:D*B?__S_W>!/'T___]_07]^02)```0_?D%V?____>UKPW] +MR02UK`CX`)BI`;*MF*\-QYD']`L-Q_D0]!M7/K1"`,?Y$_0+1\?Y$O0;,>2\ +M__]FO_0;*)BI"H[___W__N2/``#__9\$_\F5M:D*B0``,/WI!;6N#0H"^`#' +M^1#T&Q.RVGX;0@`^J$(`^`@*`?@`"@'X`)BO#8D```C]^06UKPW'^32SD`$6 +ML)8!]`@3LY`"&+.4`R@^_D(`LIKX`'X;0@`*`O@`?EI"`/@`B0```O_YE;6I +M#0H!^`#X"`H!^`#Y`IB@",<)&_4+NP"8J0V8O@+'G#2SQ`$5F*D)C_[_`/&4 +M__^FG_4;G0"8N0%R[<>;D/0+&+/$`AD)_6;I]0R&`'/I`((`/FY#`+/``GG' +M"1/T"PNSP`,(L\0!:^3<___'"1/T&S>8J0J8K@V8K0B/``#__9\$_\F5M:D* +MB0``,/WI!;6N#9$W*^]`L:F*D)\.,`CP``_PH#_9\$ +M_>D%M=X)^`!^KD$`^`!^$D,`^`#9+!D``#^>F*D"#_"RK)BK!/V?!+B=`"`` +M,^0`!O@(F-D.#_<*`?V?!+6Y#IC.!9C9#KWTM=\/\)0(_9X%M=D.^``)`36I +M,/@`"0$UJ3SX``D!-:D0^`"]I/@`^0*RO[+`Q*D#]`L%^`BRJ[+\"@A^E7@` +MWP````'9____^/\)E/V?!;6I"O@#^P&VI1BSP``^LZ01-ME$8```OYFFV?0; +M*=W@&0``V_9>``!_V3^_W!@9``"_SO"50/#T_F#9D.X!(+^@SO@`^`CX`+.D +M$2_91&```+^9IMGT&R#>X!D``-WV7@``?^D_W_"50/#T_F#I\/4"(-_X`/@( +M^`#9'!H0`;^9^5+$D0?U"Z4`V9`=``#5`,4``+^2U!`:$`'9E!T``-,4&A`! +MOYL^N44`O\ZFY?08!?@(6,\"DND!E>H(O03P\P"\GY"VE0B0F0&FFO0-!KR: +M`EC-!%C.`^2O_P^4"1BV]`C]GP6@2?'D_P.VE0BVU!BVY`AUR0K][06@/I"[ +M`;"V$/0-!;VTDA$!]`L9O+N0O)N0E)P#V=P;``"\R<"FLO0;BMF4'0``H)O9 +ME!T``+^?V9`=``"_F:;Y]!L0W^`9``!_^?&4^_]@^;VD^U&]])CY$/0P\/F" +ML+$+<,$5L.$) +M`G20%;3@#G7;!'79`[7>!)#)`:#YL)80]`T'O92@^=D<&A`!OYGPE`?T"PU^ +M)44`O:0^@T<`WYP=``"_^;VDD)D!H/G[A1#Y4K*A]##XLK"RPK+4LN.T4`FS +MM``&^`BS)!$6LAJR"W[HPP"@6K.@`R"SH`<8'0``U(P=``#6@!T``#Y92@"_<;,4 +M``;X"+]+V80=``"_D+]BO+N0O)N0E)H#V=P;``"\J:!8K`2]A'/`(`USP$`) +M<\T0P@!SQ$`-O>1//P$^3T@`OZZ8C1!8J0*2[P&[[0+PDP"VY0B\^?"[_0*V +M]0B0^0&[G@)SQ!`AO`D`IB#T&`6R`ABI"O"4`?0;!;+O#`$)`3Z22`"["0)S +MQ"`5&*D*\)0!]!L+LN\]Q#Z22``]Q+V4Q)H!V9P:``"\Z=`_V9#N`?"4_O^I +ME2#9,\0`"?"4OR#9D-T!IN_T#>60NP&PMA#T#06]M+R[D+R;D)(1`92:`]G< +M&P``O*F@6*P$,UD`.__9A!T``*!BH)"@<:!+V2P:$`&_F5BO"N>9:`%UJ0MF +M^?0+!?@(WP```$#9&!H0`:"?<\`A#G/)0=X`<\T1"0'9`````?\YE/0+0W/$ +M(2"_K]D`Z0``IOGT"S/?'!D``+_YD)D!H/D^)4H`<\01(-X<&0``W0!B``"_ +MZ3_?D)D!$/\!H.D@WSXG2@"_KKV46*\"F)T0DND!T(0=``#P\P"[G0*\GY"[ +M[0*5D0BVY0@)`;N>`KR1L'/$$1R_";]O#0&\N9"@"::?]`T4H&D-`3Z]20"_ +M"3W4NYL"H`D8J0KPE`'T&P6RX=F<&@``Q-P!O.GP/_F0[@'PE/[_R94@^3/4 +M``GPE+\@^9#_`:;A]`WE/B=*`-F$'0``OY_>G!H``#_I\)2^(.F0[@'9W!L` +M`*;I]!OON/]``0+9A!T``*"?/B=*`/@(OWF_3Y*9`9#_`:!YH$^P]A#T#0>] +ME*!)F*D$OZV8J@/'/!CG.R@!!0'YE=D8&A`!OY.P-@#U'I/]V9@=``"_F;.0 +M`"/9D!T``+^?V90=``"_F:;Y]`L/W^`9``!_^?"5!&#YO:3[@?0P_/E"]##X +MLZ0`5MG@8```/YG$G__'^0'T&PK$^0'U"_(`V9Q@``"_G]GL8```?YO9____ +M`++Z_?D$_DD!D)D<\+,`W0```"&PD0#__=4,(=Z^(P``?H9'`#Z?2P#?`,8` +M`-EAZ```O)^R#P'9(T```##Q!+"1`-D!8@``WP#&```]Y++Z()[9____`/WY +M!-X````1?<3__N4-$7[Z10#^20&0F1R@FD&8.K.@``GX"$&8.M(!8@``!/_3 +M&!H0`3\I,Y`!.`!D/G!+`+\YL)8`]!\1?M%'`#\I,Y`!$#.0!@R2``&F!/0; +MY3\I,Y`!#I(1`?0;S3Z,2P"S%``&^`@]]-D!8@``O:0@G_0P"/M%!-\`Q@`` +MV]E*#9O93>F!T``)B?$+_I/<2\#_*2F0&@Z97Y"+SQ\+*=E?H(WYP: +M``"\GY`^:4P`()R0W0&0F0&FVO0-]CZ"3``-_]P8&A`!DNX!INWU&WS_O:3T +M,`C[$96I&+/)`*,`LYT1D`#9C%P``+^9IMGT&R#=X!D``'_9VY!<``#<"!D` +M`#^_O\[QE0`!/A--`-D`M@$`IMGT&Q'?,%P``#_Y\)3^/HI-`-D`X0``IMGT +M&Q'?$!D``+_YD)D!H/GX`-D`O`$`IMGU&[X`W>`9``#;8&8``'_9W!09```_ +MO[_.\94`! \/3^(+^0[@&@SO@`V0@!$`&@FI"9"*"=^`"SG1&%`-F,7``` +MOYFFV?0;(=[@&0``W9!<``!_Z3_?\94``?#T_F#I\/4"(-_X`-D`M@$`IMGT +M&Q'?,%P``#_Y\)3^/H=-`-D`X0``IMGT&Q'?>1H``#_Y\)4"(/GX`-D`O`$` +MIMGT&Q_>X!D``-U@9@``?^D_W_&5``3P]/Y@Z?#U`B#?^`"]I/@`O:3X`+VD +M^`#X`-GP$``!OY_Y`K*:O<39:&8``/#T_YB;`K^=F)X!``$^N4X`L]`"4+#6 +M`O0,#+/=`<0`/@=.`+/0`UBSW06W`#XC3@"SY``&^`BS\`$,#`$-`CZY3@#X +M"`T"LOP^N4X`L_`!#++<#0$^N4X`LMRR^SZY3@"@H+^IQ)__L_0!#++<#0,^ +MN4X`LMP+`3ZY3@"]]-GH$``!H)_=Y!```9"9!*">O]_9````()7L&)+.`OWY +M!:#?L.8#]`T9L\`(%K/`!Q*SP`D.L\`-"@X%L\0,%MEH9@``F)D##@2SE``( +M^`@.!-]H9@``O92@_K7Y`C[)3@#X"++00 +M``&_F;*N"@*5GQ^S]`$VV6AF``"_F;.0`0RSD`4(LOKX`-]H9@``MN08V?__ +M_P#_N93]G@6U_`.U^0%^Q$T`O:3X`+.D$2/9`(D!`*;9]!L8W[1F```_^?"4 +M_B#YL\0`"?"5`B#Y^`#9Y&```+^9^0*SD``,?C(H`#Y=4`#9P&```+^9LY`` +M#'Z%*``^75``V5A@``"_G^3Y``+T"V/9,!D``#^?V2X9```_G<3[_Y2_`\39 +M_[R;P)2Y!KR?\MD86```O/GP/J]/`+_YD/\XY)X``?"4@#.0``BSX``,D+L! +MIKST".?$V?^FN?0-!?@(DKL!``G9`?0+!?@(V8E,``"PD0#9____ +M`-\`X0``VV'H``"R^KN_`OWY!#V4W@```!$PD03__N5]Q`T101`G?OI%`+.@ +M``GX"$$0)_Y#`=)Y&@``!?_4&!H0`9`S(#\IQYD!]!L\0!`G/K%1`+])H#F_ +M.;"6`/0?#W[11P`_*<>9`?0;"Y(``:8%]!OC/RG'F0'T&PV2$0'T&\8^,5(` +MLQ0`:#XQ4@"SI`)>V7D:```_F<>9`;.0`0;X"-F)3```L)$`V?___P#?`.$` +M`-MAZ```LOJ[OP+]^00]E-X````A,)$$__[E?<0-(7[Z10"SH``&^`C?>1H` +M`#_Y\)3](/D^,U(`^`CT,`C[502SH#@-LZT\@0`^FE(`V3@@``&_F0_'_[_T +M\)0(]!LHW@`C``"8[2RV]0;$N0&V]`;PU0&UZ3.U[RVU[2RU[S&U[R_X`,3] +M!C/0`#[9X!D``'^?W@`C```U[1CP]0)@G_@`V3@@``&_F?"4"/0;&MD`(P`` +MF)\LM9LNM9LRM9LP\/4"M9\L^`#9520``#^9LJS>6"0```H!Q)W_/O-2`'_I +MD.X"Y)___\?Y9Z;)]!L+Q/E_IKGT"PV0J@&FK?0-XKVD^`"PIB3T#!V2KP&\ +M_Y"\GY#?V`8``+:4!+R?D+6<"[6;"O@`LZ0$&]_880``O_F\N9"@^;&61@#T +M#1SX"/@`WP!A``"_^;RYD*#YL99&`/0-!?@(^`"8J02RKK^M"@3$G__T"T") +M__\/Q]IT_]F4]!L+L_0!(3Z:4P"S]`$9&.D(,Y0`$K.@`QVSH`$9LZ0"$_@` +MDJD!L)8!]`T)"@'X``H#^`#9`",``)B9:\>9JK.0#SJPE@_T#!"2F0JPE@+T +M#%H^%U0`LY`05[.4$4^_KIBO"@GX_>D$V?____B@KOWY!+6O"CX75`#9+!D` +M`#^9,Y0`+;^OQ/D'LY`"#@GX__F4\)4#H*F8J0K?____^/V?!+6I"CX75`#X +M"/@`V3`SY:5`"]]-D`!```F)D:W@"$UQ>\Z9*\^9"\ +MF?"\^?"V]0&F_O0-!;+OB4!"#__YO+.T``VP]@#PO`OPM@'?"&$``+_YIKGT +M"RJ@^PH&O<1^RTX`LZ0!'=Y88```W>`9``"_Z7_?\)5`\?4`"*#I8-_X`-\` +M+@``^5+$I3^260&VE`:\GP#?P"4```P4O)\0L@NRH[(:?E0W`+\?F!X!"?B8 +M"@K]^02]E/#U`;49!:`?Q^Q#Q,L!]!L,W0````$^&U4`W0````.8'P&]E+49 +M#[49";49#L?YZ)"9`;:4&\?_(;49![;T$HD``"#_V97]GP7>`",``+49!ICI +MI)COHL2=_Y39".2>``\S\``(\>4`$+.P`"?9````(/_I];/4`"^PQ@3T#2C9 +M____#__YE-\````P/IU5`++OL]0`$K#&!/0-"]D````0_?D%M1\(L[``&-D` +M(P``F)FB,Y``#.2O__\^O54`O?2)```(__F5M1D*V0`C``"8F:+PE/_T&PF] +MQ#[O50"VE`'?5"0``+R?D%B9`?"4?Y2<"-D`(P``WS`9``"8GJ$_])B=H\?N +M\,1"_Z;B]`@0^&%<` +MF#FAQY[PIN+T"!_9+AD``#^?Q$G_\/3_O/F0INGT&`J[X@(^]58`V3$9``#? +M+QD``#^9/__PE/_P]/^[Z0*F[_0(!?@(V91<```\GIB/```#Y-X`__WL!;:4 +M$/V?!/WI!8___S^)``#`_^_T_]F4_?D%M1\-^U'9`",``)B?!]YH(P``^1+T +M,/B4^0*\GI"V]`*_D=E$(P``O/GPO_"R&[(*?NC#`+.D!PKX"#YK5P"SH`,Y +MWM"K``#9````$;#A`-[___\`_P[D_>D%/92R&S"1!+(*?<0-$7[Z10"SH`(, +MV0`C``"UD`3T,`C[$?D2LJ#T,/BRL;.D``;X"+,4``;X"+(*LAM^Z,,`LZ0' +M"O@(/OE7`+.D`RW9T*L``+"1`-D````AWO___P#_#N3]Z04]E+(*LALPD01] +MQ`TA?OI%`/0P"/L1V="K``#T,/BPD0#9____`-\`Z0``VY51`0"R^KN_`OWY +M!`D!W@```"$PD03__N5]Q`TA?OI%`+.@``;X"/0P"/@`^1*\NA+T,/BRH+(; +M?NC#`+.D!PKX"#Y>6`"SH`,*O:0^FU@`V="K``"PD0#9````(=[___\`_P[D +M_>D%/92R&S"1!+(*?<0-(7[Z10"SH`(.V0`C```*`;60!/0P"/L1^1*\NA+T +M,/BRH+(;?NC#`+*ILZ0'"O@(/L)8``H!LY`#.]G0JP``L)$`V0```!'>____ +M`/\.Y/WI!3V4LALPD02R"GW$#1%^^D4`LZ`"#MD`(P``O:2UD`3T,`C[$?E" +M"?^RL[*@LL(+_R;9]`L+"0&[G022FP$_"<31_P0!/IE9`+N4`I2=`MDL3``` +MO-G0/]GPE`^FD?0+7UC?`;Q)E/\YS>3Z__\^DED`&`D!E*X%E*\"O.^BQYD$ +M]`L,V7Q2```^;ED`O.^BV?0-``"\J:!8J0'PDP#_N92FG/0;$+,@`"*8J0*V +ME03T&Q@8J03$FO^SI`"Y&-D!\)3_]!N&O:3[03^[,[0`"+VD^``_K0\!Q+G_ +MNY\"LOP]Y)2?`MDL3```O/GP/_GPE`\FG?0(,B:=]!L--:X!-:L""@'X`!CY +M`3*^,Y``'3*;\)3_NYP"E)\"V2Q,``"\^?`^QED`,KDUK@$UJ0*]I/@`/93T +M,/SY0K*S_D`!LJN0`!6RQ++A(`TU"0$U"0*T(`>R"GZC60"SI``*^`@^J%H` +M&`D"WRA,```]Y/"4_[:4`KR?D!B:`CZ>6@#$J?^S1`,6E)\%MI0"N_D"V7Q2 +M```^?%H`E)\%MI0"N_D"V?0-``"\^?!8^0'PDP"FD_0;#2`:("X*`3ZH6@"F +MD_0,##*N&/H$,Z0`MR`:("Z]I/M%!)BI"9B_"0SPLJZVE1B5_1@^VUH`F*D. +MLJ[_G/3PE`*X_P`@`+.4`!&8^0FR^K:5&*:=]`SBF+D.LY0`"ICI#K6Y#L6Y +M!+B9`"`"M>D.^`"8J068OP4,\+*N\)3_Q/W_/BI;`)BI!K*N_YST\)0"N/\` +M(`"SE``1F/D%LOKPE/^FG?0,XIBY!K.4``J8Z0:UN0;%N02XF0`@`K7I!O@` +MOZFSD`!)#_#]GP2XG@`@`*:^]!L:F+L.E;D$]`L'H*OX`*"I^`"R_CYW6P"R +M_9CI#O^=]+:5!+C_`"``LY``#Z:_]!ODF+L.M>L.^`"_J0_P_9\$N)X`(`"F +MOO0;&IB[!I6Y!/0+!Z"K^`"@J?@`LOX^P%L`LOV8Z0;_G?2VE02X_P`@`+.0 +M``^FO_0;Y)B[!K7K!O@`F*D%]##L^1+%KP3'F8R4G@6VE`*\Z0+9?%(``+P) +M`)@)`K*AN/\`(`*FG_4;C@"8O`C9"`X``!B[)_Y/`9`_0+6`GW_^F4M0D"F-D&\)4(M=D& +M/LA<`+4,`C[(7`"]E+4)`C[(7`"VE03T"Q"0"@BR&WZ66P`^R%P`VI@6``"R +M&WZ66P#9F!8``+^?L_0`"]F5%@``()^8&08/]_V?!+49!OL5%)BI"/0P[/DB +MLJ''F1'T&PF]!#[570#?9!H``#_YQ:X$N.X`(`(2F0$@^9BB"<#L?M`?0;+`GP_^F4N)D`(`"8GPF8&0FV]1BV +ME1BF^?0;"K4.`CZ,70"U#0(^C%T`O92U"0(^C%T`D`H(LAM^25L`F!\(F!X* +MF!T)B?___?WY!-G____WM1\(_>D$M1X*Q-H/``'T"R;9P$D````!LAN[H`*V +MI`6\J:!^WUL`F!D*C_\`__V?!+49"K(*^R44^2+9?%0``+^0LJ&S!``&^`C9 +M@%0``+^2LB\^`EX`O_FFD?0+#IC_`K/T`/8^#%X`^`B8&PB8'`&R&L>[:,?, +M0WZ,@P"8#P+9?%0``/"D_[RJH*"?V9P6``"U`@*\J:#9@%0``*`!H)`)_W4) +M`C^J/93?91H``#4)!C4*!S_Y$)D!(/G[(3YM7@"_J::;]`L*F*H"LZ0`]O@` +M/H%>`+^IIIOT"PJ8J@*SI`#V^`"8KPTS\``3F*D,QYD9,Y``"97Z"/@`/:3X +M`/0PW/F"L*$.&*D!L+$-L,$,L-$+Q)`/,P`!!O@(M*`-Q`G_E)8"V?P-``"\ +M:6!^M($`S:B\S**\\`)(N +M`7#Q(><9@P$%"+"1$;TTMI0#O420F0:]!+"1#[#A"C[%7P"T\`JF#_0;"7.` +M``9RA[20"[.4`!*R:N0;__]^B($`/DE?`+)JQ!L!?O2*`+3@"=\@3```O32\ +M_ICD?___NYH"II_T'@4#`;20"[.4`">TH`ZTL`VTP!'D'?__?BB8`$Z\`.1Y +M__^\ZJ*FJ?!,"/!&`;,P`!:S0``2LP0`!W`1(9```3ZF7P"]!*8"]`LRM/`/ +M4!$!Y!G__Z:?]`P9DE4!O""2IEGT"`ZF`O4(5O^F(/0+#0H(LS``'#[L7P"S +M0``2=.`AM)`,"@%@GC[N7P`*(_N%)/E2VO@-```+!'Z_-P#:_`T```L,?K\W +M`-H(#@``"P1^OS<`V@P.```+!'Z_-P#:+$P``$N0`'Z_-P#:$`X``$N``WZ_ +M-P#:[$P``$NJ!7Z_-P#:F%(``$O<`7Z_-P#:P$D``$L@`GZ_-P#:%!,``$N` +M`7Z_-P#:A%0```L@?K\W`-J4$0``2X`!?K\W`-K@2P``"T!^OS<`V714``#? +ME!$``*"?/?39A%4``-X4$P``()_9E!8``""?WZ`1``"2^02@GY#_#*;^]!OV +MWQ03``#9?%0``*"?O?39>%0``-Z4%```H)_?(!,``)+Y!*"?D/\,IO[T&_;9 +M@%0``+T$VI04``"@D$L``GZ_-P#9F`T``-J<#0``()`+7'Z_-P`/`=F<#0`` +MO>2UGP:]M+W$184$T2!,``!$7AJ#NML`T/@-``#:"`X```+_V?P-``"\R?`8 +M^0'$[0_PE/#_V94U^0&SY``E&`\!&*D!H!/P]/#_W_4U#P'PE/#_V97PE1`U +MJ0$^I6$`L^0!)=D,#@``M10!E+\"O/GP&/D!D+L!\)3P_]F5-?D!/J5A`-\@ +M3```O,^0H)7?D!$``+SOD""2D.X!D,P$L^0#A3WTV946```@G[WTV9@6``"@ +MG_M1^1*SJ0.B`+"F`_0,$+.@`1NSK0(N`3XO8@"SJ02[`+.M!2`!/M9B`-\L +M3```O00_^9`!`9#_!#"6`/0>'MDL3```M@0""P2\"0"R"GX<.`"R&@F`/F%B +M`+(0LQ0PU3X,8P#>$`X``+WT/^F0\0&0[ASPE`'T&R:4^0*4\`6["0+9$`X` +M`+P)``LF%(``+WT/^F0\0&0 +M[ASPE`'T&Q64^0*4\`6["0+9F%(``#Y28@"R'[,4$=X^#&,`W\!)``"]I+_Y +MD*`!D/\@LY0`&]G`20``MJ0%"R"\J:!^'#@`L@H^#F,`L@JS!!#;/@QC`-[L +M3```O?0_Z9#Q`9#ND?"4`?0;'I3Y!Y3P!$N1`+P)`-GL3```O`\`O`D`/E=B +M`+(?LQ0*U;VD^Q'%J03T,*#Y8KB3`"`"LJ&8I@FRLOY``0M+(,?G>C`+\)LY`!!O@( +MLAI^=IP`V0`H``&_F>1/___DGO\_IO[U&(,`IN+T&'V8&0;?____`-V$5``` +MO;3]GP3?`````_V?!;49!K_9D-T(LY0`1]J$50``/ZW?A%0``)2Y`[R?D*"3 +MV8A4``!2[@&5;!B\N_"V]`*\^?`)`KN``"`_<\$_P[D_9P%#^_][P3]G@7_G07_"\;$R0+T +M"P['#P'9P%4``+6?`<3)!/0+.L0)!/0+,<0)`?0+(M[`50``W>`9``!8Z0Y_ +MW_&5`!#P]4!UZ0Y@WS[R90`)^_T)!#[R90#P!03$R0CT"SK$"0CT"S'$"0'T +M"R+>P%4``-W@&0``6.D-?]_QE0`0\/5`=>D-8-\^+V8`"??]"00^+V8`\`4( +ML,8`]1\"`K`&`/0>&+WDWP1@$0'<+AD``-W__P"./N%F`-X`@!$!O^_9```` +M@+W$W01@$0']^07;+AD``*#OW@```$#?__\`SCZ,9@"_V9#,`?V>!?V?!*#9 +MD-V`/[GPE/^FR?0(Z=W`50``6-D$VU@F``'4`!/#50+7)!=\`6```?91US@1@K2#Y +M/C1H`+\MORF_+K\LQ`L"\93Q/;D?`/W^!-X``.(`_?D%_=X$_PZ4_?L%N9D` +M_=D$__T%_PS&\,0"]0N^`-S`50``F,D%DID!L)8!]`U.Q`D"V^`9``#T"Q=8 +MS@0/`W^]6,D!M<\%\.4!/KMG`%C.!'^]6,D!#P7QY0`$M<\%\),`\-5`C\`B +M`G7.!+R?D&"]MI0'OYD^-&@`"?W]"00^-&@`"?#]"039P%4``+60-SXT:`#9 +MP%4``+60.#XT:`")_P#__0D$V``"5#Q`UD`?9$%@``'6?!#XT:`#?$%@` +M`)4)$'7P!77Y!CXT:`#X"#XT:`"]!*`@^R'T,/SY$L?9JK*QLL"SE#\OW`9``!8Z0Q_W_"5!/#U0'7I#&#?/B)I`+.4`A.)___@CP```__9 +ME#[F:`"SE`,2B?__X(\```+_V93_G]79L%T``%B;@[6:/+61/;60/K6=/_Y/ +M`;V4D/\(VJ!>``"R_*#Y?@`^`#.D`!#?5"8``;_Y\)4!H/G[%03T,/SY(M+V +M7@``/RF]]/0P_/Y!`9`1$*`?Q)__Q_D!]!MVQ/D!]1O/`-E$8```OY_90&`` +M`'^;V?___P"R^OWY!+`1`/"S`-T````1#!'__=7>LT0``'Z&1P"_&;.4`!X_ +M*=[@&0``?^^]!/"5`2`I\?2__V#O/AMJ`+.4`A'?X!D``+T$?_D^!6H`LY0' +M:?@(/AEJ`'ZK``+91&```+^?V4!@``!_F["F`/`,"_`&`=G___\`LOK]^02P +M$0#PLP#=````(0PA__W5WK-$``!^AD<`OQFSE`(4W^`9``!_^?"50&#Y/AMJ +M`#\I\)3]("D^&VH`O02R"O0P!/LE!/@`V2X9```_F?"4_Z:I]`@%^`B0KQ#> +M$!0``0D!NY\$H.F]]-D4%``!H)^XF30#`*";H._X`-DP&0``/YF/0-W]\)3_ +MDID!O)K`B<`B`KRIH)2I![^=V01@$0&\KZ"VI`>\J:"_J9"J!+^IQYX,Q)\/ +M]!L'L^0`7)+Y`;"6`O0-4K/P#T^S\`A+L_`'3;/T``RSX`!%/LQJ`+/T!@JR +M_C[[:@`.`K/P!3/DV0`"]!L)O>0^^VH`#@>S\`H@#@ZS\`L:#@&S\`04^`@. +M#3[[:@`."#[[:@`.!93/`Y3)!KN?`M]`6```O)^0H)X-`;/@``P-`[/@`@8- +M![S,\)3)!+N?`M]$6```MI0"O)^0-9T!^`#Y$MGJ8```/YDSD``&^`C9,!D` +M`#^;V2X9```_F=T48@``Q+__W`1@$0'PE/_1````0+R?H(```#@^U6L`B4$" +M$+SIX)3I!+^?B;[][[SIX)3I!*#?WB0D``&\GI"_GY"9!+7?`;^>M=X$F,D" +ME>\0M=D"F,D#M=D#]`L%^`B_R9+/!!"[`9#,@/V1!/V>!;79!+___?`$_?D% +MM=\$D-T4Q+[_INKT'IC[$=X0%``!W104``&_ZDD``?0P_/F"O]"@Z=P`%@`! +MO92@V;_/V>I@```_FPF__?D$H,^@ZJ#0,[``!O@(V3`9``#3%&(``#^6O732 +M!&`1`3YY;0")00(0O!D0E!@$OXR_.9@K`;\DL,$)W0`"``Z.O_WO_9T$LLJ\ +M'A#]J06P1@#T'Q$+!;W4O02]5+WD/GUL`,>P#,>U<,=-T?"T#[(.QZD4]`L) +M2?_]_:D$$FD!\)3_E)\&MI0#N_D"V4!8``"\^?"8_`2460H/_;;4$?W9!0G^ +M_ZF4_9`%_9\$3Q_^O.[@MK0%\.0"\,2`_9X%_9\$3__#_9L%_9\$_]D%,\0` +M':"`QPG1]`L4M,`)Q\G1]!L+,FHR>WZ%-`"8/P3=__\`SMP````._TV4_PSD +MW0```$#]_03]GP7]G@6@*9@[`<1J_PP!$&8!?API`)(M!+_9C````>0/``*4 +M'@3]G`6,___'_9P$_?D%">_]^02@WY@Y!-T8)``!O.W@LGKQE/__H.F8.0*0 +M=P&U*0*8.0.0,Q2U*0.0(H!^66H`WBX9``#<,!D``#_I/\_$8?_PE/_P]/^\ +MGY"F&?4>G/[>\!D``+_OF/E`\94``;7Y0+_OF/D@\94`@+7Y(/N%!+.D`!39 +M8`(0`;^?#O[]_@2@G_@`O908F70SD``OV:Q@``!_F;WDY)___S[P;0"2^0&0 +M[@']^02S]`#W&/ET\)3_INGT"P6]I-EE&@``/YDSE``?V60:```_F3.4`!2S +MI`$0WV`"$`&_^?"5`:#Y^`#9)````;^?V:A@``"_F;NO`NR9Z`/_J:SX`+*I +MLJ^PI@#T'BNRNK"V`/0>$__ZK/^YEO0>!?@`N:H!^`"YN@'_^JS_N9;T'_`^ +M8&X`N:\!LKJPM@#T']@^96X`E:\0E;D0_ZF1_[J@_;\!O+FPMK00O+J@^`#X +M`/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +M^/CX^/CX^/@```#YD/F@^;#YP/G0^>#Y\/Z*`?F@?M-O`/R@_J@`_/#\X/S0 +M_,#\L/R@_)#X`?F0_LD!QYETL)8/]!L3]#(8_LD!_9D&_IP`_)#X`?F@^;#Y +MP/G0^>#Y\'[M;P#T,AC\\/S@_-#\P/RP_*#\D/@!````^0#Y$/D@^3#Y0/E0 +M^6#Y#!`0`:"?O^G?````@/V?!:#I^`"SE`$UW@P0$`&_ +M[]E(&0``OYW9____?_WY!*#OL]0`#D\-#MD$$!`!H)^]]-D($!`!H)_X`-X, +M$!`!O^G?____?]V(B(B(_9\$H.G9!!`0`:"=D)D$H)WX`/0P_-G@8```^0(_ +MF?0P_,2?_\?Y`?0;"<3Y`?0+3MF<8```OY_9[&```'^;V?___P"R^OWY!/Y` +M`?"S`)``"-T````AL`$`__W5#"'>OB,``'Z&1P"_";.0``;X"-_@8```/_GP +ME/P@^7[^5P`*`7X%40#T,`3[!03T,/`*`OF"]##\?@51`-G`90``/Y[?`,J: +M.]DT```!H)\/`9"9!*"?,^``"'XP5`#?____`-D`J0$`_Y_DWP```!'_[_7^ +M1@&P\0J]5-][K0$`O72[^0+8-````=D````AL/$,_>D%D&8TL.$+/IQQ`+UT +MOXFSE``&^`C9#!`0`=\`RIH[H(^_DMDH&0``OYFSD`$&^`C9[!D``#^0,PT` +MY@31>!H``#\9,Y``"G[)%``@$-E\&@``OY_9@!H``+^9IOGT&PF]%#X7<@!^ +MQ78`WT@9``"_^0$!II'T&Q.RD;V4H/E/#0[9!!`0`:"?V5@9``"_G]E<&0`` +MOYFF^?0+$-DL&0``/YDSE``&!0'9X!D``'^9\90`$/0+!WZ9!P#9X!D``'^9 +M\90`(/0+!WY`9``!_F?"4$/4+KP#0B5P``#\)O?2@;\2?_\?Y +M`O0;-,?Y`_4;E`"TL`RTT`JP80#:`*D!``P1W@(!``!^AD<`OVFSE`!U/PGP +ME0@@"3XF=`!^`*D!LZ0`"KU4/M!S``$!V<`V``"_F;.4`4_0X!D``'\)\)00 +M]!M!LU0`/K2P#+30"[!A`-H`J0$`#"'>`@$``'Z&1P"_:;.4`@]_"?"5$&`) +M/B9T`+.4`!#?B5P``#_Y\)3S(/E^7U``V6AF``"8F0*SD``&`0'=X!D``'_> +MY.D`"/0+'-E88```OY_DZ?_W8-D!`;/P``I^-D\``0'9T&```+^9LY``"WXR +M)0#]&@79L&```+^9LY``"WZD)P#]&@7D.0`!]!L]Q#F`,Y``#]GJ8```/YDS +MD``LV>`9``!_F?"4(/0;'MGN8```/YDPE@#T'!'9H&```#^9,)8`]1W9`-J@ +M7```?BRQ`+.M`,P`T.!@```_":!J\)0!]!M!V9Q@``"_G=GL8```?YO?```` +M$=G___\`LMJP80#]V03PLP#]WP4,$=Z^(P``?H9'`+]ILY0`"S\)\)4!(`F_ +M:;.4`UY^6W@!V9Q@``"_G=GL8```?YO?````(=G___\`LMJP80#]V03PLP#] +MWP4,(=Z^(P``?H9'`+]ILY0"$=_@&0```0%_^3Z*=0#?X&```#_Y`0'PE/T@ +M^3Z9=0"SE`(4W^`9``!_^?"5(&#Y/IEU`+.4!P;X"-#$8```OPJSH`!'?BEN +M`+WTF/D`9``!_F7.0`$?PE`'T"PU^`#H`LZ``!@$!V>`9``!_F?"4 +M`O0+*=KD&0``"P)^H3@`LZ``&WX;K@"SH``*`0$^6'8`VN09``!^V#@`V>`9 +M``!_F?"40/0+#'XE:0"SK0`Q^[,=`"S[D'>CP]!\)`;N?!/V>!/0+5-E8&0``ORJ_G9"I`<2; +M'Z:]]`LPOQF.'P#_Q,__MO0&_9X$__GE/I-W`+Q=^)#9`<2='Z;O]`L9#/0+'IBO!9BN!MG____[_?D$B?]__K6O +M!?WI!+6N!IBO!IBN"-P$80``?\V)___]_?D$V?__`?"UKP;]Z02)```,_>D% +MM:X(<]``&)BI"\3?_[:5&*:?]!L)Y=D`@&#)F*D&W____P#]GP2UJ0;X`-GP +M&0``]##\O)KHO=0)$OZ=#/0R$O0R$O0R$K/=`8(`V2A:``"@G;_IY)__#_0; +M(K/4`0[9*%H``*"?]#$2O92]U+"1`+WD?C2Y`#[Y>0"UZP&]]+7O`[7O!+7O +M!;7L`K/4`0[9*%H``*"?]#$2V3X:```\FNC$O_\)![N?`@\!O/FTQ.G__[F4 +M]`L%^`C_Z_79/AH``#R?J3[Y>0#X"#Y]>0#T,`3X`/DRLJ"8HPA^X7@`F`D( +MQS\2QYIHE9$LQ0!#=\E&@``/JYZ`-\?&@``//J8$)D!//FIV3X:```\FI@/ +M`;OQ!/"4___YE/0+$MGP&0``O)J8M9\(/O)Z`,4)!+B<`"`"]!L%^`@+![NQ +M`GY6>0#[,?DRTE@9``"_+]E@&0``O)\XP"8'0C9```*"/_9E/0+(MY8&0``O^^)```0"@'_V960_P&U&0CP +M]!^@[S[W>P"R&G[^>0`^YGL`O00)$OZ0#/0R$O0R$O0R$K,$`0O9*%H``*"0 +MLAJ]M'[2GP"S!`$0O?39*%H``*"?]#$2WU@9``"_^0H!O)J0\)0?H/G[,>2N +M___'Z<:2GP&P]B/T##O$Z3^2G@&PYA_T#07X"+S_D+R?D-_8!@``MI0$O)^0 +M/)Z8,)8`]!YA\)('E)H&V4`X``"\J:#X`.2L___=0#@``+WDVP```/^_W__[ +ME/0+"?@(/F-\`+/P`";?0#@``)3J!KROH)BI"YBO#+:5&+;U&[:4!OV?!:;) +M]`L/D.X!D-U`L^1&QKVD^`#9`!00`;^9LJ\*`?V:!/0+.^3Y__]R^M[Z80`` +MD)\0E?D0]`L9?^EFJ?0,![VD^`"]I&:?]`T5"@'X`'_IO:3PDP"FG_0-!0H! +M^`"]E/0P_/Y.`:#IV1@4$`&_G]F@7```M9H\M9L]M9P^M9T_Y/L`!/Y,`=J0 +M70``?@`^``D!\*3_]`L)L*8"\)P+LIKT,`3X`+_)O[_YP"SI``&^`B8J0'P +ME`CT&QN_J<>9BO0+$YBI"H_]_P#QE/__II_T#!"_64\`__V?!/0+!?@(OSK' +MJ:JSG2"?`)()`K"6!/0-#+,`(@FS#22-`,>DD)6B&%0J!OVD!7[Y>P"SI``& +M^`B8J0''G4/$W@'T&R6_J<>9BO0+'9BI"H_]_P#QE/__II_T#0V@?J!>`0$^ +M[WT`O13$V0.SE`$(LP0%/;(JLDM^_K@`LZ``#'Y:N``^,WX`V>1A``"_F;.0 +M?Q:_>K];OVR_/7X+N``*`3[8?@#X"#XS?@"]%+\_Q_FJLY0@?,?YD)7Z&':D +M!OVI!7[Y>P"SI``&^`B8J0''F2.SE`%K];OVR_/7[>?``) +M`K"F`/#\"_#V`;R?HOMQ]##PV0`4$`'Y@K^1_D@!_DOXJ_>[]LOUU^.&@`/HQ_`+,@ +M``;X"+,``!JS#0*``>4?``'9`!00`:"?OY$^\(``LHJR>[)LLEU^)7T`LZ0! +M)-WZ80``?]GE'@`!WP`4$`&0,P&@_E"9`;_Q8-D^[H``LZD".`'9."@``=X\ +M*``!OYV_Z=^@7```O_"S*_\#T`!8^@4)\/_9Y'"F`?0-'UC_!,39!V:?]!L] +MI@[T##B0"1"FGO0;,#ZW@`!SK0&@`-DH*``!OYFSG0&4`%CY!'.=`(P`F/D$ +MII[U"X(`&/D@,Y0`>[,@``;X"-$<%!`!OQGPE`+U&[4`W?IA``#;H%P``'_? +MF+P!V2`4$`&0,P%0_P'$SO^@GF#?ML4?Q0D"Q,\!_9\%H!ESI`$EF+\%,,8` +M\)P+F+X$MI0?_9\%6+\,H+ZUN0%UOP4^X8``D`D0H+E2J0%UN04^X8``OXJ_ +M>[]LOUU^WGP`LZ``0MWZ80``?]_E'@`!V0`4$`&0,P%0_P&@GF#?V0`4$`&_ +MD;`V`?0,&KT$DD0!"?^F2?0+$,09`?4;"_X^!X$`O02R"ON%$+V4M9,+:E$)"9`;R:H/@` +MF*D$OZ^VE1"5^A"SL``0X)_H`Q*I`[SYI?@`\9!`'[R:I?@`/90@J2"YWT`X +M``#=P$D``+_YLY``+YCY`9C^",>9`Z;)]`L'L\0`'2)``!`M:X!M:D"\,4!H*R8OPN)?P#_ +M_9\$M:D#F+\,V?__#_C]GP2UJ028N0FUK@>UK@:VE1BUJ07X`+*N"?^SL``U +M,\``+\RZ?92O`I2I![N?`KR:D*:;]`L&D*H!O.KR"0&[G`22F0']^02@WSZO +M@@"]E*#9"@'X`)BI")BO`<>>:#/D`!3'^4,PE@3T#0K:^`T``/@`&*DTQ.K_ +M,Y``$;:D`MD(#@``O*F@^`#9_`T``+:D`KRIH/@`F*L)Q[^$<_0`!O@(V0`H +M``&_GMEV!0``/YD8K33P\P#QY/\_=I0.DO\!?)[@E/D%MO0"NY\"WQ`.``"8 +MK`B\GY!8GP$SU``* +M%GOJ`I6_&`D!NY\$4ID!_^FD^`!XZ?]_`'R:HO@`\*3_\+3_N[H"\+:`Q[H' +M^``SM``0/:2PQ@3T#!L*`?@`&*DT"@0SE``/,+8!\/P+"0,\GZ+X`)BY"?0P +M_/F"LK3T,/RRI;+!\)0/]!L%^`B820C^2`'^1@&8$!7'F6B]Y)22`I"(*]D( +M#@``/32\*2"09BH'`3Z?A0"S"0BB`+`&"/0,$+,``1NS#0>+`3YZA`"S"0H- +M`;,-#7T!/H6%`#43`C43`1A.)[(:LBL@'GZC60"SI``*^`@^K(4`&!D"F%\% +MWBQ,``"R6_"4_[N0`K:4`KR>D,?_C+49"93Z!=E\4@``MO0"NZ\"O*F@M1H, +MD*H,?I9;```'#@$^GX4`F!\,F/D"MI4$]1L8`9CY`P`(MI4$]0L.`3Z;A0"8 +M&0R830FR*@P#6)L!((,@8[;5&+!A`/"S`+*.?@M:`+.I`-X`/VDSE``FF!X, +MF!\)&.D$\)3_=?D!(..8&0E8F0%SG0"\```*/I6%`#"6#_0,+9@>"O"4_Y2? +M!;:4`ACN!+OY`ME\4@``O/GP-?X$F!D,``T."""3/I^%`/@(/H^%`#43`C43 +M`1A>%+(:LBL@'GZC60"SH`!B&!D"&!X!\)3_NY<"E)\"V2Q,``"\^?"U'PDS +MY``1&/X!``T@+@X*/GJ%`!C_`<3I_]XL3```NY<"MI0"O)Z0-9\!F!\)``T. +M"C_Y\)1_(/D^GX4`O90*`:!9/JR%`+(./I^%``X(/I^%```-#@>FX/4;5/[X +M"+VDM1X5]#`$^X4$^8*]]+*QLJ*RQK^P&+4(O42]-`CPO70^98<`LPD#JP"P +M!@/T#!"S``$BLPT"AP$^+X8`LPD%]P"P!@7U",\`LPT'<@$^.8<`6&D!??1U +M'P-U&0(8&1$SD`$,L@\%_SX@A@`8&1`SE`,/L@^U)P8``CYEAP"R#[4G#CX@ +MA@`8&0A8'P-8'@(-`;O9!.3S___PXP`^:X8`F!D#_SW]6)D!\),`IOGT"PJ0 +M,P$^:X8`=1,##P(``SYEAP"F/O0-VP\"``<^98<`LFJR.PP!,EU^_E@`LJ2S +MH``M/ZD8'P@VE00FG_08$A@9$3.4`1FR#P`$/F6'`":?]`T+L@\`!3YEAP!8 +M&0.R#SXMAP`8&1`SE`,.F$D"M2D&/M.&`)A/`K4O#E@9`P\$/BV'`!@9$1@? +M$#.4`2^82@(S]`,6_:@$LBNXJ@`@`'[Z6@`^*(<`_:@$LBNXJ@`@`'ZK6@`^ +M*(<`D$H(,_0##K(K?I9;`#XHAP"R*WY)6P!8&0,/!5"9`0`"=1D#/F6'`!@9 +M$3.4`3<8&1`SD`,.F"D.D"HX/E>'`)@I!I`J&+.4`!P)`J"I/G.'`+(/IO#U +M&V;^H!^]I#YUAP`*`?N!^4+PM/_9"`X``)2Q`K*BO!D0O00#\`0"/M^'`+(: +ML@L,`0W_?OY8`)BI`K.4``;X"/V3!+WDN)\`(``^PH<`IO+T"QVR_KC?`"`` +MF/D&_Y/4MI4$]!OKIO+T"P7X"+/@``>UY`:0``%8&0'PDP"F"?0-K)@I!0WP +MVP````BRW,>9C)2?!;:4`KOY`ME\4@``O/GPF/X"V9@6``"@GKV4_>T$M?D" +MN.X`(``^28@`O^G]G`2XF0`@`)B?"OW[!;6?"ICN!I7I!/0+#__LE+B>`"`` +ML^0`W`\!V946```@G_M!F*D)]##L^5(!`?"4#[R1\M[`20``E/`%O`X`F`\% +MWMQ+``"VE`*\GI#'_XR_E93Y!;;T`KR?,M]\4@``Q0D$O#\PN)0`(`*RHK(+ +MD#H,?I9;`-F5%@``/Y^]E+4)!C/]``("F#P"E`K:4%/V?!-___P___=\$ +M_9T%M0D%/BR*`)@I";:5&/0+&@GP_\F4N)D`(`"8GP:U#P:UE`8^+(H`F`T% +MS%\'#O`)#[+J.Y\"_\[DWP``\`#$F_^XX0`@`+:4%+WD_9\$W___#__]WP3] +MG06U"04^KXD`F!D%O=3'F72FF_0,')@9!O^:]+:5!/0+"+C]`"``LAZRT;,4 +M`-ZSX``KF.D&M0D&M>0&QYD#]`MIF`D&#_?]GP2U"0:8Z0;PE0BUZ08^+(H` +MM0P&M30"&"DGF"P(_D\!D/\8-?D("0'>"`X``#7Y$:#Y"0.U\P,U^1"R^\?, +M:+(*ML0"O,[`?K*%`)@9!@_W_9\$M1D&F`D&\)4(M0D&F"\)E?D8]1NN`,?Y +MA)2?!;:4`KOY`MGT#0``O/GPF/\"E?D$]!L)O>0^BXH`"?"]Y/WY!+*;N/\` +M(``^AXH`F/D.F/P$O?3_F]2VE03T"PBXWP`@`)7)$+SIX+/T`.28/P()\.SN +MNPV0[@']^02X^@`@`)BI!<>9=*;I]`TYF"L(Q[MH?G>'`#[@B@"8+@K9F!8` +M`+^?V0````C]Z04)\+4N"OWY!+C_`"``F/X&M0X&M?0&^U44F*D*3P#__9\$ +M\)4!M:D*^`#T,/SY`C[CBP`_V5C/`?"4 +M#[QIE/"3`/])G6;Y]1N.`)C/`Y7Y!/0+/?_SE,0+_[B?`"``/I6+`)CY";:5 +M&*:;]!LCF/D.F/T$O?3_D^2VE03T"PBX[P`@`)79$+P9$+/T`-F8SP*5^03T +M"UW_\Y3$#/^XGP`@`#[8BP"8^0FVE1BFG/0;0YCY#IC]!+WT_Y/DMI4$]`L( +MN.\`(`"5V1"\&1"S]`#9/OR+`!C.!,3I_Y2?!;:4`KSYPMGT#0``O,G`,^T` +M2/\2``$)_R8)]1L,_[(:^W4$F*D)QYF$E)\%MI0"O/GBV?0-``"\Z>`_Z?"4 +M`?0;!?@(F*T(Q]D1]`L'^`CX`)CO`XG___?_V92UJ0CP]0+%J02UKPZXF0`@ +M`K7I`YBI",>9:/0;/YBO"=F@20``\/0/MO0%O/GPF/D%Q?T$N-T`(`+'F8R4 +MG@6VE`*[Z0+9?%(``+SIX)CI`_"5`K7Y!K7M`_@`&*DTF*\("A(SE``/Q_EH +M"@@SD`(&"@+X`/DBLJ!^GXP`,J$SI``*O:0^%8T`L@I^]((`F`L(F`P![:,?,0WZ,@P#9G!8``/"D_[RJH+RIH#^O&*D!"@$[GP+PE(`SE``4Y"__ +M_\09_[VDIOGT#`4*`?LAV8!4``"_GSXVC0"_^9B9"<>9A*:I]!L'"@'X`)C_ +M`K/T`.R]I/@`V0`$``!8G[KY@K*3"`'P\P"]1,W_`]:<#0``O/^0NX\"O)]P +MO50^PHX`WY`1``"\3Y`_F=_,!```Q)'_O'&0MI0$O)^0M94#M6D3H)6UE0&U +ME0*S%`!QW_@-```_^3.0`"]8.[JR^@P!#?_PLP!^_E@`LZ``&YBJ`K.D``;X +M")AO$U@YNJ#Z\),`M?D#WP@.```_^3.0`#!8.[JR^@P!#?_PLP!^_E@`LZ`` +M')BJ`K.D``;X")AO$U@YNK7Z`O"3`+7Y`]G\#0``E!("O"D@&"D!QYD&]`MF +M6#FZ\)0'LY0'7;,0`0;X"`\!O!^2E)H"V0P.``"\J:"\&)+?7`4``)20`[P/ +M`*`%M04!/ZDSD``N6#NZ#`$-_^>[@P&\O+!^_E@`LZ``&)BJ`K.D``;X"%@Y +MNJ`*\),`M0D!LQ0"#5@YNO"4!_0;/#\I,Y``-U@[NK,4`@=VM0.R*O"S``P! +M#?]^_E@`LZ``')BJ`K.D``;X")AO$U@YNK7Z`?"3`+7Y`Y!$`=^4%@``/_GP +ME/^F2?4(FO[[@?&D_S_QM/\_N[H"\;8`(,>Z#?@`^8+9>%0``+*ES(``.F`\"M2\" +M/H>/`)@)`J")OV^8"0*U#P*@8+*0/IR/`+("F``"LPT`:/_[@?DRV815```_ +MF3.0`&;PE/_>A%0``)*;`;W4O<0#\-+___\`?12]!#X#D`"_[[/P`"U8Z0)F +MFO0;'?WS!+C_`"``F/D&=>$"_9($M?D&H.`^_8\`IMST"`6RW)#=`9#N"*;; +M]`W)$,\!V815```@G_LQWP`$``#9=@4``'&F_C_T#!(_F7:4#GRID%"9`3X_ +MD``_F1"9`?"4`7:4#G7YNO@`F*D&^0*RH+:5&+.0$@BSE`%0V7A4``"_GSYK +MD`"_^::0]`L.F/\"L_0`]CZ@D`"8#PC'^0WT&R>8#@;9__\!\/_YE(\```K] +MGP6U"0C9____`/WI!+4.!CZ_D`"R"GVT?NB.`+(*?M9<`+.@`!'9`"@``;^9 +ML@I^VET`^P'Y`MF8#0``/YGDK/__WI04``!]I/"4_P`!E)T$O-[0/A21`!CI +M"?"4`?0+)YCI`Z:;]!L?&.D(6.\#O`F4\),`_\F=9OGT&PN_Z5B9"7R:H)#N +M$*;M]!O.^P'Y$G*P\+0!?O2*`'*AO;1R"G[!D`!\&J#[$?D"V9@-```_F7*L +MWI04``!]I/"4_P`!E)T$Y\N#`;S>T#Z3D0`8Z0GPE`'T"S`8Z0A8[P.\"93P +MDP#_N9UF^?0;'+_IF)D$MI40S)F\$)D!\)3_9LGT&`90JKR0[A"F[?0;Q?L! +M]##X^8*T8`RPP0FRM;+7,NA]M+*@/U)^](H`"P&RH[(*?O2*`+"A"K-D``JR +M.C[RD0`8"@'9"`X``'VT\*0/MJ0"O*F@?O2*`+PZ,'VD?C61`/"C`+RCH-F8 +M#0``/YG?G10``#U$\)3_E)X$O._@/B*2`+^9II;T&PX_^?"4`?0;!A!$`9#_ +M$)#Y`Z;^]!OF?10^JY,`O^F8F0$SA``9QYE#O?0PE@3T#04/`;20"::?]!LG +M&.D(\)3_0?__^[G`2F^?0=";VD/LN3`,2__]Z4%```E/D$ +MO)Z0OYF8F02VE1"\J;"FM_0(";*K/NF2`+S_D-V<%```MI0#O)V0&)X!MO0$ +MW9@4```0(@&\_?#PY0%U\0$UG@'$"?_>E!0``)2:!+RNH#Y:DP"_\)@)`3.$ +M`!G'F4.]Y#"6!/0-!0X!M)`)II[T&S48^0CPE/]FR?0;*AC]"<39`?0;(9@) +M!+:5$+RYX*;G]!@3Q=D!=?$#-?D)$"(!/DV3`+*^D/\0LNNF^O0;IU#,`7#& +M#_0,#-^4%```/E*3`%`1`;-@`"$+`7(:?L&0`'*@24G0,^?I0` +MQ+D!]`MELT``,9@_!;&FNP#T#1:\_?"\_O`8^0&2JKP2F40^8)0`O/WPO/[P +M&/D!/)J0/G.4`)@_!;&FNP#T#1F\_?"\_O`8^0&2JKP0F40U^0$^>)0`O/WP +MO/[P&/D!.YH"-?D!O:20[@&VM0&SL``(LZ0`COM!&+DT^3*RH+*RF+H$,Y0` +M#96C$+T4/JN4`+*Z`0%^M($`LJ.8"0J8"@@-_[W$6)L!\+,`?OY8`)@.%K*M +MINKT&QU8Z0@8[QA\DY`0_P%UZ0@U[QBS$`!\/D^5`+/@`$T8Z1A8[@@UJ1B8 +M#Q9UK@A]Y#_Y\)3](/F8"18UGAAUG@BS$``HF`D6F)D%LY0`!O@(F-\%/_GP +ME/X@^9@/%ICY!;79!;V4M?D%6-D(&-\8/]Y\DY`0_P'PY0)UV0@UWQ@@WK,0 +M``ZRVK(K#`%^SI,`^S'T,/SY@K*Q]##\LJ*8L`9^LX(`_D^`+`&!_0,$+,``1NS#05R`CX6E@"S"0HX`;,- +M"V0"/A*7`)@I",>9$?0+!?@(-1,"-1,!&"DGLAJR2R`9?J-9`+.D``KX"#XB +MF`"8+PD8&0+>+$P``+(KQ_^$E/H%MO0"\)3_NZ\"NY8"W_0-``"VE`*\GI"\ +MKZ"U&0FU&@J0J@Q^25L```4.`3X1F`"8'PJ8*@F8^0*VE03U&^L!F/D#MI4$ +M]1OA`<>JA'X7C0"SK0#6`;(.``<^$9@`F!D*F"T)LDH,`EB;`2!S(%.VU1BP +M40#PLP"R?GX+6@"SI``&^`@_7S/T`""8&0J8'PD8F03PE/]U^0%PE@#PG`N\ +MB0(^MY8`,/8?]`PFF!D*\/3_E/X%MO0"&)D$N^\"``O?]`T``+SOX#7I!#ZW +ME@#X")@9"IB?!;/P``L_^?"4_B#YF!\*#@<_^?"4_CX,EP`8&0&8'PDSE``- +M&/\!($\^`)<`&/\!\)3_WBQ,``"[E@*VE`*\GI`UGP&8'PD."@`+/_GPE'\@ +M^3X1F``8*328*@0SE``-E:,0O00^+Y<`LBH``7ZT@0"RHY@9"K)*O<0-_UB; +M`?"S`'[^6`"SH`!JF!\*IJ_T"T,_^?"4`O0+.QC_&#^I-:\8F!\*\)4"(*E8 +M_PAUKPBS```BF*\%L_``"S_Y\)3^(/F8&0J8GP6UKP4_^?"5`2#Y&*D86*\( +M$ID!>_,"-:D8=:\(LP``#+(KO<1^SI,`F!H*/ZGPE`'T&P:UJ068*0C'F6BS +ME`%@F"D!QYGHLY0"5MF(7```/YTSU`$@O>39$!0``:">3P`!D)D$H)^XF?0! +M`*">/OF7`#/0`"L2WP'9B%P``""?/B"8`+(./A&8``X%``NFX/4;<_VU'@:] +MI#XBF``*`?0P!/N%!/DR/ZFRLK+!LM,SD`!"LLL-_[W$?OY8`+.@`#28H`6S +M```MLBI^AUX`E!D#O#F2\*3_MJ0#O`J@O*F@&*E),Y0`!QBI`<2:_SYVF`"] +MI/LQ]##\V9@-``#Y@C^9??2RL[*E\)3_E)X$V9T4```])+SIX/Y)`9"9)F"? +MWYT4```_L3[!F`"_F;.4``\_^?"4`?0;!A`B`9#_$)#Y`Z;^]!OG/E69`#_9 +M\)3_[QLE/0>?=V4%```Q/#_E`D$O)V0OYNR6K),#0%^H5X`LZ0!8-^< +M%```W9@4``"\`)"VE`.\GY"4#P08G@&\_?!_31`1`?#E`36>`77]`3YDF0#^ +M1`'8F`T```?_!@&01"8F$O0+%3^*W9P4``!,_P`]M`__/OF8`"`Q"@$^A9D` +MO:3[A02SH``.F+D"M:D"/J"9`)B_`MF`5```H)_9?%0``+^?WF4:```*`;6_ +M`C_OH)L2_P$@[WZY;0#X`/0PY-ED&@``^8(_F?0P_+"A#3"Q,S.9`,D!WP`$ +M``!8^;HRN/"$_]=0&0``\),`S94#?CZ-`+20#<2-(,2.`=2>%@``D)D!\93_ +M/Y26$-D$``"`_VF5L)$.V0@``(#_:96PD0_9!0``@/]IE;"1$+Q5D+R5D+TD +ME)$$TR1:``#9S`0``+#1"[P9$+#A"GZTN@#?``0``%CYNI@?`_"3`*;Y]1O8 +M`+,M`($`OQRSP`!,M)`*LY``1;2P#K`A`+VDO=2]Y'XTN0"SI``//SGPE0$@ +M.3ZXF@#=G!8``#\Y/]]TT!K>3AD``/"4_B`Y8.T0_P'>G!8``"#OF!P"L\`` +M*[3P"[/P`"0-\/_-E+B9`"``F)D%M+`/O:2]U,>9=+WDL)$`?C2Y`)@<`;/` +M`%"0(`&\@)?PE`'T"T.TL!"]Y+(JL.$`O=1^-+D`LZ0`$C\Y#P&[\`3]GP4^ +M-YL`/T\_/G30&@D!$/\!NY`$8'WPE/\@3SF9`/V>!"`YD"(!D'<"D$0"D!$0 +MLRT#"/\TX#,SX`!1WUP%``"47`/9``0``+S/P%B9NIC/`?"3`*;Y]!LRO\RS +MP``M"0K;"0``@+"1`/]KM0H!O=2]Y'XTN0"SH``2WYP6```8^0@0F0$U^0CT +M,`3[A1SY@M1.&0``LJ6]-`@!LD??)%H``#_Y\)3_NY,'\)0!]`LM?TGPDP"F +ME?0+([Q9\J:5]!@*DO$!/N2;`+CQ_S\`L!8$]`T+`00^\IL`O12\@V2])#XJ +MG`!_2?"3`)"9`<2?!^20_S^S-`,/L_``"W5P`SXGG`!R"GX4D`"R"C)K?L"9 +M`)`B`:8A]`C/D#,!D$0"LST$?O_[@=DP`!`!OYGY$K*AF*H$\)0$]`LE,J#P +MI/]^`@<`LZ0`&1@9"`H2,Y0`$@H(,P`"#`H"/G2<`#VD^Q'99!H``/0P[/DR +M/Y^RH1#_`2"?F*D,QY-TLS0$89BO"]DP&0``/YG'\O#PE/^2F0&\D@"\`/"4 +M"02[GP+?1%@``+:4`KR?D#^9,Y0`%K(JO;1^8"0`LBJR.[W$?A,@`+P`\)0) +M!+N?`M]$6```MI0"O)^0/Y\0_P$@G]ED&@``/YDSE`$XWS``$`&_^=Y.&0`` +MO:3PE02@^;_Y\)40H/G9`"@``;^9\93_/W7I`V#I=>D!=>D"?KEM`)@9"<4? +M!+CR`"`"QYF$E)\%MI0"O/D"V?0-``"\"0`_"?"4`?0;!?@(D`H,LAM^25L` +MO928'PFU&0X_";;U&,>99*:?]`L%^`B8#P*5^03T&S6U`@*R&GZS@@`8&2?^ +M3P&0_Q"RK#7Y"`D!-?D1H/D)`K7P`[+[-?D0LAI^LH4`/L:=``GP__F4N)D` +M(`"8GPZU'PZUD@Z8'PB8'@:8'0G9__\!\/WY!(D```K]^079____`+4?"/WI +M!+4>!O#4#_0+&K(:?EB(`)@9"H__`/_]GP3QE0`"M1D*^S44V0`H``&_G_E2 +MV8!4``"])+^1Y//_/P7_U#`9```^#)\`6!D"OQ!FE?0;0Y@+")@,`;(*Q[MH +MQ\Q#?HR#`-F<%@``\*3_&!\'O*J@O*F@&*D!.Y\"\)2`,YT`L@"R"GZ?C`#P +MI/]\HZ!U&@)8&@)R.W[4C@"SK0">`#X5GP"8"0C'F0WT&PVR"GYVG``^HIX` +ML@I^#(P`F`D,QYETLY0$5Y@/"S])Q_KP\)3_DID!O)H`O`#PE`D$NY\"WT18 +M``"VE`*\GY`_GQ+_`2"?]!L)"P%^8"0`O`#PE`D$NY\"WT18``"VE`*\GY`_ +MF3"6`/0?!?@(F!`"LANR*GZ(F0"R`;,=`"'_/BJ?`+(2F!$"/@R?`!@9!C.= +M`&C_/IR>`/M1 +M/A*@`+_III#T"PZ8[@*SY`#V/I"@`-^<%@``Q*G_O)F0O)^0#_]U[P(_F37I +M!CZEH`#X")CO`MET5```H."@G]^<%@``Q*G_O)F0O)^0#_]U[P(_F;7M`C7I +M!MEX5```H)X^I:``V8!4``"_GSY_H`"_^::0]`L.F/\"L_0`]CZ?H``)`37Y +M!CZEH`#9=%0``+^>L^0`H3XVH`"R"GYVG`#[`?DBLJ*RL#+!"@%^S6$`LJTR +MJ3.D``SX"+VD/C.A`#\.\)3_#`&[G`*4F@+9+$P``+RIH#/@`$K?+$P``,3I +M_[N<`K:4`KR?D#^9Q!__\)0/IOGT'0HUK@$^)*$`&"D!WRQ,``#PE/^[G`*V +ME`*\GY`8GP$UKP$UG0$^)J$`(`T_J<0?#_"4\/WY!2"O^R&8J0CT,/R]Y/F" +MQYEH]##\E),"_D`0H!/G&C +M`!@N+#V4M2,(-2D!("XU*0*R*K([?J-9`+.D`!>8*P@8+"RR*GZGH`"U*@D^ +MX*$`&"D"WRQ,``#PE/^[D`*VE`*\GY"U*0E8+Q=8.0%F^?0-!G4_`0X!``(^ +M9J,`6"47F"H(&"TL/92P<0`@>2!IY%O__PP#LFY^"UH`LZ0`#+(.``,^9J,` +M/VFR#@`$-2D\\)3_E)\%MI0"N_D"V7Q2``"\^?"U+PP^9J,`L@I^S6$`3.0`"7P +ME/^4GP6VE`*[^0+9?%(``+SY\!CY!#7I!#7Z!#Z@H@"8*0EUF@$U+3P.`P`$ +M/F:C`/@(L@X^9J,`"@1^S6$`!/WY!;4/!9A."8G_#_[]^00)\,0= +M#_WI!/W>!;5-"1@I/(X`\`'%#`2XS``@`K:4#/V>!/WY!;4/!;4L#I(1`;4@ +M#=_@2P``#@2\^!D`!3YFHP#X"`X$/F:C`)@I#)B?`Y7Y!/0+"9@I#;6?!I@I +M#)@O#@X%``BUGP.FX/4;`_ZU+A2]I/0P!/N%!/0P\,6I!/F"N)D`(`+T,/RR +MH_Y(`?Y&`?Y'`;*QL,$+LM6PD0J8L`:]])"(-I!F-Y!W,#Z%IP"S"0;,`;`& +M!O0,)+,``E&P!@+T#`RS#0&X`S[\HP"S"03U`+,-!:H#/NFD`+,)#+T"L`8, +M]`P,LPT'E@,^'J8`LPD-@`.S#0Z(`SX`IP`8.0*R#P`"-1DL/H6G`)@Y"+(Z +MQYEH-1D<,I!^LX(`M1H(,P`""Q@Y-#.0``T8&2P2F0,U&2S\$ +M\93P`0_P_9X%_9\$M3D),]``'I@Y"-S\#0``QYEHMI0"O)R0&)\!\/5`-9\! +M&!D<#PZ<`/928$`@U&0$U&0(8 +M,R>R&K(+(!-^HUD`#@&SH`!V&!D"&!X!"@'PE/^[F@*4GP+9+$P``+SY\+4? +M"3/D``T8_P$@#SY>IP`8_P'$Z?_<+$P``+N:`K:4`KRH-D^D*<`L@\^A:<`#PP`#:;P]1LG_+4?!KWDLNKT +M,`3[A1`0Z0'?E!8``-R0$0``(/G$Z?\\P)D^7:0`WT09``!__]E@$``!OYGP +M\@^V]`/'F:B2F2"VE!"\GY#?``"F#KR?D.R9`/"4GQ"VE`R[^0+9-``0`:"? +M^`#Y(K*OLL+_RP2SK@`,#[(+?L<.`#[JJ0"XJ2`$`K&6@`#T#`VR"WXZ+@`^ +MZJD`N*D@"`*PEB#T#1FXJ3`&`K"6//0,(KBI.`8"L)84]`P-L@M^U[$`/NJI +M`+(+?LED`#[JJ0#9`"```;RI$+.I/+,`L*8\]`PCLZ`D5+"F)/0,#+.M('L! +M/J^H`+.@-&^SK3AN`3X-J0"SJ5BQ`+&F6`#T#!&SJ5"(`+.M5%0!/BJI`+.K +M``8(`;.O!`9%`3YRJ0"R"G[P#@`^ZJD`OQZ_&;\=Q`P(\>04!/&4`1NY+P#] +M_03]^07D"10$_?P%N9D`_>D$__X%/NBI`+\>OQFYSP#D#?___?D$B0``__WI +M!-E`(0``_>T%_^\%H)`^Z*D`LOJR"WXY4@`^ZJD`"<#]"039``0``+60,3[H +MJ0#9``0``+60,C[HJ0#9Z!D``+^9\)0!]1NJ`-D$(``!OYG$"O_PE/^FJ?0- +M!;*:OQZ_';DI`$\`__WO!/V=!/V>!?^:!3[HJ0"_';\````X+DO`.0+ +M$>#]^03_#I2YF0#]W@3]V02)[A\?_````(/W^!:"?H!#[(=DH6@``OYGY@K.=`#$!V0``$`&_D+B9-!``OYGP +ME`+T"QW=Y!```;_?V61F```.`2">V0```(#]^02@W]DT$!`!OYGPE`3T"S)^ +M2Y\`WF0`$`&_Z=\```"`_9\%H.G9)````;^?V7@:```.`2">D/\!V>!A``"@ +MG]F`&@``OYK8!``0`=E\&@``UP@`$`&_GI*A`=8,`!`!U6!;``#4````0-,` +M``"`T@``$`$^$*L`OXN_?;]LO.J2IN'T"S^SD`\\L.8/]`T%^`B\[I"\GI"0 +MGP&VE`*\7?G?8%L``+R?D+6<`J";D.\!_P24Q/X/_9,%H"F_(#X0JP#9?!H` +M`*">V4@9``"_F;.0``;X"+WTV000$`&@GP\!V4@9``"@GSX=JP#$"0'T&XG9 +M?!H``*">#P'9$!`0`:"?^X'>``0``-W@&0``F.D#?]^UZ@3QE0"`\/4(M>D# +M8-_X`-E4)```\*3_MJ0!O*F@6*H!\*1_^`#>."```;_IQ)\(]!L/"0B@Z=D` +M(P``-9\8^`#96"```;^9\)3_IJGT#0>]I/@`WM`C``"2KP&5^06VE`*\GI"_ +MGO#T'PD!NY\$_9X$\*P+\*8!^`#>``0``-W@&0``O^E_W[7J`?&5`(#P]0*@ +MZ6#?^`"SP``IW0`$``#;X!D``+_9?[_<`%H``+_.\94`&/#U`J#9D.X!8+^@ +MSI6I&+.4$3+9`",``)B?!-G___\`_ZF4IOGT&QS>``0``-W@&0``O^E_W_&5 +M`!#P]0*@Z6#?^`#9`",``)B9:\>9JK.0#Q"SD!`ELY0+1#Z#K`#=X!D``'_? +M/>39RC4```H!\/4"()Y@W_@`W>`9``!_W]G`-0``E`+"F`/"L"_"F`?L!F*D*^3*RH;*SF*(!QYD7]`L)LJ`^ +M]*P`F!D,F*H+MI4;MJ48MJ0&_:D%?OE[`+*@Q"D(]`M1LP0`!O@(O10)$OZ1 +M#/0R$O0R$O0R$K,4`0O9*%H``*"1L@I]M'[HC@"8"0BR"O&5`""U"0A^C:P` +MLQT!Y@"]]-DH6@``H)_T,1(^&:X`LP``%,4)!+VTN)H`(`(,`3Z9K0"8'PC9 +M`",``)B>?9@=#/'U`""U'PB4Z0/?`",``+R?D)B;@=D`)0``MN0#O.G@O^FV +MU1NR$+;4!KW$O-F@F`D(QYD2]!L)O:0^&:X`WL@U```_Z=W)-0``/]\0F0$@ +MZ1#_`2#?F`D(Y9T`(+4-"+/``$:8"0K?____^,?>:`H!_9\$WP````']GP6U +M"0K9\!D``+R>^-G+-0``()Z5V1R\J92U^0B8"0C'F1/T&Q*@.CX9K@"8'`I^ +MA$0`"@'[,=D`(P``]##T^8*8F`+T,/C^20&0F33^3P&@F)#_,+*3O93>`.H` +M`*#YU____P#?````(?_GE/V?!;T4L)$+U!`&``#9L>\``-6,!@``O)YB/F*P +M`+`6"/0-/7Q1*+Q!".0K__^R"G[HPP"SI`,JV="K``#?````(;"1`#V4_P?D +ML@KD*____>\%,)$$?<0-(7[Z10"_,;,9")$!L!8(]`P4L!8!]0BC`;`6!O0- +M&3YXKP"S$`EMDAD+L)82]0R+`3XZKP#:`.H``+)K?NC#`+.@!V&SI`-G_DH! +MLCN0JC!^`.H`LQT!9`&_.;.=`5T!M.`+V="K``"PD0`]E-H`Z@``,)$$LFM] +MQ`TA?OI%`-D`(P``WP#J``"UGP0^8K``?%&XO$&H\+,`?NC#`+.D!PKX"#Y5 +MKP"SH`,4OS_9`",``+6?`PD'/CRP`+\Y_DH!D*HPO$F8^96@.CYBL`#>``0` +M`+_OV0`C``"8F@-)_^_]^02@[Y*I`;"6!?0,#M(`Z@``LF`^K:\`?%J8O$HH +MY)#__[(JL@M^Z,,`LZ0'!O@(DJD$L)8!]`Q&V="K``"PD0#_)Y3>````$?^> +MY3V4L@LPD02R*GW$#1%^^D4`LZ`"-]D`(P``F)\#M9($L_0,-WXN5P"SI`(O +M/A^P`+.D`UO9`",``)B9`[.4#"%^+E<`LZ0""O@(/F*P`)*I!+"6`?0,"0D( +M/CRP`-D`(P``F)D#H#D^8K``W@`$``"_[^3Y`!#T"Q79`",``)B9`Z`Y2?_O +M__F4H.F_.:89]1L)_MD`(P``M9$"IACT"PT/`?Y)`9"9,*"?_DD!]#`(D)DP +MOYK[A0SY$M$T%!`!OQFRP++<#0SPE`'T&S6_K]DD%!`!Q;X!O=2@GYBO`9"9 +M!*"?F*\"D)D$H)^8KP.0F02@GY"9#*"\#M>D" +MLAM^C[``LZ0`$E@)!9`?$*`/4ID!=0D%^Q40V20@``&_F;*O6*Z#\)0!,Y`` +M"PH%<^[^`T6X^0`!`#^9"@0SD`PW&/DA,Y0$"+VD^``PE@CT#"$.`0H#O.GT +MQ/EL]!L8LNKD^8`!]!L/Q/D#"@+T&P?X"+VD^`#?``0``)6I$+.>_@,1F/T1 +MW$0$```^J;$`F/T0W$`$``#$J0'T&R?>X!D``'_IQZ_HMO00\/40\)4!8.G9 +M__\`___9E/WY!:#/^`#X"/@`]##\^3*XJ3@&`O0P^++#L)84]`P@V0`$``"X +MKS`&`IB1$="P70``W$0$```"`3XZL@#9`",``)B9A+B@(`@"E0\%YYE(`:;Y +M]1@H`MD`!```F)$0Q`\?W$`$``#0H%P``#TDV0`@``&\J:"S^13&`+#V%/0, +M$+/P"!NS_1#V`3[,L@"S^1C7`+/]'.@!/M"S`+^NOZ_DO?__N3D`_9\$CP`` +M__WO!/WI!?_MM?4+Q`$S(``2V3`F``&_G\?_D#ZCL@#9""```;^?Q_]D"0&[ +MGP2FN?4,G0&X"00!`#^9,Y0?"0D!-0D@N`\$`0`_^?"5`3[:LP"_KK^MN3D` +M#\#PY#__O_3]G03]Z07_[[7U"V,!V20@``&_F?"4`?0;"#,I`%(!N`\$`0`_ +M^?"5"#[:LP"QMO\`]`T%^`C9)"```;^9\)0!]!L(,RD`*0&X#P0!`#_Y\)40 +M/MJS`!@)(3.4!TW>X!D``'_O6`T%Q1D!H,GP]0%@[W/4`#68"028#@&@"9@) +M!;4)`5@)#'4)!=DH*``!OYFSE`$6F`\%E>D?\)8!MI0?_?D%M0\!N`D$`0`_ +MG<39`O0+-[\/"?#_N92FG_0;*S,@`!395"8``;^?#O[]_@0^P+,`20`!_D\! +MD/\8H/F__]E$`!`!H)_%WP*X"00!`""?/MRS`+@/!`$`/_GPE00@^:"KN`D$ +M`0`_F3.4'V(8"2$SE`!;,R``#=E`)@`!/@*T`-DP*``!OYJ0F02_F[.D``;X +M"%@)@P$"D`P0,!$$MI00#1"PD0#>B+$``'X[P@"SI``9V>`9``!_G_#U`6"? +M"0,U"2$^1[0`-0$A]#`(^S4$WN`9``"_J7_O\94`@*"IQYGP_9\%8.GX`/D2 +M/ZGT,/BRH,21_[,9!-,`L!8$]`P0LQ``&[,=`_T!/L6T`+,9!1$!LQT&[P$^ +M0+8`6*H!P"SH``9Q:D$M0$$N)D`(`*U"@*U"0,^ +M>+8`6`D!QYK&Q*T!M0T&DJ\!L/8C]`PVW-@&``"\_Y"\GY"4G@2\[."8[`JS +MP``?D-D$MI0#O`F0H)R8[@N4WP.\#_"U_@D^1;4`V0`$``"8FS*8F3&8#@'P +MI'ZVI`.\J:`)`K#A`#"1!)`,(`T0WDVT``!^.\(`"02SK0#^`#Y^M@"8#P98 +M"@&0^02VE`.\"9"_F;;T`[P/\,>JQK4)`YCY"9@+`[*3;0``'X[P@`)!;.M`*@`/GZV`)BM!5BO`;_9 +M\/,`Q/H_MI4;IJGT#0F]E#YUM@#'_\:P]B3T##N8W@*2_P'$)"?)#7\`1C>!C6>)%C=`77]`9@/!K:D +M!I@,!0U`D/D$MI0#O`F0OYFV]`.\#_#>3;0``+RIH+4*`PD"F/L),)$$F`\! +ML/$`M0L$?CO"`+.@`$H)!B`)/GZV`%BJ`9@+!7Z1-@"SH``H6`H!?OE[`+.D +M``;X",6I!+B9`"`"M0H"M0D#O92U"00^>+8`F`D%M0D""@$^@+8`O:3T,`C[ +M$=DL&0``]##T^8(_G]GP&0``O)N8LJBPD0LS]``&^`BSA``_V31;``"\FYBS +MG0!8`=G\&0``O)OXV6@:``"4O@*\Z7`)\/WY!-DT6P``N/8`(`#?'!H``+R_ +M,#X:MP#93%L``+R;F+.=`!T!V10:``"\F_C9=!H``)2^`KSI<`GP_?D$V4Q; +M``"X]@`@`-\B&@``O+\PO.F0LFJPD0J]!#\UO10^I+<`F*D.#O#_GL2XS0`@ +M`)C?",24"(D```+%P@3_^96PD0FRGL?_$XG___O]Z02S]``MF-D.M=X(_TF5 +MM:D.LP``"[4""3YXMP"TX`J@XC\YLM`2F0$@.3ZAMP"S$``*LMH^H;<`F-D, +MWP````'%P02RVOV?!:!Y$E4!,U0`B+,``&"S%``?/SDSD``&^`BRBGZ'`0"8 +M"0GPE0*U"0D^"+@`I@;T&QBSA``-V?P9```^XK<`V10:``"\D;D)`K4)";]W +MM.`+#_#_'_2X_P`@`+7W#+"&`/#\"[N?`K7I"/N%#/D2V>1A``"_D++1LP1_ +M!O@(WC!:``#9_&```)0/!+S^\+^>F/T#H)#9Y&$``+;D`\?=P_'D^`.@G:#Z +M20?\M?L!_QF4M?P"_9X%M?D#^Q';_&```+^]L]E_FP"4W@39,%H``+SIX)CL +M`Z;J]!LFV>1A``"_GZ"=Q\G#H+FV]`-)!_SQ]/@#_\F4_?D%M>\#^`#'S,.R +MZS[XN`"4SP39,%H``+SY\*;Z]!L^F+\#F*D#30?\WN1A``#]_03QE/@#_9\% +MM;D#F*\#O^F@[/W]!+:4`_&4^`/]GP6/___?_9\$M:D#^`"8^0.R^\>RU;+FM(`,O13^D0ST,A+T,A+T +M,A*S%`$+V2A:``"@D=GP&0``O),(Q"3_WB5:``"_"?&4_P_T&TD_Z0\'N_0" +M$)D!(.FP]@'T#"'=]&```-S@&0``O]Y_SPD!NY,$_9X%\?4`(*#98,^S%`$0 +MO?39*%H``*"?]#$2O:0^*KH`/92P@0"P,0$@Z;(*LFZR*[)\LEU^=P4`M0(! +MM04#M08$M0@%M0<""0>\E.*PY@'T#";9/AH``#R3V`D!O)[TQ-G___F4]`L% +M^`C_W_79/AH``#R?.0H!IAKT&Q&]]-DH6@``H)_T,1*R&O0P"/N!^1+9/AH` +M`#R;Z,2@_P\'`0&[\`*\'_3P]/\Y_P#]_@0\G[GT,/RS``8GLP0'5-D?&@`` +M/)N8,Y``2-G\&0``LKJ\F\C9"!H``#Z7N@#9)1H``#R;F#.0`"G9%!H``+*Z +MO)O(V1@:``"\FMB]E+(+L)$`O>1^-+D`LAH^K[H`O:3T,`3[$?0P]/E"?JUO +M`+"F`?0-!?@(W^AA``"_^?Y!`;+RU-QA``"0F0&0$13$D`_3#&$``#XFNP!^ +M_`0`LZ``1;\OL/8/]`T%^`B_'MT,80``O/^0O)^0E)\"O/WPH/Z8'0&0F0&0 +M#@&\/9F8&0*U^0*@(,3@#[])LAN]I*8)]!NZV?`9``"_G]G<80``OYF8_T"F +M"?0;(<3Y`?0+&]T$$!`!O]_9^&````X!()Y)__?]^02@WP\$V1`0$`&@G_M% +M#)BO",?Y&O0;![VD^`"8J0?>____!\?_E;;T&_V>!/WY!;6O!WY`"0#X`/DB +M"?#'K.C]N02XL0`@`+/``U^PQ@/T#`NSP``7/L6[`+/)!3@!L\`&2+V4/D>\ +M`/"D_[.@!1VSH`D-LZT$^P$^Y;L`"00^[KL`/90^[KL`$-D!WYP6``#PE/^\ +MF9"\GY`8GP$0_P$UGP$^T;T`O>0)$OZ>#/0R$O0R$O0R$K/D`0O9*%H``*"> +MF!D(C___]_V?!+49"+/D`1"]]-DH6@``H)_T,1*8&0''F4.SP`,9L,8#]0V! +M`;/)!:(`L\T&>`$^M;P`\)0#LY`#!O@(F!P(Q\D1]0MB`8 +M'0;?____!\?)E?WO!+:4&_V>!8\```JU&0?9__\!\/_)E/V?!;49"-G___\` +M_=D$M1T&/M&]`/"4`[.0`P;X"+T$"1+^D`ST,A+T,A+T,A*S!`$+V2A:``"@ +MD+(:?D20`+,-`?(`O?39*%H``*"?]#$2/M&]`)@?!I@9`97R&,>9([.4`2*S +M(!`>LR`2&K,@%!:8&0;?____`/V?!+49!C[1O0"]Y`D2_IX,]#(2]#(2]#(2 +ML^0!"]DH6@``H)Z8&0B/___W_9\$M1D(L^0!$+WTV2A:``"@G_0Q$K,@$'>] +M!`D2_I`,]#(2]#(2]#(2LP0!"]DH6@``H)"R&GY$D`"S!`$0O?39*%H``*"? +M]#$2LR`20K(:?CL%`+,D%!*_&0_X_9\$\)4$/L&]`)@9`<>9([.0`P;X"+\9 +M#_C]GP3PE0*@&;(:"P%^G`@`/M&]`/@(^R&8KPCY`K*@Q_D:]`M,Q_D;]`M& +MF*X-F*P'F*T*F*L)B0``,/WI!=G___\'\;3___W)!,?_E8D``/^V]!O]V03] +M_`7]VP6UK@VUKP>UK0I^0`D`/DN^`,?Y&_0+'5@+$K(*?JY!`+\)\)0'LY0" +M#+(*"P%^G`@`O:3[`?DR"0?$O_^RL;R?,K*B"?#'N^C_R92XD``@`+.Y!IP` +ML+8&]`P6L[D#RP"SN047`;.]`@<"/IF^`+.Y"FD!L[D+=`&SO0?T`3X+P`"] +ME*#IV2P9```_F3.0`!"R&K(K?ID+`#Z&P`"R&K(K?B^Z`+.M`,H!T#X:``#< +M`"```#P"&)C*`=O@&0``V3L:``!_OCR2V`D!O)/T\>4``;N=!/#T__V:!3G_ +M`+7)`?WQ!&"^/`\I/H;``-DL&0``/YDSF0`B`9@/"L?Y6/0;/9BO0+#;(*?M.]`#XIP`"R"GYQNP"SK0`5`9@)"-\` +M```(_9\%C___[_V?!+4)"#XMP`#9+!D``#^9,YD`EP"8#PK'^1?T"PL)`:#I +M/BW``,?Y6/0+";(*?GX)`+\)F`\&#OC]G@3PE0*@";;U&+/T%`S]G@3PE02@ +M"9@/"(G__^^R"@L!_?D$M0\(?IP(`#XMP`"RR[(:LMRR+7[W!P`^AL``LCJR +M*WZ1"@`^AL``V2P9```_F3.0`'28"0K'F5CT&P7X"+(*"P=^?@D`LZ0`7=DL +M&0``/YDSD``1F`D(C___]_V?!+4)"+`V`?0-!?@(WC@:```\XO@)`;N3!/WY +M!3SO*;,T``W9'QH``#YRP`#9)1H``+PIH#^I,Y``#1*9`2"I/H;``/@(^S&] +ME/0PX/F"L)$0V2`0$`&]-+^8O:39\!D``+"1#[.)`/8`WSL:``"\/Y`_F0\! +MN_D$_X^4]0O.`+20#[^2N?D`O?3]B02P\0V0*82P\0Z0+XBPD0RP\0N0*8R0 +M+Y"0)("8(""PD0JP\0D^:<$`M)`,M/`+OY&_]K20"K3P";^5O_=^404`Y0D` +M`:!)Q!G_DID&L)8!]`P>LANR;+)=LCK^3@&0[D!^3;X`"0&PD0T^6\$`QQ#H +MLP`$&+,`"12R&K)KLGRR/7Z;NP"S!``*OT`^:<$`OT"T\`ZS\`$1"0&PD0ZR +M*L0)`?0;A[3P#0H!L_``%+2P$+(Z?LL#`+V4"@&PD1"T\`^0,P&0_P2P\0^S +M/0,/__N%('^IW^`9``#QE0"`8*E_^?"50&#Y^`#91!H0`;^?^3+9L!8``-,P +M&A`!OYS$^P?2-!H0`=$X&A`!T#P:$`$^*L(`&,X66,T*V@````;PY/_PTP#' +MZ0+'[P&VE!VV]![]GP7]G06@.;_)\.0!H"F8R0'PE/^@&;/@``G:````!)C) +M`IC,!I*[`?^IE:`)L\``"+.T`+'9L!8``*"<^S'Y4G+4LJ*RL[+!LN7$20_T +M&S/$J0_T&RU)`/__N93T&R3$R0_T&QZQQO\?]`T7VK06``#;N!8``'XD@0"R +MH+.D``SX"+VD/LG"`*"BM:,!M)`'=:0*M:4#VZP6``"UJ00TD""R##6I%K@9 +M`"`"M:D"VJ@6``!^#($`W[`6``"_^0H!LY0`#*#P?K3!``H!^U'Y8K*BLZ0` +M5=F\%@``OYFSE``D/B3#`)@)`[.0``F8"@3YE;(,VK06``#;N!8``'X,@0#; +MP!8``-J\%@``?B2!`+*@LZ0`U-F\%@``OY^S]``+V81<``"@G]E`&A`!OY&P +M%@#T'G6]E#[DPP"@-MJH%@``VZP6``!^)($`LJ"SI``&^`B8#P+_%93T"P7X +M"/\4E*:?]`L%^`BS(``-&`D6QYD#]`L?F`D#LY``"9@*!/F5L@S:M!8``-NX +M%@``/IG#`+(,VKP6``#;P!8``'X,@0"_,3ZSPP"RD]8```!`U0````&$\/\# +ML!8`]!Z!V;`6``"_F;.0``A^M,$`V;P6``"_F=^$7```LY``#`D!H/D^Y,,` +MH/D)`;*:^V&]E)B>$*:N]`@6F)\1IJ_T#`Z2J0&\FY"FG_0("?@("@?X`+RN +MDM^<&@``MI4(//F8Q)K_Q*D!,Y``#,>I!@H#]`L%"@7X`-W@&0``W-!E``!_ +MWUC.'-D`!```F)D/\?4`!/'E`(!@WW7.'/&4``'T"P<)1"#)^`#X`/CX^/CX +M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +M^/CX^/CX^/CX^/CX^/CX^/CX^``````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````/@`V@`@``!+L`!^OS<`V;`@``#>`"```+7I$MF^30``M>D.V;I-``"U +MZ0_9P"```+7I$-D`(0``M>D1V10$``#?`+8!`+7I&]F>NP$`NY\"WS1<``"@ +M^0D!W?`9``"@Z=SJ8```20`!M>D:O>0_R3.0``BSX``0O]^8^2#QE0"`M?D@ +MD.X!D-T$L^0#Y/@`"?"[RP*0S`_]R039````0/W)!=DP&A`!H)R2F2R_F?0P +M_+B[`"`"CO#_`[RIH-DT&A`!H)J2F2R_GY"9,/^^Y-Q`&A`!\/3_H)_9```` +M!@]D_>D%_DT!V3P:$`&@GCX`QP"2_P&S]`$,O\F@V3[QQ@"S]`#QO\F@V;_9 +ML)8`]!X)#V0^\<8`Y^FD`;:4!*:;]`L%^`C9````0-]`&A`!_^F5H/GT,`3X +M`/D"LJ!^(]X`?IC>`'Y>W@!^'0"$``+7I0=EP(@``M>DQV;`B``"UZ4+9 +M\"(``+7I0[V4WV`B``"U^0.@^;7Y`;7Y`@D!W?`9``"UZ13E` +MO>0_R3.0``BSX``0O]^8^4#QE0`!M?E`D.X!D-T$L^0#Y/@`^6+:`",``$O` +M$WX<.`#9P1,!`-\`(P``M?DCV;$"`0"U^2397"(!`+7Y)=D"*0$`M?DFV2(T +M`0"U^2?9`B`!`+7Y*-D"&0$`M?DIV0(=`0"U^2H)`;7Y`@D+W@`,`0"U^0C9 +M618!`+N>`K7Y&@D,W0#P``"U^0G9;@L!`+N=`K7Y&PD*W``B`0"U^0K9PB@! +M`+N<`K7Y'`D.VP`I`0"U^0O9-2H!`+N;`K7Y'0D/V@`K`0"U^0S9R#0!`+N: +M`K7Y'@D1T``@`0"U^0W9<"$!`+N0`K7Y'PD-T0`7`0"U^0[99AP!`+N1`K7Y +M(`D0T@`=`0"U^0_9U1\!`+N2`K7^$;7]$K7Y(;7\$PDQM?L4M?H5M?`6M?$7 +MM?(8M?D0V00@``&_G=D"40$`W@!1`0"U^2NU_AG9DU$!`+7]A+N>`K7Y(C#6 +M)/0-!?@(Y]E(`;"6`?0-!?@(E=D8L)8(]`T%^`C9`#L!`-\0!@``M?D)V0`\ +M`0"U^0O9`$H!`+7Y#-D`3@$`M?D-V0`U`0"U^0[9`$0!`+7Y#]D`10$`6/T2 +MM?D0V0!&`0!8_!:U^1'9`$=>D)V4(\`0![G`)8\B!UZ0O9R$H!`'N;`ECS +M(G7I#-D'3P$`>YH"6/0D=>D-V2Y("=>D0V4-&`0![DP)UZ1'9-4Y4"=>D3 +MV35)`0![E@)UZ139`#T!`+7Y%=D`/@$`M?D6V0`_`0"U^1?9`$`!`+7Y&-D` +M00$`6/TJM?D9V0!"`0!8_"RU^1K9`$,!`%C[+K7Y&]D`2P$`6/HPM?DYP"6/(V=>D6V8L_`0![FP)8 +M\SIUZ1=8_SC9-4`!`'N:`G7I&-EL00$`>Y`"=>D9V35"`0![D0)UZ1K9L4,! +M`'N2`G7I&]DS3`$`>Y\"=>D@_'U`("@W_@`VL`V``!+\`!^ +MOS<`WRP$``#9P#8``+6?&=^P-P``M9\)W_`W``"UGQK?T`8``+6?&P\!H)\/ +M$+6?&/@`WP`$```)`37Y>-X[&@``-?G"-?G!/90@Z37YP`D"-?F("0@UZ0$) +M`S7YF`D0->D"^`#Y$MH05@``2X``?APX`-D05@``T,!5``"U"32U"35)`AC? +M@%8``-$0-@``M?D#H/$)`=K`5@``-0G8"T!^'#@`"0&U"4#9)@```K4)00D( +MM0E$B0``#/`5`;4)1HD``#BU`4*U"4H)!+4)3OL1^4+:P%4``$M``GX<.`#9 +MP%4````!M9`+M9`#M9`%M9`(M9`)?N+,`#V4WQ!8```U^08U^00U^04)"7VT +MW,!>``#=$%\```$"TM!>```U\!$U\`$U\`XUT`0UT`4U\0\UT0$UP00UP08@ +MR37Y!R#9`P,URP@U\Q`URP(URP,URPD"20`$=2D" +M=L#-?,"=?D"==L"2?\' +M=>L"=?D$^T'9J!8``+WTH)_9K!8``*"?V;`6``"@G]F\%@``H)_9P!8``*"? +MV81<``#Y,J"?T+@6``#1M!8``*`/H!_:Q!8``$LP`GX<.`#9Q!8``-+@%@`` +MH`G3]!@``*`9LBS:M!8``)`B'-NX%@``?@R!`*8C]!OK^S'=`)\!`-^$8``` +MV0"C`0"U_0+>`*$!`-T`I@$`H/FU_@.U_0'9`)T!`-X`EP$`W0"/`0"U^039 +M;&```*">M9T!W@"2`0#=`)H!`+6>`[6=`MZ<8```W0!2`0"@[7_L?YM8F@+Y +M8EB2!%B0!MG@8```6/8"?_%8\P18]`98]0@]]""?V=J(`0![G`+?[&```&#Y +MV0N9`0![FP+>U&```&#IV5&1`0![F@)UZ0'9JY8!`'N0`G7I`]DQG`$`>Y(" +M=>D"V0VE`0![D0+=7&``` V3^@`0![DP)UV0+9!*(!`'N4`G79`]FY4"==D$V>^F`0![E@)UV0'[8;WT]#"P^8+^0`&0`'"@#_Y)`9"9;*"?DID$ +MH)^2F02@G]D\%``!OYFPH0E+P`':0%@``/"4`3"1.]GN8```()_9H&```""? +MV=!@``"@G]FP8```H)_9K&```&"?V6A@``!@G]GH8```8)\8_W79R&````<$ +M!@$@GWX<.`#:,%@```L0?APX`-DQ&0``/YG<15@``+W4U1`4``'$FO_;%!0` +M`=-4%@`!TO____V$```0T4@6``$@QMZX8```O-Z0(),+/T +M`"V@7TD`$*"YOSF@";\)_9($H`F_":`YH+2_&:`)OPG]D@2@";\)H!F@OY#) +M`Z"?D,PXL]0(A]DP&0``/YS=$!0``0D!H-F]Y-D4%``!H)X/#[B9#`(`H)_^ +M2`'^10'^00'^1P'^0P&@WA+$`3TDUNI@``"0B&B056"0$6R0=V20,W`^:-,` +MQ$#_E`D&E`\#O)_2"03<0%@``+S\$H#Z_/KP`\+N?`@\!H,ZVE`+<1%@``+R +M.!D``+SMF+.0`#.4#@.4"0;<0%@``+N>`KR\Z?"_^8S`(@*\W-#<"&`1`:")OXF\[.#<````SK;4!_V< +M!*!9OUG<``#_`,0J_XM!?@7]G`6@6;]9\95?#*!9OUF@^;_93Q_^H!F_&?V? +M!/"5H*`9OQGQE0`"H!F_&?"5$*`9O^F@>;]YH.F_&:#9?B5J`)0.`Y0)!MU` +M6```NYX"O)V0#@*@GKP`D)0/!-Y$6```N_D""0.V]`*\_O`U^0$^8M,`/VDS +ME``+Q"K_?EEJ`!`B`1!$`=\N&0``/_DF*?4()?[9,1D``#^?-)`[,Y0`$[W$ +ML,$/L,$0L,$1/K#3`-EX%``!OYFPD0_9?!0``;^9L)$0V8`4``&_F;"1$1+_ +M`3W4_D8!_D@!_D`J!_MI0"H*&\ +MG)`/`3[^U`"2V06PE@'U#-$`OXGPE8"@B;.T!2R_?@\"H*^\1/"4203PY8"[ +MGP+=1%@``+:4`J!^O)V0#P,UGP$^[]8`L+8#]`T(L[T/X@&_>8Y"`A"\3D"4 +M2@3PE;V@>;^IC[[][[Q/0)1+`Z!9OU])'_Z430:[VP+]^03_/_6@7[]9WT!8 +M``"\W]"\1/#PE0&@6;]9E$X$N^\"WT18``#PE0*@6;]9MN0"O._@3__#E`P* +M_9\$_D!"0$UV0_9)````;^9D)D!M=D)/N_6`+/= +M!X4`L[`'!O@(OWF,0@(0O$Q`E$P$\)4@H'F_B8V^_>^\34"\1/#PE2"@B;_) +ME$X$N^\"WT18``"@6;]9MN0"O._@3Q_^_9\$\)7@H%F_691-`Y1/!KO]`MU` +M6```\)4!O/WPH%F_70D!H/D)!Z#-->D!V20```&_F9"9`;7Y"3[OU@"PU@/T +M#0BSW0_#`)1)!KQ$\)1+`[R;PI1)!+N?`M]$6```MI0"O)^0#P?"5@*!YOX\)"*#)B;[][_'U +M#8"\24"@C[_I3Q_^H%F_6?V?!/\IE:!9OUE/_\/PE0*@6;]9\)4!H%F_6?V? +M!/&5``R@6;]9H.G9)````;^9D)D!MV409``!@G]DH&0``H)_9+!D``"">V2T9```@GMD$6@``H)_9"%H``*"? +MV0Q:``"@G]D06@``H)_9%%H``*"?V1A:``"@G]D<6@``H)_9(%H``*"?V25: +M``!]U""=V21:```@G=DH6@``H)_9?!H``*"?V8`:``"@G]E(&0``H)_9Z&$` +M`*"?V=QA``"@G]GX8```()W93!D``&"?V?QA``"@G]D(80``H)_9V&$``*"? +MV0!A``"@G]G$8```H)_9H6```""=#/[9(````:"\!M>\"D)D$#@&@GMG@&0``8)_9Y!D``*"?V5@9``"@G]E<&0``H)_9!&$` +M`&"?V?IA``!@G]DP6P``()W9,5L``""=V?!@```@G=GL&0``()W9>!H``""= +MV60:```@G=EE&@``()W9%!H``*"?V1@:``"@G]DB&@``()W9)1H``""=V4Q; +M``"@G]E06P``H)_9=!H``+W4H)^]Y-GL80``/;2@G[W$L]0"#=\`0!$!/AG: +M`+/4``W?```1`3X9V@#?`"`1`=KP&0``O.J0H)_?.!H``+S?D-H^&@``()N\ +MVI#?_!D``"";O.^0V@@:``"@G+SJD-\<&@``H)R\WY#:'QH``""3?P$D``*">D)E`II_T +M&_G?,%H``+WDO=2@_;7]`;7]`I#N`93I`_&4^`.U^0.0_Q"SY!#HWC!:``"8 +M[S_93AD``'6=`V"==9T!=9T"V>1A``#Q]?@#H)W9_&```+7O/P]_H)_9]&`` +M`#WTH)W>IA8``-F<%@``()\UGP&0F0*FGO0;]MF(7```()_X`-X``A`!O^E/ +M__'=!`(0`=P(`A`!\94/`?V?!*#IO]F0[A#;%`(0`;WT\97_`:#9O\G:&`(0 +M`9#=&/&5/Q"@R;_I&/]T\)4'H.F_N?&5,?.@N;^I\)4'H*F_V?&5$0.@V=E@ +M`A`!OYG%G@8S\``-"?[_Z?0^#=P`Q9\'V6`"$`&@G_@`V0!:``#Y`KT$H)#9 +M`!D``*"0V009``"@D-D(&0``H)#9#!D``*"0V1`9``"@D-D@&0``H)#9'!D` +M`*"0V1@9``"@D-F)7```()#9,%P``""0V31<``"@D'X6SP#?C%P``-D`K@$` +MH/E__]X`X0$`V41@``"@GG^>V?FU`0![GP+?DEP``&#YV9!<```@D-DS`0(` +M>YX"WT!@``!@^=GV7@``()#[`?D"VFAF```+3'Z_-P#?[(H!`-EH9@``M9\2 +MWU:*`0"UGP7?<8H!`+6?!M^,B@$`M9\'WR:,`0"UGPC?.HX!`+6?"M]QC@$` +MM9\+WU>,`0"UGP3?&HT!`+6?#=];C@$`M9\.#P&@G]ED9@``/=0@G=FT9@`` +M()W9P&```+WDC\#4`:">V>1@``"@GMFD8```H)^8[Q_9J&```-HX&0``"PB@ +MG]G,8```H)[9M&```*">V5A@``"@GMGJ8```()[9-!D``"">?K\W`-I`&0`` +M"P)^OS<`VD(9```+`GZ_-P#9&"8``;^VC(9```RV=`S&0``)LWT&`\2F0$@K#R>D#[N +MW0`2R0$@K3R?D"`)V0!8```]]""?V109``"]Y-\`O`$`H)[98&8``"">V;C@ +M`0![GP+?$F(``&#Y?J'.`/L!]##\O=3^3@&@[0\!V1`4``&@GY"9!-P$%@`! +MH)V_R4\`_Z#IO^G]GP2@Z;_I\)4?H.F_Z:#)]#`$^`#T,/R]U/Y.`:#M#P'9 +M$!0``:"?D)D$W`@6``&@G;_)#_B@Z;_I_9\$H.F_Z?"5!:#IO^F@R?0P!/@` +M]##\O=3^3@&@[0\!V1`4``&@GY"9!-P0%@`!H)V_R0_]H.F_Z?V?!*#IO^E/ +M?__]GP2@Z;_IWP``A`'QE/__H.F_Z?V?!:#IO^F@R?0P!/@`V<1E``#;0&(` +M`/0P_*";VM!E``!+D`!^'#@`#0'<"!8``=D0%``!H)V_S_Y.`=G090``VT!< +M``"@[[_O()VUFQG9````!/WY!:#OO^G?````$/V?!:#IO^F@R?0P!/@`]#(2 +M]#(1]#(0C___`-D4```!H)^2F1"@G[WTD)DDH)\/`I*9#*"?DID,WB04``&@ +MG[_I#_?]GP2@Z=D$;P``_I``^`#$J0+T"QOYD^HN$`H.^_Z>6?``'PE`'T&_6]I+VTO<1^CDH`?DG?`'YH%^_6=^`&@``O__QE/__H%FF[_0+(GYT%`#?2!D``+_YLY0!$KV4H/E/ +M#0[9!!`0`:"?O02_6?"4(/0+*=D8&A`!OYFPE@#T'P=^T4<`V4`:$`&_F;"6 +M`/0?";VD?LO"`+T$V>`9``!_F?"4`?0+"7X`.@"]!-&A8```/QDSD``;"OY^ +M*6X`L:;',O0-"SV4(!E^30T`O039T&```+^9LY``#GXR)0"SH``&O0398&8` +M`#^9,YT`Q0"_6?&4@`'U"[H`T.!@```_";WTH$_PE`'T&SS9G&```+^=V>Q@ +M``!_F]\````1LMJP00#]U@3PLP#]WP4,$=Z^(P``?H9'`+])LY0`"S\)\)4! +M(`F_2;.4`TQ^6W@!V9Q@``"_G=GL8```?YO9````(;+:L$$`_=8$\+,`_=D% +M#"'>OB,``'Z&1P"_2;.0`AK?X&```#_YO03PE/T@^3YYY`"SE`(6W^`9``!_ +M^;T$\)4@8/D^>>0`LY0'!O@(O039X!D``'^9\90`!/4+M0#18&8``#\9O?2@ +M3\2?_\?Y`O0+8MD`!```F)D/\)3`,Y0`!O@(V1)B``!_F[*-L$$`V@"\`0`, +M(?"S`-Z)3```?H9'`+])W>`9``"SE`(0?]GQE0`$8-D^+>4`?]G>8&8``#_O +M\93_^V#9\/3Y(.\^+>4`Q/D!]!LOV1)B``!_F]H`O`$`L$$`#!'PLP"R?=Z) +M3```?H9'`+])LY0`"S\9\)4!(!F_2;.4`PI^`+P!O01^7U``V6AF``"8F0*S +MD``&O03=X!D``'_>Y.D`"/0+&ME88```OY_DZ?_W8-FS\``(?C9/`+T$OUGP +ME`+T"P=^VGX`V>`9``!_F?"40/0+#7XE:0"SH``&O039-````;^9LY0`!O@( +MTS0```'2`,J:.Z`RD``!L`8%]`TMT#@```&]%*`!?HI``*`R"0'?*!D``*`) +MH/E^$'``V2A:``"@D?0Q$KT$V>@9``"_F?"4`?0+"0H!/@+F`-GL&0``/YGP +ME`;U"^G\O:3T,`3[A0C>,``0`;_I#_[=)"```?V?!`_+\)4"_9\$H.F_V4_W +M]Y#N-/V?!*#9O^G?````0/V?!:#I^`#9+AD``/0P[/F"/Y_9,!D``#^9BT$" +M$+W4\/3_\)3_O)N0E)($LBX^AN8`O^G;0!D``+S;P)#=`<>9!/0;"K_I\)0! +M(,F0[A"FW_0(X=G(8```/YX/#]D$!!`!H)\/`Y"9"*"?D)D(H)_PY/_$Z0'T +M"PN/#P`//KSF`(\.``[$Z0+T&PJ)_?_]_?D$W`@$$`&@STG_#]T0!!`!H-G? +M&`00`:#YV1P$$`&_GK+TLL;^3P'PY0&@GI#_-$F($[+5LOJ@^=,$!!`!T0P$ +M$`'0%`00`3XQYP"_.[\9OP^_;K]=OTS]FP7]GP7]G@7]G07_G.7T"PZ_KY+Y +M`:"IL_0`V_Y)`9"9-+^9LY``"+/@``;X"-\`!!`!"0'^30&R_*#Y#F20W20/ +M9)+_`;/T`0R_R:#9/F/G`+/T`/&_R:#9O]GPE`$SD``.DNX!]!O;/L?G`+/@ +M`#H$`?Y``?Y*`?Y,`=LX&0``O=3>!&`1`=@N&0``D``HD*HLAP``_T,?_H8` +M`""0S#`R13X_Z`#X"#Z1YP"8Z0&@";\)\)0/LY0$$M]"&0``O-^0()4^,^@` +MH+2_Z:"IOZG]EP3QE5\,H*F_J:#I/_F_+_"4`?"5$/V?!?V3!/"5H*`IH`:_ +M";7I`;\9H,F_R?V3!/"5H*#)O\GPE1"@R;_)H!F0W0&0NP20[H"0(A#90!D` +M`+S9\#^)DN$$\)3_IMGU"'S_/?39-!D``""?^X44^``````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````^``````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````+^_]##X +M^7+T,/C^20&0F2R@G[*SL_0`!O@(V=]0`0#?`%`!`+R?0MG___\`_?D$V0`` +M`"'^0@'_^67^1P'9````$;VD__E5D"(LD']#$2/KOM`-``(P``F`HMF`LNO90P$02P +MD0#?OI%`+.D`@J@ +M(3Z[[0#9`%`!`+4!`[4)!`D(H#D^R>T`T``C``"8"6O'F:JSE`83LBI^+^\` +MORZU#@,^N^T`LBK;P#4``+)\?M/M`+]YLY``"`D%H"F_+M\`(P``F/EKM?X# +MQYFJLYT)/0'?T*L``#V4L/$`,)$$LDM]Q`TALF[:`%`!`'[Z10`^N^T`V<`U +M``"_G]G$-0``OYG0`",``+;T&)@.+;4/;I@/+K:4&/&5`(2U#FRU"6^U#VW: +ML"0``'VTW``$``!^`#X`"0DSK0#0`)@)+0\&M0\#H"^0F1"U"2T^N^T`V@`$ +M``"_J^2Y`$#U"[$`W>`9``!_V=X`(P``&.P8#P+QE/W_H"]@V;7O`TG_O_^Y +ME*"I,\D`B0`)&-_`-0``H/D)"CZY[0#9P#4``+^9T``C``"8#RZ8#BVVE!BU +M"6X]E+4/;34)&+4.;-DX(``!O?2@GXD`A`#:L"0``+4);WVTW``$``!^`#X` +M"0LSI``KW>`9``!_V=P`!```O\X/`?&4_?^U#P-@V:`O2?^__>D$H,X^N^T` +MM0D#H"FR&K\AIJ'U&Y#\H#JRJ;*:]#`(^W4(^`#>`",``)CO:_E2#0$]E)7T +M&-7$-0``M>V)->D9H%2RH[*RLL''\*JP!A'T#"VP!@[T&'VS``MPL`8+]`P0 +MLP`)1[,-"A$!/H#N`+,`#$RS#0T$`3YV[@"S"1:P`+`&%O0,#+,-%?``/N3N +M`+,`%PVS#3'C`#[N[@"@O;V4H,V@63XM[P"RNGX`4`$)!K.@`7.@,#[4[@#' +M^0GT&Q0U[1D^@.X`#P'9`",``#6?&;)*?GFK`+.D`![9`",``)B9:P\+H"_' +MF:JSG1&0``D3/B?O`-X@(P``O?2_Z9#N!*:0]!L5V0`C``"UGP>P]@CT#1`^ +MSNX`D/\!L_0)X?@("16@.;V4/BOO`+V4H,D)#3X?[P"]E*#)"0X^'^\`WB`C +M``"]]+_ID.X$LY0Q%MD`(P``M9\'L/8(]`T0/A?O`)#_`;/T">+X"+V4H!D) +M#*`Y/BWO``D%H"D)`:`9^U'Y$M&@)```F!\#"0*@J;*@Q_\%]`M#V0`C``"8 +MGRW:L"0``'VTW``$``"UGVR8GRZUGVW?`````;6?;H\`A`"UGV]^`#X`,Z`` +M#`D$H`D^K^\`"0:@";\9F!X#F!$!W0`C```/P/V?!+71+K79+;*+.P`W:S,`$( +ML[0`;K/P`'#'F?"PE@_T#&"8`@25+Q#T&R>0NP''JNB0J@%^A&X`LAM^A&X` +MY"G__^2O__^VI!#]J06U"@2S-`,5L?8!#/"<"/"6`<::`3[\\`"S-`$A/>2) +M`,``IOGT#04R/L;I`<2:_S[\\`"]I#[\\``*`?LQOZGY$IBO`;*@QYDH]1NP +M`,?^0\?]Z/0+%\3I`[.9`J``L^D$FP"PU@+U#),`E?D0]!L=\?3__[/D!`R) +M``!`/D7Q`(D```'_^96U"0&8#0'$Z0.5VQ"SE`,+L;8`!/0,7K/D!`BSM$!7 +MLY0!"[&V``3T#$O$Z0$*`?0+1;\)QYGPL)8/]`PXF`$$E1\0]!L>Q]KHD*H! +M?H1N`.09___DK___MJ00_:D%M0H$L?8!#/"<"/"6`<::`3Z\\0"]I/L1F*\! +M^1*RH,?YZ/4;KP"_J<>9*/4;I@#'_D.5^1#T&QWQ]/__L^0$#(D``$`^\O$` +MB0```?_YE;4)`9@*`<3O`Y6K$+/P`PBSY`0+L;9``/0,:K/T`0^QM@`$]`T2 +M/G?R`+/T`@NQMD``]`Q0Q.D!]`M0OPG'F?"PE@+T#3^S]`$.L)82]`T1/G?R +M`+/T`PJPE@KT#">8`025&1#T&R3'JNB0J@%^A&X`Y!G__[:D$/VI!;4*!#Y] +M\@"]I#Y_\@`*`?L1F*\!^1*RH,?^0\3I`[.4`W3'^>CT&VV_J<>9*/0;997Y +M$/0;'?'T__^SY`0,B0``"#ZZ\@")```!__F5M0D!F`\!E?L0L+8(]`PYOPG' +MF?"2F0.PE@?T#"N8`00*`949$/0;(L?ZZ)"J`7Z$;@#D&?__MJ00_:D%M0H$ +M"@$^!/,`O:3[$?F"T$`N```#`M@``/``U___#__6@"T``-40(``!/A;T`-^$ +M+0``O_D$`;M#!/])E/4+V@"8#P'$/@''\D,SX``*,"8$]`T-L^0`$#`F!/0- +M"?@(/BST`-\`(P``F/F@QY%TLQ0$#K(*?@+P`#Z<\P"S%`,.L@I^_O``/ISS +M`+,4`0ZR"GZ^\0`^G/,`LQ0"#[(*?H'R`+.I`)``VH`E``!^4%,`F`D,MJ04 +M_:@$_9<$_:D%M0H,OVG_293T&Q&_"?"4!_0+"0H(/B[T`+\.Q^V*]`LYQ"D# +MLY0"3[,4!$N_7\?I#\?^;+.0``VFWO0-'3XL]`#$^8`SE``OLNFPY@?T#04) +M!Z;9]`P?D#,!D`!`W\`M``"_^;:5&Z8Y]0T%_PH!/B[T``H1^X'Y$MP`)@`` +M#0+1P"T````!VH0M``#;@"T``#Y\]`"_J9#=`?_YE+.4`2._OO_^E/0;&K_) +M_?X%\)0']`L/LY`#"@H3/HOT`*"_D,Q`OQF\#?2VE1NFV?0-R`H!^Q%^QE0` +M^`#>`",``)CII/F",I:SH``OQ&G_W_P-``"4E`*4DP*\3T#9"`X``-&4%``` +MO#DPO20]A-<`(P``/C_V`-F`+0``OY_$:?_10"X``)24`I23`I7R`MD(#@`` +MW_P-``"\.3"\3T!%_^]]A#UT/K+U`,0I`?4+J`"8'PG'^0ST"PG_]92U&0F8 +M&0$S8```+WT\*3_MJ0#F`D%O)J0O)^0-9=)D/\! +ML_0(\9@9"?V5!+49";8E`9`10+,M`$__/J/T`%@9`@__9I_T&W>_%9A9`3-@ +M`!>8>:(SD``*LCH^^/4`LDH^^/4`QYE#,)8#]`T,VO@-```^^/4`VOP-``!8 +M&P.]Q`W_\+,`?OY8`+*@LZ``,9BI!7WT=:\)LY``);):?H=>`+WT\*3_MJ0# +MF`D%O)J0O)^0-9A)D/\!L_0(\9`B`9`1$-^8#0``/_GPE/^F*?4(=0\39`?4+M@#?E!0` +M`#WD/L'V`+_YD/\0IIOT"PL0[@$FX/0(\;-```XS%``*,-8$]`P2LSD`A``S +M%``*,-8$]`QX\.3_W904``"4Z02\G9"@F[^_O.Z0W9P4``"VE`/'__"\G9`@ +MGS,0`@BS4``7$O\#O.Z0W9P4``"VE`.\G9`@G]^<%```O.Z0E)T#O-_0&-\! +ME.D$WI@4``"\GI!@EW6<`?#T`?0+"C7<`3Y;]P`0``$^6_<`$"(!MJ4!D+M` +MLZT`-/_^20':0#@``)"9)[W$()*])+^ILYD`S@"8J0'?0#@``)3+!IBN"+R_ +ML,>?0YB]#<3Y`?4+KP#'Z6@F&?4;I@#$V?_PG`OPE@&F6?4;EP"S0``.,Q0` +M"C#V!/0,$K,Y`(4`,Q0`"C#V!/0,>9B_"24G`,^&OH`Q+D!]0N(`)@]!;S\!CY23.4`!88_P$S]``&^`B\ +MW)"\GI`UGTFS0``QF#\%L::[`/0-%KS\\+S^\!CY29*JO!*91#[\^0"\_/"\ +M_O`8^4D\FI`^#_H`F#\%L::[`/0-&;S\\+S^\!CY29*JO!"91#7Y23X4^@"\ +M_/"\_O`8^4D[F@(U^4F]I)#N`;:U`;.P``FSK0!K__M!V8`M``#?`",``/0P +MZ/F"OY"8^:2PX0G?_`T``+"A##"1-_"4_[*VE)X"E)@"O._@V0@.``"PP0NP +MT0J5!0*PX0Z\B8#4`"8```<"/A3\`,19`?4+E`&TX`R83P&_ZJ5^^7L`LJ&SI``&^`B8&0FR"KW$#?_'F824GP6VE`*[^0+9]`T` +M`+SY\%C[`?"S`'[^6`"RH+.@`$98J0ESE``*6*X(=:X)WP`C``"8^:*8&@0S +ME``+E:(0/N+[`+(:?K2!`+(;LJ*]Q+(*?D?Y`%@)"7N2`G4)"3[Q^P#X")@9 +M"?&5`!"U&0FS-`$0O>39*%H``*">]#$2ME4!D'"`X``/"4_Y2:`K:4`KRKH+R>D##Q7["A'+"1&[WT"0<]I+#! +M#;#1#--`+@``L/$2L)$3,*%G/MT!`;20%O"4`?4+.P6TL`Z8/P&_NT$O?39*%H``*"?]#$2/MH! +M`;\Y-*!?MI40,)%4,Z`"%MD`(P``F)FB,Y0`"KVT/B[]`#2P5!*[`S"Q5`L! +MLCI^R($`-.!?,^``3[3P'S_Y$)D!(/DQED8`]!T.M*`/"0>@J3YM`0&TL`W? +M`",``)C_HK^YO)J0H+DS\``3M.`;#P&P\1*PX1@^ROT`M)`P!$+D!VI@-```@ +MJ3XN`@%0R0%@&7\;Y+G__Z:4]1XS_SX&`0&TH!BR.[W4?J%>`+.M`?T!LCI^ +MM($`S:B\S*2\LX0`"TB\`#X'_P"01`'^20&0F79_GY)+`;V4?61V]0.PL0ER +M_G#Q*?#C`+#A"C[W_P!T`#NTH!BTP`JR._`#`+Q0`+(-?BB8`/`$!Y`)`0\! +MTI04``"[^02RH0D!L/$0NY`$O02PD1H^R?\`6"D""O]FFO0;5Q@I"?"4`?0+ +M3A@I"%@O`[3@"@L!O+F4\/,`_^F=II_T&S6_*9B9"L>?Z+20&OV?!/0+)+20 +M$/V?!/0;#K(Z?K2!`+.NO``,D!&\/L/_`,VIO+P9$)```9`B$-^8#0``/_GP +ME/^F"?0(D+20":99]!L*O!B@/NK_`)`:O+&FO`#U#/(`4&8!"0'D9?__IE3U +M""[_LYD`Y`#^20&8/P&0F79_F9@]"L2:!\?Y0[.4`2N/_P#__]_TNY0$DID! +MNYH$MI0(\93___V?!4\`__V?!+4Y"CZ*``$.`;SJE+:4"/&4__^/_P#__]_T +M_Y_5D$D"M3T*N^D$D*D!DNX!O.F4L9;_`/0-"K.@``?PE0'$G_])`/__V93] +M^06U/PK:F`T``#^L-)!4VYP4``#:E!0``,3._[SN\+;T`[S[\!C]`2#YE.D$ +MO)J0\-4!-?T!=/`IH).VY`3;F!0```G_O.O@=>\!8.D0S`':F`T``""L/BX" +M`0LCL+$3_D\!D/]V?_E0F0%@^?Y,`;3@$9#,=G_)\),`II[U'MO]M)`3/F@! +M`=D`(P``-*!4F)FAY)W__S.@`#/,WGV4[P*4Z0>[GP*\GI"FG?0+!I#N`32P +M5`D!NYL$INGT#5L)';3@#Z#I/FT!`9@Y!(_226NVE1#_GYP/<+OY`J;]]!@Y +M"1VT\`^@^;-]`;H`O?39*%H``*"?]#$2/B<"`3207S.4`1>8.0''F>BSE`(- +M-*!G$*H!,*%GLW0!$+WTV2A:``"@G_0Q$K2P'[3@"S^_/^GP\@?PD@>\^?"Q +M]D8`]!T.M/`/"0>@^3XG`@&TD!:VE0&PD1:0,T"TH!:SK0"P^C2P9S.P`#39 +MB%P``#^>,^0`'-D0%``!H)I/``&0F02@GP\!N)GT`0"@GS3P9]F(7```//[P +M()^TX`\)`:#I/BD"`;V4LIK[A50T\%\S^0#<_CZ"`0'$J3_Y$I20!MF`)0`` +MLJ&\"0#'J<;T&P7X"+(:?HWT`+\)QYF*]`L0F`D-C___S_V?!+4)#=X`(P`` +MF.FDC_\`__^?]/&4`/^XF0`!`/&4___]GP6UZ:28"0''F2.SE`(0F`H,"P'' +MJG1^'E,`2PD0RV]`3^20'=<`0``)"96+S]\*">O<22F02P\0V@GK#! +M#CY2"P&S&0GB`[`6"?0,*;,9!3$!L!8%]`P0LQ`!7+,=`R@(/@T$`;,9!ZD! +MLQT(&@@^NP8!LQD,306P%@ST#!&S&0H2!+,="P$(/F<(`;,9#\X&LQD0Z0:S +M'0WN!]"4%````1"]1+UTUBA:``#8`",``#X#"@'9`",``)B9H[:5&["1#I*9 +M`K"6`?0-";(:/NH#`=G`+0``OY[9Q"T``+^?E>D;]`L/E?D8]`L/Q^D:]!L) +M"1$^)0@!?@;S`+*@LZ`!"J!:/F8+`=Z@)```F.D#QY$)]`LBM/`.L_0#%-D` +M(P``LJRUFH^R\3Y2"P$)$Z!9/F@+`=J4%```2P`"?K\W`-F8#0``L@P@D0$' +M/E(+`=H`)0$`V\`H`0!^H%@`LZD`-0>SK0$P!]X`!```O^^R'$G_[P$%_?D$ +MH.\^4@L!VJ`D``"8J0,`_,>9"?0;"MF`+0``OY"R"GZ8)P&SJ0#I!@\!V0`C +M``"R"K6?CWX?)@':`"4!`-O`*`$`?D!8`+.@`0;X"-V@)```F-D#QYD)]!L) +M#`4^U`8!W``C``"8SZ.8SJ#9____!PT!_?D$_>D$V0```!"@7?WY!;+:V0`` +M``BUSZ/]Z06USJ`^:`L!O?3^20&0F5"@GY*9"*"?DID$_D0!H)^01$S^0P&@ +M3Y`S0/Y"`:`_D"(\H"]^,/0`H%JSK0%H!K*L_D`!_D$!D`!?D!%>L@JR&W[L +M@0"TX`ZSY`,:L%$`LDJR*[(\L@VR'GXE^@"SJ0`U!OY)`9"97K"1`)*9"K"1 +M`9"9!/Y"`?Y!`9`B4)`11/Y``?Y.`9``2+"1`K):LBNR'+(-D.Y??BO\`+.I +M`/<%_D\!D/]`OPV__K\<_DD!VP`$``"0F3R8OQJ_F;R?D+R>D+N=`KN<`O0? +M"0D(/B4(`9B_&;\N_DD!D)E,OYF\GY"[G@+U'FL"O00)$OZ0#/0R$O0R$O0R +M$K,$`0O9*%H``*"0_DD!D)E4OYFSE``0_DD!D)E8OYFSD``Q"@%^D_0`_DD! +MD)E4OYN0F02_G+):?E'V`+.D`!2S#0%:!=DH6@``H)H^=PD!LP0!$+WTV2A: +M``"@G_0Q$K3P#?Y)`9"90-X`!```O_V_GY"9"+^;DID,OYRTD`V[^P*\_="T +MH`R@G9CM&OY)`9"91+^;O/WPM>\:OZF[RP*8X!F8[1B\R9"@J?Y)`9"93+^? +MD)D$F.L:OYK9@"T``+^9O,O`N_H"N]\"MI4"O/#PM>P:M>\9M>T8WP`C```, +M![7YB@$("0*U^8L^4@L!V8`M``"_GPX!V0`C``"UGH^V]0+T&PNR'`$)/E(+ +M`;(<`0,^4@L!V8`M``"_F;VTE9P"/OL&`9+)`9"[`?W)!+/$`/?9A"T``-J@ +M)```OY^8J0/=`",``)C>I+;U`K:5$O&4P!_PE0*UW(VUWXJUV8N/_P#_Q^GH +M#`F[FP+][P2VE`@!"O&4___]G@6UV:0^4@L!V@`C``"8K:3'V1CU&^\#V<`M +M``"_DMD````!_]D%M:"DQRD:]0O6`YBMH)BNH=G$+0``OY_9````!/_9M=D` +M``#_M:N@_?D$V?___P#]Z03]_@6UKZ''N72SG0.A`]G(+0``OYZ8K*+?_`T` +M`-G____]_[F4Q`W_MM0"O-_0WP````+_+_3]^06)```#_>D$B?___+6OH/W) +M!/WL!;6NHAC9`;(<`0OPE4`UV0$^4@L!\)0!F!"+]`M,L@KP!#^U$(U^.@(! +MM@0&V8`E``"\"0"SI``,"0>@63YF"P&8"0'PE`CT"R"8*8J8+XNU((X,"[:5 +M`9#_`;4IBK4OBP$,/E(+`9@9BI@?B[:5`9#_`;49BK4?BSYL"`'1`",``)@9 +MBM(`(P``LY0`BPP+/C(*`=D`(P``F)J+4JH!?OE[`+*@LZ0`!O@(V0`C``"8 +MF8O:F`T``#^OW904``#PE#^]))2>!O#T_]F`+0``O.G@/MX(`;_9D-T0INGT +M&Q24*03:E!0``+R:D*"0/N,(`9`B`:8O]`C@W9@-```_V?"4_Z8I]!L%^`C9 +M`",``-K,-0``M9"."UQ^OS<`Q0D$N)D`(`+?##8``*#YV>0U```/`;T$H)\) +M$OZ0#/0R$O0R$O0R$J8/]!L*V2A:``"@D)0I!-Z8%```O)Z06)T!V0`C``"8 +MFH[;S#4``/#3`+)C`+.@`"._6;.0`1NS#0']`;WTV2A:``"@G_0Q$K(* +M/F@+`0$+#`RS#0'.`;WTV2A:``"@G_0Q$@P,/E(+`;)S#Q+^\PST,A+T,A+T +M,A*S-`$&H&-8#P()_V;Y]`L\6`L#\/(/Y+G__Z;Y]`LM&`D)\)0"]!LDOP+P +MLP"R*GX08P"SI``-M8*.`0\^]`D!&`D)\)4"-0D)LS0!":!G]#$2D$0!D``0 +MVI@-```_J?"4_Z9)]`B,#`T^4@L!V8!4``"_FMD`(P``F)N.?E]>`+(9Z+.4`2^8WZ.8WJ#9____!_WY!/WI!-D````0 +M_?D%V0````BUWZ/]Z06UWJ`^P0H!F-FCW____P?>P"4``+W$_9\$WP```!C] +MGP6]]+79H[_ID.Y`\)0']`L%LOR0_P&S]!_PW0`C``"8WJ"0R0'?____![:4 +M&_WO!/V>!;79H-V@)```F-D#E9\8L/8D]`PTV0`C``"8GJ"8G:*8G*&2_P&V +MY1"\_Y"VU1:\GY#?V`8``+:4!+R?D'6>$W6=$'6<$7XP5`"]!`D2_I`,]#(2 +M]#(2]#(2LP0!"]DH6@``H)"]I'Z3]`"S!`$0O?39*%H``*"?]#$2"0&@6;*: +M/F@+`;(FD/0;',3Y'[P9Q,3Y?Y6?!;.0 +M``V\KYC_R96\J?FFZ_0-T?Y)`;WTD)D,#?^_GI"9!*;M]`LC"P&RO;/T`PBS +ML!]!O-N4_9X$]`L9D+L!L[0@[#ZY#`&0_P&S]`33/KD,`90O`50)!]Y4)``` +M\92`![S^\/V;!;*Z=?D!/KL,`;VD^R40V<0M``"_F8Y!`A#?P"T``+__QYGP +MO)Z0MI0$OYG'_W3'GFJSY`$3DOD!O:2PE@'T#!RRZO@`L^0"#+#V`O"L"_@` +MO:2F_O0,!0H!^`#9A"T``+^9\)0#LYT#J`'9@"T``+^9LYT`G`'9`",``)B9 +M:\>9"?0;:MG`+0``OY\.#XG__P\,!?_YM++M/E8-`;;D!/W>!3/```T2S`'_ +MZY3T&_"YV0#_N93U&U@!V<0M``"_F8Y!`A#'F?"\GI"VE`2_F;.P`!!^O@P! +MLZ0`%#Z]#@''_W3'F6JF^?4;)@'9P"T``+^=E=D;LYT!&`'9Q"T``+^?V0`C +M``"8G(3'__#U"P$!ECU&\@`V<@M``"_G^?)2`&2F0&V]1:F^?4, +ML0#9S"T``#^9,YT`I@#9!"X``+^?Q_E#LYT$EP#'^>CU&X\`L^0$$97Y$+.? +M``*$`#YB#@&SX`,(L^0!#I7Y$+&60`#T#&NSY`(-E?D0L)8(]`Q>E?D0]!M` +ML^`"'[#F`O0-)+/@`R&SY`0=Y/G__]\````"/IL.`>3Y__^/```(/IL.`>3Y +M__^/``!`_9\%WP0N``"@^=D`+@``OY_'^?"PE@_T#`O'^8KPK`OX`+VD^`#? +M`"X``/DRQ*,_DCD!MI0&O)\`W\`E```,%+R?$+(+LJ*R&GY4-P"_'Y@>`0GX +MF`H*_?D$O93P]0&U&06@'\?L0\3+`?0;#-T````!/A8/`=T````#F!\!O92U +M&0^U&0FU&0['^>B0F0&VE!O'_R&U&0>V]!*)```@_]F5_9\%W@`C``"U&0:8 +MZ:28[Z+$G?^4V0CDG@`/,_``"/'E`!"SL``GV0```"#_Z?6SU``OL,8$]`TH +MV?___P__^93?````,#Z8#P&R[[/4`!*PQ@3T#0O9````$/WY!;4?"+.P`!C9 +M`",``)B9HC.0``SDK___/K@/`;WTB0``"/_YE;49"MD`(P``F)FB\)3_]!L) +MO<0^Z@\!MI0!WU0D``"\GY!8F0'PE'^4G`C9`",``-\P&0``F)ZA/_"8G:/' +M[O#$"_^FZ_0('-DN&0``/YG$G_^\^Y"FZ?08"KSKDCXW$`'9,1D``-\O&0`` +M/YD___"4__#T_[SIDJ:?]`@%^`C?``#_`/#4?__-U;:4$-P`(P``_9\$E2X& +M_9T%MN08_9X%M1D+F,V@F,^DB?__#PX$_]FD\/3_]`L^Q]YTLZ0`#+/T`2,^ +ML1`!L_0!&YC)HC.4`!2SX`,AL^`!';/D`A<^LQ`!DND!L)8!]`T+#@$^LQ`! +M#@/9`````O_9E)3O%/WZ!?WY!=D````$_]F4E#X;_?D%V0`C``#]_@6U'PR8 +MG:+$W/_T&PF]Y#Y-$0&8F:''GO"FZ_0(']DN&0``/Y_$"?_P]/^\^9"FZ?08 +M"KOK`CXJ$0'9,1D``-\O&0``/YD___"4__#T_[OI`J;O]`@%^`C9E%P``#R> +MF(\```/DW@#__>P%MI00_9\$_>D%C___/XD``,#_[_3_V93]^06U'PW[,?E" +MV\`M```,0-J`)0``?E0W`-F@)```F)H#T@`$``#0P"0``-/0)```MJ42\:3` +M'_"E`7[!#@'=`",``%C;^)@N"]S@&0``V<`E``!U"P%_S[4I#ME`(0``F-&R +MF-J]V\`E``#PY1"UFR:U+@N]E+4Y`;\D\/40M=FS8,\@":`Y=0D#=0D"B0`` +MP+4Y`OVI!=D``)``Q!L!M=FZ\!0/#_#9P`0``/V?!/V1!;7:O;79L@D%-0D! +MB0@`P+4)`N6Y0`BU"0.)`!`!N;P`_;D%V>`D``"U.P.UG`,)_?U)!*`D^T'Y +M`L>NQK+`L.8D]`Q)F+D$F+P!C_\`_Y+N`?V?!)B_`O&5``&UN03'S?"\[I"\ +MGI#>V`8``+:4!+R>D#6=)%B[`;;U%G6<$76?$'6;$[(+?I$V`/L!^2+;P"T` +M``Q`VH`E``!^5#<`V:`D``"8F0/=`",``-P$80``QYL)E9(8L[``'IC9H]__ +M__\'8,+]GP20_P']GP6UV:,^!!,!F-FC?\[?____!_V?!-\````0_9\%M=FC +M\.3_IN+T&P5@R]$`(P``F!ZCF!E\F!VD3P#__>\$\)3__9X%E"\0M1FCV?__ +M`/_]V03]_064(`:U'Z3Q!,`?\`4!L@I^P0X!VX`E``#O+[(F!V@\/0?"0&[GP3]G`6\N>G'W72SU`-(F!FAWS`9 +M```__\>>\/#T_Z;O]`@=V2X9```_F?"4_[R?D*;I]!@+^`B]Y#ZL$P$.`=D` +M(P``F)FBWY1<``#'F3`\^>G[(=D`(P``]##\O?3Y@K*C_D8!LI*8D(F09B35 +MT"T``(A`0@_4Q#4``->@)```/D86`;,)`VP!L`8#]`P0LP`!(K,-`D0"/A45 +M`;,)!=P!L`8%]0B6`;,-!B\"/A06`7X+#0&SI``."1&R"J`Y/E86`;]*F"]4 +MO`J4_9\$]`L8?H@#`)@O5+])O`F4N9D`_9\$M2E4V<0M``"_F]G`+0``F'H# +MOYR_3MG(+0``OYW'J@G'N_#'S'3PU/]^B@(`B?__`+*@IJGT&PD)!#ZW%`&_ +M64\`_\2N_]U`.```_9\$_>D%O92@7K_1D)D!D-U`LQ``$K.41O0)!Z`Y"@$^ +M5A8!OTJVI`;QI,`?\*4!?A$V`)AY`\>9"?0+#+4A?`\!/E<5`;]*L@M^`@P! +MM2I\LZ0`$]G$-0``OYI^B`,`/K44`7YC$0'>)````;_I#P$``K4I!3Y&%@'; +M``0``+^\Q,D"]!L8F"H%?BEN`+(/IJCU#1D!``,^1A8!W>`9``!_WY@NM@G] +M_\F4\?3]_Z"Y8-^VY1BSY`$ML@\`!CY&%@&]E-_)-0``WL@U```@^:!I(.G: +MP"4``+)K?L2L`+.D``JR#SZT%0'?)````;_YOV^U*06S\``/OUH+`?"D_W[+ +M`P"R#P`$/D86`=[)-0``/^DSE``,#P0`!3Y&%@&8*@5^*6X`#P2FJ/4-@0#X +M"-\D(``!O_G>)"```0\$``7QE0`0H.D^1A8!T,0U``"_"ME`(0``O12UD29^ +MB`,`OPD/!`H!H#^VE`'?5"0``+R?D'61`3Y6%@&]]-E`(0``M9\F?IH2`=T` +M(P``V<0U``"8WE2_F0\!H#^R^KSYE/V>!;795#Y6%@&R#Z;P]1NI_=D`(P`` +MO:2UGXG[A03X```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````/@`]#"D +M"USY`C*@_DH!D*H$?K\W`-F@20``\`3_E`H%O*F@F*\%Q_D1LY0!3,?Y$O0+ +M*,?YC)2?!;:4`KOY`ME\4@``O/GPF/D#M:D&Q:D$N)D`(`*U^0._JPGP_D\! +MD/\$_;D$"0&R_+B[`"``M?D5?K*#`/L%7)C9"IBO"/0P^/F"6)D!LN>RTK*A +MY)3__[*VLLC'_V@T4#"8J0&8K@DS\``&^`@U+QS'F4/P]/\PE@/T#`^V]`+9 +M_`T``#[)%P&V]`+9^`T``+SY\!@9)[4O"#4I+!@?+\?IA/"0'#4O/=_T#0`` +MO)^0M2D*F!D,MI4;-2D^,U0`"KT$/AH8`<19_Y20!=F@20``O`D`F`D%CP`` +M`OV?!;4)!9@9",>9$?0+$)@)!8\```3]GP6U"048+"S^0P&R2I`S*+)KLCU^ +M=((`LZ`!#*!ZO:0^_Q@!OST)_Z;9]`LUM2H4=2T7LFRR&K(K?C6A`)@9",>9 +M$?0+'+(:O;1^6(@`F!D*C_\`__V?!/&5``*U&0HS4`!OF`D%QYD2]`MEL@JR +M&W[?6P`8+"RRB_Y``;)*D``DL@U^=((`V0`H``&_#K^?V78%```_F?'T_S_P +ME/^VE`Z\GZ"FKO0-&!@I++RDX@\!N_D$DO\!_^^4/O$8`;RDDKB9_W\`"@&P +ME@+T#06]I`D!H'G[A0CY@MD`(P``]##\LJ:RDYB1B;U4O72]Y-04)0``V"A: +M```^41P!LQD#70&P%@/T#`^S$`$CLQ0"&3[Y&0&S&06E`K`6!?4(+P*S&0;Q +M`K(>/E$<`=F$+0``OY[$[0'T"R/9R"T``+^?F#F$MO46YYE(`:;Y]`@-"1&R +M&J!I/F$<`<3I`O0+:9@YL/"4![.0`0ZSD`,*"1,^YAD!F#F@W@0N``"_[\>9 +M=+;U$+.4!`ZS^P`"G0(^Y!D!LY`#%[.4`1RS^0B+`K/Y$(8"L_D@@0*S^4!\ +M`C[D&0&SG0)S`K/Y"&X""1&@:0H!/F$<`0X!L]D`I``^11P!V<@M``"_GY@[ +MH9@^HMG$+0``OYV8/&N)``#`_?D$B?__/^35___]Z02)``#___[E_[F4M3ZB +M_UF5M3FAY+?__Y7)&+"6)/0,()*9`;;E%KR9\+SY\-G8!@``MO0$O/GP=?X0 +M=?41F#FD,Y0`,*9U]`LJF#^@"0$.`B!)MO4;V14E```!`R"?/E$<`=X5)0`` +M/T\_Z2;Y]`T+LAX!!CY1'`'$^?^4D`;9@"4``+P)`)@)`;\.QYD#,YD`N@#$ +MZ0P"RHK.D``;X"-K,-0``"UQ^ +MOS<`Q2D$N)D`(`+>##8``*#IF`D)O03$GP\)$K4_B_Z0#/0R$O0R$O0R$K,$ +M`0:@@+(J,/$`LENR?-W,-0``LFY^>!@"4``,0)_[:4 +M!KR>D)B:",>J:'X"!P`.!+.I`*H`O00)$OZ0#/0R$O0R$O0R$K,$`0:@@)@Z +MBWX"%P&S!`$+O92@B?0Q$C])LAX!`Q"9`2!)/E$<`9@YL=X$+@``O^^8/FOQ +ME/__MO40E/`0_PF5M3FQE>H8L*8D]`PB=J0&\:3`'_"E`7[Y>P"SH``1F*D! +M\93___\)E;6I`=^$+0``O_D.!?"4`?0;$SZ2&@$)`:!ILIH^81P!#@$!`CY1 +M'`$.`0$%IN'U&]3\V0`C``"]I+6>B?0P!/N!^``````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`/@`^8+9`",``+*FLI68DXF])+T4O438R34```?D+5?BO0+#IA9H+:5 +M&Z;Y]`T)"1,^VAT!O/.2TL`E``"4D0:\$A"8&0R8&@NVE1NVI1BVI`;]J05^ +M^7L`LJ"SH``.LAJR"PQ`?E0W`+\?M5".Q/H'DJD#L)8!]`T5LZ0!$L?YBO0; +M"PD3H&D^TQ\!F$D"\?0`?+:5$/0+')7Y"O4+#``"`0,"/L,?`0D%H&D*`3[3 +M'P&5^0KT&_._2=W`-0``LG*@U[49`IA/`0,$M1\#/L,?`0D!TL@U```@B2`I +MW!9@?!Y@="+49!9A"`4G_X/W*!/"T!_W+!?W)!(G__^"VY1NV]1NV +MY`BV]!#][`7'W1O]Z02VU!C][P79_____OWI!/WM!;42![5>B[(:LC)^_GD` +M`P,^PQ\!F%F*/X^[EP*4D0;9P"4``+P9$)@9!C/]`.0`W![4:"`,$/L,?`9@?!Y@>!I@=!=G`-0``OYR)``#^_?D$V?__?_^U'P?] +MZ039````_;4>!OW9!+4=!;/$`1>_'\3Y![.0`0X)^/_YE/"5`Z`9V0`C``"8 +MFHZSH``,LAL,0'Y4-P#9P#4``+^9/MH=`;(R/L,?`0(#IB/U&US]V0`C``"] +MI+62B?N!^``````````````````````````````````````````````````` +M`````/@`^4+9`",``+*DLI.8D(F]]-$`!```0O_O/EXA`;,``ABS``0[LPT! +M,`&U,(^R#P`"/EXA`=H`)0$`V\`H`0!^H%@`LZD`&`&SK0$3`;\9L@\`!/V2 +M!*`9/EXA`0K_?I@G`;.I`/,`"OQ^'R8!#P'9`",``-H`)0$`M9^/V\`H`0!^ +M0%@`LZ`!!O@(T``C``"8#;N8"KR8#J"8#Z.VU1B4V0:VI1O_FJ79````"-'_ +M__\'_>$$_?$$_>D%_?D%V01A``!@G4D`__WY!+4.H+4/HW[Y>P"SH``UF*T+ +MF*\%OZX)@/W9!/WQ!`GX_>D$\.4!LJNUKP6UK0N@K@Q`VL`E``!^5#<`/BTA +M`9@/NY@-L)@.M0F`_?D$"?C]X03]V02U#[OPU0&U#K6U#;#9Q#4``+^>V0`C +M```/`;6?B=E4)```MN0!H$^\Z>"R^GV4=>D!/FXA`;(//EXA`0\"IO#U&[[^ +MV0`C``"]I+6?B?M!^``````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````^`"2J@'=5"0``)6N!=G0(P``/]^VY`*\ +MZ>"_[/"D'PD!$O\!NYH$(-^YF0#]G`2@Z?@`L*8D]`PDDJ\!O/^0O)^0W]@& +M``"]Y+:4!+R?D`__M9X+M9X*=9\0^`#Y@MD`(P``LJ2RD9B0B;W4T\0U``#2 +MP"0``-95)```U?___P?8__\`_]<````(/@XD`;,)!.,`L`8$]`P0LP`!&[,- +M`F:L`LZ0`#+(*"0L^_B,!OSZ8'U2\ +M#I3]GP3U"SD!F!F@H"F8'Z'9S`8``+4O`;SN\+S^\+\NMO0$O/GP6/D!_>4$ +MF"T!F!RCQYF+MI0;_9X%M1F@/_G]V`3?``#_`+;%&[:4$/V?!/V=!;49H;/) +M`.8`DLD!L)8"]0S;`+40C[(-``(^#B0!"O]^F"4$_9<%M1^/M1ZUM1FC``0^#B0!OSI^B`,`OSW95"0``)3? +M`;SY\%CY`7.0`!@_;GV4=?D!Q.G_IIWT&P@2Z0$@:;\O#02U'Z"8*0&U&:$^ +M#"0!OSI^,R(!OSI^`B(!L@T`!CX.)`'=`",``)C?H]G$-0``F-Q4OY[9____ +M!_WY!+7?HPH!O*[T__R4]`L2N?D`H$K]G`2UV50^'B0!2<$`H$D^'B0!L@T^ +M#B0!#0$`!:;0]1M^_MD`(P``O:2UG8G[@0`````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````^`"8J0R8J@OY$K:5&[:E&+:D!OVI +M!7[Y>P"RH+.D``;X"-K,-0``"UQ^OS<`Q0D$N)D`(`+?##8``*#YV>0U```! +M`;(*H)';S#4``'Y9E0"8"0GPE`_T"R.\D:+9P$D``+:D!;RIH-D@-@``L@N@ +MD=S,-0``?K*#``H!^Q&8KP'Y(K*@LK'$^0CT"R>8J0@+`<>9:#.0`A"8J0WP +ME/_PO`OPM@&R"G[(@0"@&C[#)0''^2.SE`(0F*H,"__'JG1^'E,`V20```&_ +MGY@."Y@-#-G\80``D/\!E>(8E=$;H)^R*K(;?OZX`+.@``A^6K@`LBJR&W[^ +MN`"SH``&^`B8"0R8"@NVE1NVI1AVI`;]J05^$38`OPD/^/V?!*`)^R'9`",` +M`)B?H)B9I/0P]/F"MJ4!,IBVE`2V]1ODDO`/_D;R?D+59 +M'#[E)@&_+[]YO)^0H"F861B87QF2F0&0_P&U61BU7QF0,P&0$4"TD`FF.?4( +M8/_[A0S?`",``)CYH/0P_/ERE:4!E90;O93^3@&R]Y#N(-#`)0``H.FRY@G_ +MO12U^8J])`,!/G$G`;PQE/V5!/0+)[\)\)0']`L?L@JR:W[$K`"SH``4F`D! +M`@'PE`CT"PBU`+.@``H/`SZ?*`&0(@&0`$"F)/0(LCZW*`$_>3.0 +M`$D/`P$(/I\H`3]Y,Y``.Y@Z!7XI;@"FJ/0-&/@(WR0@``&_^0K_\94`$*#Y +M/K4H`;(?IO'U&Q?_V0`C``"]I+6?CSZU*`$*`?N!"?^U.8H^:"@!^`#X```` +M```````````````````````````````````````````````````````````` +M`````````````````/@`^2+0`",``)@.:[*AF`F@Q^^0]0O!`+:5&Z:?]0BX +M`)+Y`97J&)22!K"F)/4,EP!VI`;QI,`?_:\%?OE[`+*LLZD`@P"_J?"4![.= +M`HH`F`EKQYD)]!L1F*D%W____P?]GP2UJ06_SYC.!IC-!0GX_?D$V?__?__P +M]0/]Z02@S]G____]MD!O\_9`",``)B=CMD````;M>D""?#]^02@[YC)`YC?`L>9`<3^`;.0``?P +MY@&_R0_P_9\$_^F5M=D"F,P!M=P#^`#9`",``)B=CIB>:P_PW+`D``"8V0+: +MP"0``)BK`\?ND/V?!*#)V<0U``"_F9C?`[;D$+:4&/&5`("USP'_GN79____ +M?[7.`_^Y]+6O`[_9QYF*]`L.O92UR0&@R3Z_*P&8V0+_^9;PE`'T"PS9```` +M&SX;+`''N:JSF0:W`+"6!O0,#K"6`?4(V@`^[BL!LY`'0;.=",X`/JD$Q[X$M<\!F-\%MT#^`!^`BL!"@'X`-D`(P``F)N.F)IK^1)/ +M_]^8N0B_OOV?!+6Y",3A![,4`1`)^`$#_^F4\)4#H+F_N<>9BO0+$)BY#8__ +M__[]GP2UN0V8N0C?___O\T#!`/V?!+6Y"-D`(P``F)F,\)0$]`LBV<`E``#' +MJI```0Q`NZ`"MJ0&O*F@?E0W`+,0`P8`$[(*^Q'9`",``)B?:_DBF)F@Q_J0 +M]0OO`+:5&Z::]0CF`-F`)0``E*`&O`D`F`D,F`H+F`(!MI4;MJ48=J0&_:D% +M?OE[`+*ALZ``#K(*LAL,0'Y4-P"_"<2:![.M`:D`LQ``:+WT"1+^GPST,A+T +M,A+T,A*S]`$+V2A:``"@GY@9"/&5`""U&0BS]`$0O?39*%H``*"?]#$2Q1D$ +MN)D`(`+?`",``+7YC+7QCKV4M?F-Q"D(]`L)"10^B2X!"0VU^8D*`3[0+@'= +M`",``)C>?9@/#-P`)0``M=".E.D#O)R0OYFV]1NVY`.V]`:\[>"\^?"UWXR8 +M[H$)"K79B;7>C3[0+@$*$_LA^5+9`",``/0P^+*4F)")O?31``0``(/_?__5 +MP"0``-+@&0``/ODO`;,)((4`L`8@]`P0LP`>&[,-']@`/D,O`;,)(8H`LPTB +MR@`^J"\!?RF_'YA*BO"5`O'U`(!@*:`??I-\`+(/LZD`P0``'S[Y+P&_&9A/ +MC@KPW,`D``#]DP2@&;V4F/X"L)$`"0(PD028^P/_ZJ0-$-ZRJP``?CO"`+(/ +MLZD`A0``(#[Y+P&_'^3Y`(!SE``*L@\^^2\!__.4L@^@&0`A/ODO`7Y3*P&R +M#P`B/ODO`=JP)```?;3<``0``'X`/@`SI``_F%D#L)8`]!\M?NPL`=JP)``` +M?;3<``0``'X`/@`SH``6/O9 +M$_0;%)@)"K(>M2".`0W]F`4^]#(!"0&8*HP@22!IF"N-F`P*?H1$`+(>`0L^ +M-S,!/TDSG0"!`I@JC)@KC;V4L)$`"0*R/#"1!`U`WK*K``!^.\(`LZD`7P*R +M'@$,/C/C9&_WO!+:4&/V>!;4IB^3? +M__^)_?\`IOGT#0V)``#__]F4M0D*/=0)`2!)(&D@69@/"C/0`!_9____^/_Y +ME-\````!_9\%M0D*/90@63X1,@'9____^/_YE-\````#_9\%M0D*F`T(Q]D3 +M]`L=Q]]HV?`9``"\G^B5WQP)`;N?!+7I"#XZ,@&R"G[^>0#9)````;^9LAX! +M#K4I!3XW,P$_:9@@CC.4`!$_23.4``L_63.9`-``OPGPE`>SF0+&`)@J!7XI +M;@`.#HE`0@^FJ?4-O`#X"-XD(``!O^G?)"```0X.`0_QE0`0H/D^-S,!F"^- +MF`X-F`P*F`T(OPN)__\_MO06_>D$_=<$V?__?_C]_@7]R02U#PVU#0BU#`K' +MN8KT"RZ8*8NR'H\``/\!`L>9&+:4&_V=!;4)")@IBO_/]/&4___]GP6U"0H^ +M-S,!Q+D'LY`!#+(>`0(^-S,!V?IA``!_F;(>`1[PDP"U*8H^-S,!V0`C```* +M`;61B3Y',P$.#@$//CB?0P"/N!^7+9`",` +M`+WTLI>8D(F8D8[6@%0``-7Z80``!!*]--(H6@``/A`T`;,`%D^S`!=?LPT4 +M@@"R,/Y`#/0R$O0R$O0R$K,$`0:@(+(:?;1^Z(X`LAI^C:P`LZ0`$[,$`0F@ +M*O0Q$@\4/M$S`;,$`5:@(_0Q$CX,-`&_:K(;?E]>`+(/LZ0`0P`7/A`T`;\9 +M\)0'LY`!$M\`(P``"0*U^8D^!C0!?UFR#P`>\),`M7F*/A`T`=D`(P``M9") +M"@$^(#0!#Q0`%J;P]1MB_]D`(P``O:2UGXG[L)8$ +M]`Q4/HTT`7[/+0&@*K.@`32R"C[&-`&U$(E^#C`!/I0T`;40B7Y,,P$^E#0! +MM1")?M(N`;.@``JR"CZA-`&8&HF8$(D^MC0!?DHM`:`J"@$^QC0!L@JFH/4; +M?O_9`",``+6:B;VD^R'X```````````````````````````````````````` +M`````````````````````````````````-K`-0``?AHX`0D.LZ``$-D`(P`` +M#P6UGP,)![*:^`#9`",``/D"F)]K/=394!H``-Y<&@``()V0F0&FGO0;^H" +MY)____4+L@`]E#SI^3Y1-@'9``0``)B:(1B0B8L`4P=^0VX`W5,:``#>0"0` +M`=R@)``!O^D/4,>9:K.4`0J]]#[E-0$S```&LJ\@WY#N$)#=`:;L]!O?/E$V +M`=D`!```F)\E&)"9BXBG$;S_D+R?D)2:!+NI`KRJH'Y#;@#=4QH``-Y`)``! +MW*`D``&_Z0]:QYEJLY0#"KWT/CXV`3,```:RKR#?D.X0D-T!INST&]\^438! +M^`C[`2:K]!LXL\``-[+.#P&]E+:4!+;E!/"5#S+[L^``"Y#_`;/T!>[]G02F +MG/0;$,2Y_[:4`KO9!3Z/-@&]U++:^`"_KIBI`?F"C___#[*B_^]DMI48L)8/ +M]`T%^`@]]-E0&@``Q^09()\,_P\!#5H^TS8!LT``"B#M/M`V`2#LD/\!F"D! +MVU`:``"\^^"VE1BF^?0-X=!`.````UJ(B*<1LK77P$D``+\)LYD`B`"8"0'P +ME`CT"WV8*@$8"2[<,1D``)@-##_+C___#[:E$+)L/)NP_=\$?E,V`;*ALZ`` +M59@)#,>9=+"6`?0(1K"6`O0-"[.4`ST^@C!?L!V0`C``#T,/B]Y/F"LJ3T,/BRD_Y&`?Y'`9B1B;TDU0`$``"( +M_W__D&8PD'9`3Z3.0&8.FO'J7"2F0&PE@/T#0T)!;(:H$D^(3H! +ME:(8]`L+LAX!`SX1.@%^'S4!"@P^W3D!LBI^>:L`LZD`#@'$*0&R*K4Y?;)K +MLGQ^838`LZ``+I@Y?=T`(P``#@,!!I2?`[S]\-T`)0``MI0#O)V0OVV@G;]Y +MM?F!/A$Z`9A9,9A;,K"A`,0J_K:D`[RIH`D"H&K>LJL``#"1!-P`)0``#1!^ +M.\(`#@.SJ0#M``D%#@.U.0,^$3H!OU\.!>3Y`(!SF0#5`/_XE`X%H%D!!CX1 +M.@&8/WV]E+"1``D"W0`C```PD03>`"4``)3Y`[;T`[R=D+S^\)B;@;_ZWK*K +M``#<@"4```U`?CO"`+(>LZD`B0`!!SX1.@&_7^3Y`(!SD`!V__B4LAZ@60$$ +MV8`E``"U.8X^$3H!F#".OP_'^1KT"PK'^72SD`,."04*`:!)/B$Z`;(*?I,V +M`9@*`;:E&)"J`7ZT-P&R'@$"/A$Z`=U@&@``F#F*O]^F^?0;&MG@&0``?Y\. +M`:!.LNKQ]/W_8)\^(3H!LAZFX?4;./[9`",``+VDM9Z)]#`(^X4(^``````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````-P`!```VK`D``!]M'X` +M/@#<`",``#.D`"68R2W>X!D``'_O#0:0F1"US0.UR2WQ]/W_LME@[SX_.P$) +M";7)`[*:^`#X```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````#:L"0``'VTW``$``!^`#X`"0LSI``LW0`$``"_ +MV=S@&0``?\Y/_[_]GP2@V=D`(P``\>3]_P\!8,ZUGP,)![*:^`#X```````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````]##X^3+1`",``)@9:_0P^/Y"`?Y#`960&,0)`9`B')`S&+(KLCRU&7VR +M"GYA-@"SH``LF!E]OR(/%]T`)0``M1\#E)\#MI0#O)V0H)*_,[SQ\`X'M?.! +M/I8]`=D`!```F)LRF)DQL*$`Q`K^MJ0#O*F@"0*@*MZRJP``,)$$W``E```- +M$'X[P@`.%;.@``L)%@X'M1D#LNKT,`C[-0CX```````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````-L`!```O[P*%N3) +M`(!SD`!NWN`9``!_Z=\`(P``F/UKF/]]\93]_V#IW@`C``")_W___\F4D/]` +MH+FV]`.\_I#>!",``+;5&+S^\+^"[6<"@\7V0`C```*![6?`_@`^``````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````#>`",``)CO?0D8W0`E``"UZ0.4^0.\G9"_ +MFK;T`_0P^+S^\)C[@;.D`#*SM``NF.EKQYFJLY0*$`D,M>NCM>D#/H(_`?@( +M"04/$[7I`]G`-0``H)\^@C\!O92PD0`)`MR`)0``,)$$#4#>LJL``'X[P@`) +M%[.@`!`/&-D`(P``M9\#"0>RFO0P"/@`^``````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````W``$``"_S0H8Y-D`@'.0`";>X!D``'_OB?]____9E`H'\?3]_Z#) +M8._9`",```\9M9\#^`#X```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````/D"T``C``"8 +M":#T,/BVE1NU"9#T&PD)&SY@00&8"7W>`",``-S`)0``3<`'E)\#MI0#O/[P +MW@`E``"\GI"_FKV4L)$`"0(PD028^X&0JD#>LJL``'X[P@`)&;.@``L)&K4) +M`PD'LIKT,`C[`?@````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````#<``0``+_-"AKDV0"`&[#V$/0,%;#V#?08 +M3;/P"Q2S]`P,/H=#`;/P$2D*`?@`Q]D)]`L0L.8`\)P+\)8!/H)#`;#F`O"< +M"/"6`<::`?@`DND"/?2PE@'T#04/`<;Y`<2:__@`DND!/?2PE@+T#04/`<;Y +M`<2:__@`^``````````````````````````````````````````````````` +M`````````````````````````````````````````````````````-F@)``` +MF)L!OYJ]E/0P^+"1``D"W(`M```PD00-0-ZRJP``?CO"``D/LZ``$-D`(P`` +M#Q"UGP,)![*:]#`(^`#X```````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````#<``0``+_-"A#DV0"`X!D``'_OB?]____9 +ME`H'\?3]_Z#)8._9`",```\,M9\#^`#X```````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`/DBT0`C``"8'P?>:",``+*BE/D"O)Z0MO0"OYO91",``+SY\+_Z?NC#`+.D +M!PSX"+*N/L1*`0X'LZT#C`"8&0?>C",``-K`-0``MI0"O)Z0OYGYE9@?!]YH +M(P``LJ"4^0*\GI"V]`*_F]E$(P``O/GPO_I^I5<`LP0`#@D!#@R@*3[$2@'? +MP#4``+_YLY[B`!0)!K49`[*>"0&@^3[$2@&SD`$=LY[!``D)`:#Y#P79`",` +M`++^M9\#/L1*`0D<#@>U&0.RZOLA^``````````````````````````````` +M``````````````````````````````````````````#9`",``)B=:_E"F)^0 +M]##XF)F@Q]ZJ,^`*$I63&Z8_]!@CLO,^0DL!E=D8O)GPO/GPVV8`M``"_G]F$+0``OYD])/_Y +M%3[12P$0(@'$&0'T&S+9P"4``)2@!KP)`)@)#)@*"[:5&[:E&+:D!OVI!7[Y +M>P"RJ[.@``RR"@Q`?E0W`+85`<0J_Z:C]`C`D#D!W(`E``!4G0:]Y-L`(P`` +ME$\#E$D#O/OPVP`E``"\FY"_FKV4L)$`"0$PD028^X&\ZJ#>LJL``'X[P@`) +M'+.@`!#9`",```\=M9\#"0>RFO0P"/M!^``````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````-P`!```O\T*'>39`(!SD``OWN`9``!_[XG_?___V92@R?'T_?_9P#4` +M`&#O#P$*!Z"?#P79`",``+6?`_@`^``````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````#>@%P``-F@)``` +MO^^8G0/Y(MDP&0``/YR0_P&@[[*BQ,__E=H8IJ_T"!79+AD``#^9Q)[_O.^0 +MIJGT""'9`",```\%M9\#V<`U``"@G[WTV<0U``"@GSZA3@'9`"@``;^=O*^2 +MII[T"`7X"(E!`A"\J:"4J02_GXF__>^\J:#$^0$SE``J#P39P#4``*"?O?39 +MQ#4``*"?#P79`",``+6?`PD!#P>@*3X#3P''\6HS$`0&^`@\K`*0W0&]I';4 +M!-N@)```,@Q^3@(`#PVSH``S#P'9P#4``*"?O?39Q#4``*"?#P79`",``+6? +M`P\',Q0$$<0*_PL$O<1^$R``#P<)`:`ILOK[(?@````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````D!^0*@J;*@?EY0`;.D``@)":`)OPG0`",``)2O&/'U`(2VE!BU +M"6Z8"2VU#V_:L"0``'VTM0ELF`DNW``$``"U"6U^`#X`,Z``"KVD/EQ0`9@) +M+0H!D)D0M0DM^P'96"```?D"OY_95"0``#^9)I_T&&O>T",``+W$/M%0`;S= +MT)#Z`?_;E+*O]!LZWE0D```_Z=!5)```/P__O=40F0$@Z93)`M[0(P``O)Z0 +MH)WP]/^4R06\J:"FK_0-(R`*/MU0`;.D(+N0S`&0[@2SP"`.O^N]]`T!/H%0 +M`;VD^P'X``````````````````````````````````````````#X`/D"T``C +M``"8#RV]E)B9$MJP)```M0]LF`\NM0]ME9\8MI40Q)X/QYEDE)P#O)F0O)R0 +M/.G@V0````'$_0_PY/_'_V3]Z064^P.)`,``O/_PO/OP/-_0\-3_MM0(_>T% +MM0EOM0YN?;3<``0``'X`/@`SH``*O:0^D5$!F`DM3N(`W\`U```*`9"9$*#^ +MM0DM^P'X`/@````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````````````^`#991H``#^9,Y0`,MED&@``/YDS +ME``GWR4:```_^3.4`!P8^0$SE``5&/D",)8`\)P+\)8!QIH!^`"]I/@`V3`9 +M```_F9"M`<2?_Z;?]`@DV2X9```_F<2>_[SOD*;9]!@2O*^2D)D!II[T""@^ +MD5(!V3$9``#?+QD``#^9/__PE/_P]/^\J9*0F0&FG_0(!?@(C$("$-\$:!$! +MO*R@E)L$E*X$O+_`O\V_[XF^_>^\J:")```!_]F4]`MF21_^__F4\95@`Z#I +MB0``___9E*#)E*D#WPQH$0&4K@:[Z0+90%@``+R_L+SIX+^_F.D,W"0D``&4 +MK02\W-"VE!S<____#_W\!/WY!:"_O]^8Z0S]_`2VE!S]^06@W[V4M>D+^`"4 +MJ0.4KP:[^0+90%@``+SY\)C\!/D"Q,F`,Y``&^3)``'U"\L`27_^"@'_R92U +M^00^$%0!V3`9```_F9"M`<2?_Z;?]`@DV2X9```_F<2>_[SOD*;9]!@2O*^2 +MD)D!II[T""@^J%,!V3$9``#?+QD``#^9/__PE/_P]/^\J9*0F0&FG_0(!?@( +ME*D&E*X#O)X"V4!8``#%SX"\"0!)__[]^02RJ[4/!`H)W)"-`0!^RTX`LZ0! +M)-Y88```W>`9``"_Z7_?O:3QE0`"\?4`"*#I8-\^$%0!LZ0"%I@)!$]__PH! +M_9\$M0D$/A!4`;VD^P'T,/3Y@K*@LK@RPC/$!`W9,!D``#XO5`'9,1D``#^9 +MC;_][_"4_[P)<(E!`A"2=`&\>7"4?`2_P[#!";Q]<,<^T;#A"C,D!!K?!&`1 +M`90)![R?D)"?!+^1O_4^DE0!E`T$,R0#$-D$:!$!O-G0/HM4`=P$3%@``+N?`KR> +MD!B?`S/T!!64"0?<"&`1`;R"&@1`;S>T#[L5`'9 +M"'`1`;S9T+_9M-`+,/8`\,P+\,8!QYX,IM[P;`OP9@&S8``(L^`!8=G__P#. +MCP```?\9E/^?]3,D!!"4"0?=!&`1`3XX50$S)`,3E`D$W01H$0&\G9`^:%4! +M$BD!E`T$,)8!]`P1V01P$0&\V="@WSYJ50'9!&@1`;S9T*#?N-D`"`"@GXD` +M``'_&93T&SZS9`!:B0``0/\9E/0;-)1)`Y1/!MU`6```N_D"O/WPF/D$\)0$ +M]!L:L\D`,PF)```(_QF4]!L+/L]>`;-D`!^420.43P:[^0+90%@``+SY\)C_ +M!,3Y!/4+I@.43P.420:SY`$YNY\"W$!8``"\G)"8F03PE`3T"P7X"+Q$\)1) +M!-U$6```NY\"MI0"O)V0#P,UGP$)`S[17@&[GP+>0%@``+R>D)B9!/&4`!#T +M"PNR"@L!?F`D`)1/`Y1)!KN?`M]`6```O)^0F)X$O?2UGPFUGPI/\^_][P1/ +M?_7][P2UG@0S)`0MB<`B`KP)`)0)!XQ`W?V_GKP,`-T$8!$!E`D'O)V0OY^0 +MF02_F3[15@&4#00S)`,JCH`6$;P.`)0)!-\$:!$!OYZ\W]"_V9#?!(R`Z>Z_ +M^;P,`#[15@&.`!<1O`X`E`D$WP1P$0&_GKS?T+_9D-\$O_F,`.GNO`P`Q)T/ +M,R`$"KWT/N%6`<>?#+/4``PS)`1ZL_0`=I+9`;"6`O0-;+/0#VDS)`0BL]`( +M8;/0!V.SU``,L_``6SXN5P&SU`8*LMX^ST`9' +MY.D``O0;";WD/G-7`0X'L]`*-@X.L]`+,#,D!`RSU`0,/FM7`;/0!QCX"`X- +M/G-7`0X(/G-7`0X%/G-7`0X!/G-7`0X"E$\#E$D&W4!8``"[GP*\G9"@GK3@ +M"[/@`0BS9`$+B0```OTY!<<9%K:4%H_L_[__/_3]^05)'\+]^03$7@^VY`7_ +M_E6T\`G9__\`SO\9E*#UCP``0OV?!8\``/__G^0S)`06Y>-_#+(*BT%^!7XE +M:@`^8E@!E$D&E$\#O)\2V4!8``"\&1"8&03%XX#PE$#T"R@]M+)*?I2%@` +M`+N4`K:4`[R>D+^1LQ0!.MRL8```V^A@``!_SG^ZW6A@``!_WY!)`;P9E/"3 +M`'F9`/^?]/^>Y/V:!&#?8,Y@N;VD?KEM`#,D!!.4"0??!&`1`;R?D#[^6`$S +M)`,3E`D$W`1H$0&\G)`^_E@!$BD!E`T$,)8!]`P1W@1P$0&\WM"@TSX`60'? +M!&@1`;S?T*#3N-D`"`"@D]DX`!`!CP``?Z"?M)`*LY0`$L=9T?0+"S)Z,@M^ +MA30`"0>@B=D`6```/YDSF0">!3,M!)D%V>@9``"_F?"4`?4;B@4*#KVTO<1^ +MRTX`LZT!?`7>6&```-W@&0``O^E_W_&5`$#Q]0`(H.E@WS[)7@&SR0"F`<<9 +M$S.9`)X!L@K$*_]^1B,`?@)2`;.D`![$*_^R"CW$?A(C`+(*Q"O_#`%^$B,` +M/L]>`=PD)``!E$D$W2PD``&\G+"\G9"_O+^9E`T$Q)\#,R0##=X,:!$!/M=9 +M`=X,V?__`,[_ +M&93%GP0S)`0?E`D'W`1@$0&-P"("O)R0O`T`H)^4#P<^:EH!,R0#))0)!-X$ +M:!$!O)Z0H)^/@!81O`\`E`\$25`"H/D^[EH!$BP!E`T$,,8!]`P1V01P$0&\ +MV="@WS[87@'>!&@1`;S>T*#?N-D`"`"@GS[87@&4[P1)4`*@^3["6@&/@!81 +MO`\`3U`"E`D$H)^4Z02@GS,D`2S9)````91/`[^>W$!8``"420:[GP*\G)"8 +MGP20[@&UG@WQ]0`(M9\$O[Z\1-`/^)1)!/WO!+N=`J"^MI0"W418``"\G9`/ +M"36?`0D)/M%>`3`F!,16#^3Y``+T"T])__W_^>243P.420:[GP+?0%@``+R? +MD+6>!#,D!`;X")1)`]Q(6```NY0"MI0#O)R0OYFSD`$&^`C$Z0'T"P7X"(D` +M`$#].04^?UL!C___O\<9%O\_]+:4%O^?-91)`Y1/!MU`6```N_D"O/WPF/X$ +MY.D($/4+Y`!)]^__Z92U^02]E+7Y"K-D`&TS(`0&^`C9__]`SO^1]#,D!!.4 +M"0?>!&`1`;R>D#X*7`$S)`,3E`D$W`1H$0&\G)`^"EP!$BD!E`T$,)8!]`P1 +MW@1P$0&\WM"@WSX,7`'9!&@1`;S9T*#?N-D`"`"@G[)*?IXF`#[/7@&2:0&P +ME@'T#%?#+/4``PS)`1\L_0`>)+9`;"6`O0-;K/0#VLS)`0?L]`(8[/9 +M!Z,!L]0`#;/Y`)H!/GY=`;/9!H4!L]D%D@$S(`,*,"8"]`P(L]D&@P'DR0`" +M]!L)O<0^_EX!#`>SV0IQ`0P.L]D+:@$S)`0,L]0$#3[P7@&SV0=+`?@(#`T^ +M_EX!#`B420:43P.\G_+90%@``+SY\)C]!-G__T+.H/S_D<3$V0'T"Q:S9`\3 +M"?[_V92U^02)__^__>D$M-`)H-XS)`03E`D'WP1@$0&\GY`^/UX!,R0#$Y0) +M!-T$:!$!O)V0/C]>`1(I`90-!#"6`?0,$=\$WEA@``#=X!D``+_I +M?]_QE0!`\?4`"*#I8-^420:43P/=0%@``+R?HKRMH+^ILY0&%+-D!1`)`Z") +M"0*@J3[)7@$)!Z")OXH^U5X!"0>@B;*:^X4,CP`7$;P/X##&`?4,S/L^HEH! +MLMP^_EX!#`$^_EX!#`4^_EX!#`()_?WI!#ZT70'T,/#Y@K"Q";*B,\0$#=DP +M&0``/B-?`=DQ&0``/YF-O_WO\)3_O"E0B4$"$))0`;Q94)18!+^$O%U0QT[1 +ML.$,,\0$+I0I!]T$8!$!O)UPOW'?"&`1`;R?8+]CE1X1L.$*LNGPE`'U&Y,! +M/HMC`90N!#/$`Q#?!&@1`;SOX#Z07P'9!'`1`;SIX)#I!+_CE`\#OY'=3%@` +M`)0)!KN?`KR=D!B9`S.4!!64*0?="&`1`;R=D+^?/MU?`90N!#.4`Q#?"&@1 +M`;SOX#[;7P'9"'`1`;SIX+_OB0```?\YE/4+?`3'_`RSS0%U!-DD```!W4A8 +M``"_GY0.`[S@DK:4`[R=D+^=D/\!E`D&NYX"WD!8``"\GI"UGPF@G+/4`1S> +MK&```'_OD`D!O-F4LMK]^05@[WZY;0!.#_Z)`0`"_TF5_9X$Q!\/MO0%_?D% +M2?_#QQYP_?D$E.D*__G5L^``!O@(E`\#E`D&NY\"WTQ8``"\GY`8F0,SD``& +M^`B@C=G__P#.C^^,0_\YE/^?];/D!!"4*0?>!&`1`3ZN8`&SY`,3E"D$W@1H +M$0&\GI`^WF`!DND!E"X$L)8!]`P1V01P$0&\Z>"@[S[@8`'9!&@1`;SIX*#O +MN.D`"`"@G\?9T?0+$K30#+/4``PR6C(K?H4T`+3@"0D'H.D^9V0!C\`B`KPO +M()0I![^=L)$+OWF_:8Y`W?V\+B#$GP_'G@RS]``)L^T`FP"2^0&PE@+U#9`` +ML_D/C`"S^0B'`+/Y![@`L_0`#;/I`*\`/GUA`;/Y!I,`L_0%*8\```/9__\` +MSO\9E/V?!;3P#*!YB0```O])E:")L_0`*3Z680'DV0`"]`MAL_`*7K/P"UJS +M\`1I^`@^]6$!,EHR*WZ%-`"4"0.4#P:[^0+90%@``+SY\)CY!$Y___V>!+7Y +M!#Y"9`&R"GXB4P&SI``-M.`)O^D^9V0!LBI+$0Y^)6H`Q4\"/OYA`;(JBT%^ +M!7XE:@`)_?])]#[^80&T\`F_^3YG9`$)_O_YE,<_#+3@"OV?!4__P[^,_9\$ +MQS]PMO0*_9\%C____?V?!$\?_O#D`;;D$?V>!?V?!(___[_$/0_'S`FVU`7] +MG07]GP3''Q:V]!;_GS6SP``:E`D$W20D``&\G9"_GX[___[]_@2@G]XH)``! +ME`P$O,[0O]^)``#_WO__`,[_'N3]^02@W[3P"[_]OWF_;XD``$/_Z17'_@SP +M]`_T&P>SY`!.DOD!L)8"]`U$L_`/0;/P"#VS^0>R`+/T``VSZ0"I`#[18@&S +M^0:@`+/Y!9L`Y-D``O4+D@"S^0J.`+/Y"XD`L_D$A`#X"#YG8P'9)"0``;S) +MT+_>E`\#E`D&NY\"WT!8``"\GY`/"*"?V>____[].00SX``'\!4"O]G'F>CT +M"P;P%039`%@``#^9,Y``.=GH&0``OYGPE`'T&RL*#KVTO<1^RTX`LZ0!'MY8 +M8```W>`9``"_Z7_?\94`0/'U``B@Z6#?H(.@<<949$?"49<0]#\D%2?S#_>D$H(ZST`80L]`*([/4!5P^(V0!E`\#E`D&NY\"WT!8 +M``"\GY"@G3XC9`&4#P.4"0;=0%@``+N?`@\'O)V0H)_$Z0'T"PJ)```"_>D% +MM/`,21S"_^F4_YSEH(ZS\``-M-`)O]D^9V0!Q^G1]`L2M.`,L^0`##):,BM^ +MA30`M/`)"0>@^;*:^X40]##H^8*PL0FRH3+%,\0$#=DP&0``/HID`=DQ&0`` +M/YF4$P3>"&@1`;P^$)09!]X$8!$!OYV\'Q"4&0>\ +MGI"0GP2_F+__/AQE`3-4`S*/@!81V01H$0&-@.GNO!\0O#DPE!D$O!T0OYV_ +M.+]_WOR7[OZ\/C"P\0P^4&4!B0`7$=T$Z_>;P>$-_\E^[^O#\P/A%F`8D`%Q'=!'`1`;P9 +M$+P],)09!+^=OS^.`.GND#,$O!X0OSG?^(_N_KP_,,2?#S-0!`J]Y#XA9@'' +MG@RS]``0`@@S7037`+/M`"`(DOD!L)8"]0V#`+/P#W\S5`0EL_D("0BS^0<& +M`;/T``VSZ0#]`#Z)9@&S]`8*LO(^[F8!L_0%#3-=!-X'/NQF`3-4`PRS]`84 +M/D9N`3!6`O0,"0("L_`&-^39``+T&PF])#Z\9@$"![/P"B0"#K/P"QXS5`0, +ML_0$##Y.9P&S\`=.^`@"#3Z\9@$""#-4!$*S(`@4LR`&*K,@`B:S(``B/DYG +M`32@-_"D_WXB4P&SJ0`_![(:2Q$./O1F`0("LAJ+07X%?B5J`#X\:`$"`3-= +M`#P!E$\&E$D#WD!8``"\^0*\#@"8#P20!@PU90/$^03U&QP!Q/D"]!L:Q?D" +MM0D$V20```&_F9"9`;4)!SXP:P&8"@=^*6X`L*8"]`P,M)`)OYH^(FX!F`D$ +M#_W]GP2U"02S)`@TM)`.\)0/LY0&*K30#-D$:!$!O#G@Q]]P-6\#O^DR]8\` +M`/_]GP2@Z;]YH'D^/&@!C8`6$=X$:!$!O!T0O#Z@E!X$O^V_J;]YCX#I[KP? +M$,2?#[#V`_0-.;/P#S:2^04"`K"6`?0-")``#__?D$H,^_Z;!Q##+5`@B@Z3X\:`'X +M"+3@"I1/`Y1)!KN?`K_MWT!8``"\GY"@DC-4!$>5C!/$R0'U"\<%WC@9``"\ +MX9BSD``FV4`9```\D?B]E+SI&3/T``N)```"_=D%/?390!D``#R?&8D```C] +MV04^)6X!QXD5MI05_]GULR0("_#U`CZT:`$)_?WY!)1)!I1+`[R;PME`6``` +MO,G`&,X/QXD2MI02__G5,^0$)@_^_]_TM-`,Q]D,_?D%B?___?WY!,>)$;:4 +M$?_Y93X!:@$SZ0":`+RTDMY(6```MI0#O)Z0OYK%WP&)___]__EDLZT!ZP"8 +MP`3D"0`$]0O?`-]H8```WNA@``!_^W_MD$D!O*F4_YNU\),`>9D`_9T$8.E) +M__O_"91@^[7)!/"S``H-W-.+`0!^RTX`W5A@``"SI`$=O]G>X!D``'_O\94` +M(*#9\?4`"&#O/@%J`;_93__?_9\$H-D^`6H!WPAP$0&\/S"_.=[XC^[^O#XP +MQYX,]`L4V20```&_F9"9`;7)"3Z]:0&US@G?2%@``)1)`[N4`K:4`[R?D+^< +M#_Z)```"_]_T_^F5_Y]EL\0!(MFL8```?YZ03P&\S_3P\P!Y_P#]_@2]I&"? +M?KEM`)1/`Y1)!MU`6```NY\"O)V0F)X$">__:<3$Z03T"RZ2*0&PE@'T#07X +M")1)`Y1/!KOY`ME`6```O/GP"?O_Z92U^02)```B_VE`*\G9`UGP&TX`D)!Z#I/H%L`;/I +M`,D!E8\5Q/D!,Y``?XD```C_B93T&W0S5`1QWPA@$0&)``!@E!X'O._@CP`` +M(Z#IV?__`,[_B93]GP62[@2@Z8G`(@*\&1!)'_Z4'P?_V92-0-W]\)6PO!T0 +MH/FR&HM!?@5^)6H`O$3PE$D$WD18``"[GP(/!K:4`KR>D#6?`;3P";_Z/B)N +M`96+$_^_E?"4`?0;,#-4!"+9R&```#^9\)3_NY$'\)0!]1L?`<>I!/0;$CYX +M;`&TD`SPE`^SG04+`91)!I1/`[R?PME,6```O,G`21_^CP``(!C.`O^O]?WY +M!+20#/"4#[:4!?V?!4_NP_^?U#/@`!")```"_=D%/90UR0+$N0'T"T3>.!D` +M`+SA^(D```C]V06S\``RV4`9```\D?B]E+SI&3/P``^)```"_=D%/O)K`=G_ +M_P'__=D$/?390!D``#R?&;3@"K3P#(D``""@[?WY!3-4!!64&0?="&`1`;R= +MD*"?/C]L`3-4`PJ@?SX_;`'="'`1`1)9`;P]X#"6`?0-!:!_H.^\1/"4203> +M1%@``+N?`@\#MI0"O)Z0-9\!M-`)O$_TE$D&NY\"WT!8``"\GY`/`J"?"0.@ +MV3Z!;`&TX`F_ZCXB;@&T\`F_^9*9!;"6`?4-D0&TD`I,O0"_DC-4!#KD*0`" +M]`L9E$D$W20D``&\G9"_GX[___[]_@2@G]XH)``!E$D$O)Z0OY^.``#_3'\, +M_?X$H)_?3%@``)1-`Y1)!KN=`KR?D!B>`X\``/^)```O_XF5_9\$_\D%,^0` +M*+S4DMU(6```MI0#O)V0OYFPE@'T#1&SD`,.-*`W\*3_?D$A`+3@"\?IT?0; +M%<U3Z;:`$"`C[^9@$""#[49@&]]/0PK/F"_DD!D)EPH)^2 +MF0R@GY*9!*"?LJ,RL3.T!`W9,!D``#Z!;@'9,1D``#^9/).0,)%.-)!.$ID! +M,)%/,Q0$#;W$L,$4/N]N`3203]Y,6```\)3_E)\&MI0#N_D"O/[P&/\#,_0$ +M$Y0Y!]\(8!$!O)^0/N=N`90Y!#/T`Q#<"&@1`;R"'`1`;R>D+^9 +MQYD,L)$4-%!/C+[][X]"`A#>1%@``/!4_[Q?4)19!+Q<4+"1"[3`"[Q5\)19 +M!+N?`K_/MI0"O)Z0&)D!_D\!D/]T\)3_H/GU&WD&^`@^J74!&$T!Q-[_L.$2 +MH/XS%`0IOX_^20&0F62TP`R@G[20%;^?_DD!D)E@H)^_SY"9$*"?/JAO`?Y, +M`?Y.`?Y/`9#,<)#N9)#_8#,4`Q:_>:#IM.`6O^F@^;3P#3ZD;P&_::#IM.`7 +MO^F@^;3P#K_YH,FTD`N_G_Y)`9"9:*"?,]`'>S#6!_0,(3/0`U@PU@/T#`PS +MW0&N!3XD=0$PU@7U"*(%/@-P`3/0"V74!_D`!LCJ0`'0R'+(+?A)4`3XG<`$S%`0&^`C^20&0F62_ +MF<>9$#.0`"JTP!2SQ`$CW>Y@```)"#5)`3_?#@C^20&0F702_P&@GB#?/A5Q +M`;3@";_J?BEN`+&FT$F"\$W>Y@```)"#5)`3_>\/4$M2\$#P@2[@$@ +MWCY-<0$S%`0&^`C^3@&0[F2_Z<>9$#.0`%^T\!2S]`%8O^G?__\`SMW@&0`` +MW.Y@``#]GP2@Z;_OB0```_WY!:#OO^F@>;_IH&G9)````;^>"0XU20$_SW_9 +MD.X!M2X)$O\!\)4@(,]@V3#V`/4?800^=W4!M)`)OYI^*6X`L:9P%_4-3`28 +M+P3=[F````D%-4D!/][P]02U+P0/!1+N`2#>_DD!D)ETH)\PY@#U'R$$/G=U +M`9@J";.D``;X"+20"MQ(6```NY4"MI0#O)R0OYFSE`$0F"D$\90`!/0;!?@( +M?BEN`+&F9`#T#1$TH$_PI/]^%R(`/GEU`=_@&0``?_GPE2!@^3YY=0&8+P0) +MW__YU+4M!#,4!!R_C[3@%?Y)`9"99*"?O^^2F02@GSX)<@'^3@'^3P&0[F20 +M_V`S%`,6OWFTP!:@Z;_)M.`/H/D^#'(!OVFTP!>@Z;_)H/FTX!"_Z<23YB<@$2&0$PE@'T#0>_Z:!YO^F@:0D+L\`!%)+)`K"6 +M`?0-"+/-!.``"0FT\!&TX`N@*?Y-`;_YO^^_+I#=;*#?#_C]GP3_R06SY`L5 +MO]E/'_[]GP3PE4"@V3X_ +MO]F/```"Q^[1_9\%H-F_W[#F`/"<"S*<"?[]^02@W[_93__#_9\$H-D^R'0! +M_DD!D)EHOY]._\,]Q/W^!*"?_DT!D-UHO]Y/'_Z4N07QE.`!_>\$_9X%H-D) +M`;_?H"FTD`N@GPD'-4D!#P?^20&0F72@GS/``'TTH$XR.WZ%-``^>74!,Q`$ +M;+^9LY0%9@D'-4D!"0&@*3YI=0$S%`01M,`5O\G^20&0F6"_F;3@#/Y)`9"9 +M<+_OH)^_F?&4``+T"S'^3@&0[FB_Z0\"H"^T\`OQE0`"H.F_Z:#Y"0;3`%J#IO\D^TG8!OVF@Z;3@%[_I +MH/F_^<>2%?Y.`9#N9+_IC___O_V?!*#IO^G?``",`/V?!/0;"#,I`&$!M/`+ +M_DT!D-UH_DX!O_F0[F2@V;_4,Q0$%+_OO^G9``"``/_Y!#Z>=P&_Z;_OO^^. +M```$_YX$_?X$]`MIO]D/_?V?!*#9_DD!O]Z0F6"_F4\?_OWO!/"4#[:4!?V> +M!:#9,Q0!0K3`%K_)\)0/LY0%-K3@%[_I\)0/]!LJE%D#WTA8``"[E0*VE`.\ +MGY"_F;"6`?0-$;.0`PXTH$_PI/]^02$`E%D$O%7PW$18``"[GP*VE`*\G)`8 +MF0'$G?^2V06PE@'T#3BST`@6_DD!D)EDOYF/```(_9\$_0D%_DD!D)EDOYDS +M(``7_DD!CP``()"98+3@%:"?OYF@Z?Y/`9#_:+_Y_PF5H/FS``!5O_FT\`N@ +M^3,4!!+^20&0F62_F:")/DEX`3,4`Q+^20&0F62_F:!Y/DEX`?Y.`1(9`9#N +M9#"6`?0-![_IH'F_Z:!IQTG1]!L,-*!.,CM^A30`^X54O?3T,+SY@OY)`9"9 +M7*"?DID$H)^2F02@GY*9!*"?WV`"$`&_^;"1#O"4`;"1"?0+$+3`#@G^_X!D``-DR&0``?^\_F;W4_D8!\?3?__Y(`6#O,)$V/>2PT0R]-##A +M-Y!F6)"(7#ZVAP'9,!D``#3`-C^?)L_T"#/9+AD``#^9Q/[_,L_P]/_PE/^\ +MGI"F^?0?&=DD$!`!OYD-!+S^,C#1-["1&#[+>@'>,1D``#20-C_O)I_U"+0! +MV2\9```TX#8_F<3]__#D__"4_[R=D*;I]1^8`<1<_[S,\)3)!+N?`M]$6``` +MMI0"O)^0O.TR&)L!E,\#E,D&W4Q8``"[GP*\G9`8F0,PD3<2N04PE@'T#`@] +MY##A-S.T#324SP.4R0:[GP+?0%@``+R?D)B:"[.I`!P.?BEN`+&FR`#U#0\. +MQ%K_?C]2`3ZMAP$TD#Y@```_F3.=`,4`W:!@```_V3.9`)L-/LMZ`320-Q*9`3"6`?0,=)0_ +M!-X$:!$!O/[0O]F0[@2\_O`.`:!IO_F[XP2PD16_::#9M)`5H/G9+!`0`;^9 +ML)$8M)`8_>D$]!MLV>Y@```_F3.4`&+?H&```#_Y,Y0`5Y3)!I3/`]Q`6``` +MNY\"O)R0F)D$\90`"/4+'0T^RWH!V2P0$`&_GPD!NY,$L/$8M/`8_9\$]!L> +MV>Y@```_F3.4`!3=H&```#_9,Y0`"3.]#N<,WJ!@```_Z3"6`/0>$-GN8``` +M/YDPE@#T'P7X",12_Y0I`Y0O!KOY`ME`6```O/GP&/D,,Y``&MDD(``!OYGP +ME`'T&PPTH#8R.WZ%-``TP#!?@(E"D&E"\#W$Q8``"\GQ*\'!`8&0'PE`+U"X$`W20D +M``&4(`2\#0"_"=[Y@```_F3.4`#N\(I"4+P3>1%@` +M`+OY`K;T`KS^\!CY`3.0#B"4*0.4+P:[^0+90%@``+SY\)CY!/&4``CU"^4* +MW#`9```TT#8_SR;?]`@IV2X9```_F?#T_S+>\.3_\)3_O)^0INGT'P_9ZF`` +M`#^9,YT`L0HTX#\ +M[>"_Z9#N!-_XG^[^H&F_Z;SOX+"1%;]IQYD>,Y``>CZ??0$TD#>4/@0SE`,C +MC(`6$=T$:!$!O#PPO.W@E#D$D.\$OYF,@.GN/HU]`8T`%Q&\/3"4.02_F=\$ +MO"*0E"\$WD18``"[^0()`[;T`KS^\#7Y`0\!L/$,/JV'`=D48!$!O.G@ +MO^^4*03<*"0``;R^P +MD1FTD!F\+R"PD0LSQ`0D#X) +M@`$S1`,7OV^4.03"@Z3Y`@`&_:=\$:!$!O._@N.\`"`"@Z;]IH/F4*0.4+P:[^0+90%@``+SY +M\)CY!/&4`!#T"PNR.@L!?F`D`)0I!I0O`]Q`6```NY\"O)R0/M:!`;]OV0`` +M`,Z4/@?=!&`1`?WY!*!OOVF\[>"0[P2-P"("\)40H&F_:;P],)0]!Z#IB0`` +M(*#YOXE/__V.0-W]O#XP_9\$H(F_B4\?_OV?!/"5@*")OXGPE1"@B;^)H-D) +M"C7)`3ZZB`&4.0??"&`1`;R?D+^9L)$5/K^"`=DQ&0``-,`V/Y\FS_4(NP?9 +M+QD``#^9\/3_,L[PY/_PE/^\GY"FZ?4?H`>4,03="&@1`=X(S] +M_W^4+`.4+@;]^02P\1FTT!FTD!6[[`+<0%@``+SLX)CN!/"4#T\?_K:4!?W? +M!/V=!;"1&?'D`!#T"PNR.@L!?F`D`)0N`Y0I!KN>`MY`6```O)Z0O=2@G;6= +M!+PBD)0O!+OY`ME$6```MO0"O/GP"0$U^0$S1`0;C,`B`HU`W?V\/#"4.0>\ +M/3"_F3[=@P$S1`,;CH`6$8^`Z>Z\/C"4.02\/S"_F3[=@P&)`!<1O#DPE#D$ +MOYF,`.GNO#PPW3`9```TX#8_WZ"))N_U"*8`V2X9```_F?#T__#D__"4_[R? +MD*;I]1^-`#-$!!.4.0??"&`1`;R?D#XJA`$S1`,7E#D$W`AH$0&\G)"/```@ +M/F.$`1))`90^!#"6`?0,%=T(^\/#"4/@?]^02@C[^) +MO#TPH.D^QH0!V01H$0&4/P2\^>"_Z8W__^_A0$S1`05E#D'W@1@$0&_;[R> +MD#[XA`$S1`,7OV^4.03"@Z3XOA0&_:=\$:!$!O._@N.\`"`"@Z;]IH/FTD!F/```0M,`*_9\% +ML)$9M)`9#_?]GP2PD1FTD!E/'_[]GP3PE8"PD1FTD!F@R;,-`$\"M)`9QYG1 +M]0M$`C2@-C([?H4T`#ZMAP'X"#ZMAP&4*0.4+P;=0%@``+OY`KS]\+_YLY0` +M';20%8\``$#]GP3T&P^_:8\```+]GP3T"Q*_B?&4``+U&U,!,^D-3P$TX#4/@0SE`,0W`1H$0&\[.`^]84!W01P +M$0&\[>"_Z:!IOVDTX#>/___O_9\$H&DSY`05E#D'W`1@$0&_;[R!&@1`;R>D*"?/FJ&`320-Y0^!!*9`3"6`?0,$[]IWP1P +M$0&\[^"@Z3YJA@&_:=P$:!$!O.S@N.\`"`"@Z;]IH/F)```@L)$5M.`5E#D' +MW0A@$0&\G9"4+P.@GI0I!MY`6```NY\"O)Z0F)D$\90`$/0+"[(Z"P%^8"0` +MO"+PE"D$NY\"WT18``"VE`*\GY`8G@&4+P.4*0;<0%@``+N?`KWTO)R0M9\$ +M$NX+,.8!]0S6`-_N8```/_D2F0$@^?0?!?@(O"+PE"D$W418``"[GP(/![:4 +M`KR=D#6?`3ZMAP$TX#R.GY2;@$.`;#A##3P-A#_ +M`3#Q-MPS&0``-%`V/\D250$F6?4(!_%^D!\`V3(9```_GMDQ&0``/Y^]Q-DS +M&0``$NX!\/3_/Y"2^@&]M#XGB`$8F0$2F0LPE@'T#`VFVO0?!?@(D,P!E-D& +ME-\#W4!8``"[GP*\G9`8F0P0[@$SE`$'D+L!Q.W_O-WPE-D$NY\"WT18``"V +ME`*\GY`FX/0(L]GN8```/YG$S__PD@>F^?0+!?@(V:!@```_F<2___"2!Z;Y +M]`L%^`BTD`FSD``0WV`"$`&_^?"5`:#YM*`,^X5$L)$4M)`4QYD4,YD`%_8^ +MH'X!E#D$W0AP$0&\G9"_F;"1%33`-MDP&0``/Y\FS_4(0?@^BW\!E"D$O"+P +MWD18``"[GP*VE`*\GI`8F0$SG0JI_#ZMAP'X```````````````````````` +M`````````````````````````/@`V6AF``"_G[/P!`;X"-GH$``!OYH^:8D! +ML_`$#+/T!DD^-(D!V6AF``"8F0.SD``&^96]Y-GH$``!H)[=Y!```9"9!*"> +MO]_9````@`P!LLK]^02@W]GP$``!H)[9:&8``*"<^`#X"+/T`+&]I/@`^1+1 +MZ!```;\>E>`8L`8/]`PDD`\#V6AF``"\GYBSD``6VO___P#_ZJ3YE;,$`QD^ +MQ8D!^`@/`=EH9@``O:2@GSX4B@&S``40LP`'#+,`"`BS!`LGO?39Z!```:"? +MD)D$WN00``&@FK_IWP```"#]GP6@Z3X)B@'=Y!```;_9WP```("]Y/V?!*#9 +MH![9[!```:">D)D$H)X/`=EH9@``LOJ@G_L1V6AF``"8F0*SD``(?L1-`-YD +M9@``/^DSD``GV?`0``&_GSV4(.GP]/_T&P?X"/@`L_0!"GX"B0'X`'YQB0'X +M`/@(B8`@!::I]`T%^`C9J&```*":V@```(#X`/@(B8`@!::I]`T%^`C9J&`` +M`*":V@```(#X`(G`U`&FJ?0+!?@(V:1@``"_F;.>X"XVO>3?`&`1`=PN&0`` +MC>___3[*B@&_^9#N`?V=!*#YF/D"M?D"D/^`/\GPE/^FZ?0(YMFD8```H)I/ +MF#K9/``0`=H```"`H)_X`/E2VTA8```,`=4P&0``U````$`#[](Q&0``T2\9 +M``#0+AD``+RLE?"4`?0+5+^YLY0!3S]9Q)__IL_T"!P_";S/XL2=_[S?D*;) +M]!@,INWT"!L^5(L!/RD_'_"4__#T_[S)XJ;O]`@%^`B)@!81O.G@E.\$O_G] +ME`7]DP2@^9#,`9"[.+/$":"]I/M1O93?P&```*#YMJ48LZZ!`$N/P-0!V:1@ +M``"@GT^8.MD\`!`!O>2@G]PN&0``WP!@$0&-[__]/L6+`;_YD.X!_9T$H/F8 +M^0*U^0*0_X`_R?"4_Z;I]`CFO:3X`+VD^`"5J1BSGH``1N>JP0+T&P7X"-]% +M6```#0X^"8P!Q*D!]`L-O^D@_?&5``2@Z;:E`9#_.)#^"[.D`.??X!D``'_Y +M\)4@8/D^(HP!^`B]I/@`LZK@+@?X"'[J'@"SI`4+V@```('X`$_@+MFD8``` +MH)_:````@$],'=D\`!`!H)_X`'Z0'P"]I/@`E:D8LYJ```?X"-G___\`_:D$ +MB<#4`::I]`L%^`C=X!D``'_?V\?4`"-FD8```8-^@F@H!^`#9 +MY&```+WTH)_9____`/E2_ZGTV:1@``"@G[:E&+.N@`!A@``!@G]H```"`^S'9____`/VI!-E`6```E*X&MJ0#N^H"O.G@V3`9 +M```_G=DN&0``/YF8[P3PU/^2W`'PE/_Q]0`!O)VPE,D&M>\$DKT!E,\#O)_R +MV5!8``"\^?`^&HX!O_F0_SCDG@`!\)2`,Y``)K/D`"+>6&```-W@&0``O^E_ +MW_&5``+Q]0`(H.E@WSX?C@&0S`&FS?0(R9*Y`:;)]`@2V5A@``"_GT[__?W^ +M!*"?O:3X`-GJ8```/YDSD``&^`A^-6L`#P'9ZF```-H```"`()_X`+V4&)ET +M,Y``"KVD?KEM`-H```"`^`#9ZF```#^9,Y0`!O@(VI@```@ +MGS/@``_9$&(``#^9,Y``"'[?:P#:````@/@`^``````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````/DRV3`9```_GI2O`Y2I!K*@NY\" +M\.3_WTQ8``"0H@&\GY`8DP.F+O0('-DN&0``/YG$G_^\_I"F*?08"KRNDCY: +MCP'9,1D``-\O&0``/YD___"4__#T_[P)DI"1`:8?]`@%^`B4"0:4#P.\G_+9 +M0%@``+SY\)CY!/"40/0+);_YLY0((,0[_SW$LAI^$B,`L@H]M'Z7(P"R&L0[ +M_WY&(P"4#P/>2%@``+SPDK:4`[R>D+^=L]``"+/4`WF4#P.4"0:[GP+?0%@` +M`+R?D)B:";.D``;X"'XI;@"QIF0`]`T-L@I^%R(`/D^1`90/`Y0.!KOO`M]` +M6```O._@O`#PE`D$NY\"WT18``"VE`*\GY`/#C6?`3V4W.`9``"0[0PUV0-_ +MR0\$H._PE2!@R3Y/D0&SW0&U`-Y`6```E`D&NY\"O)Z0F)X$#P2@GY"9##WT +M-9\#\>0`!/0;9MGH8```?YN\TO0*#-S7BP$`_;\%8)OPLP!^RTX`W5A@``"S +MI`$=O]G>X!D``'_O\94`$*#9\?4`"&#O/J*0`;_93__O_9\$H-F\`/"4"02[ +MGP+?1%@``+:4`KR?D`\'/MZ0`=W@&0``?]Z\`/"4"02[GP+PY2"VE`)@W@\. +MWD18``"\GI`UGP$^3Y$!L@I^02$`O`"0E`\$N_D"V418``"V]`*\^?`8^0$S +MD`L0W^Y@```_^1"9`2#YV>Y@```_F3"6`/02`=D(9Z/0+#<2:_WY( +MJP#$J?_$FG^S)`,;CY`6$;P/`)0)!*":B7#I[KP)`#ZODP&-$!<1C_#H[KP- +M`)0)!+P/`*":E!D#W4A8``"[D0*VE`.\G9"_F;.9`*P"LR0$%=\$8!$!E`D' +MO)^0OY\^^9,!E`\$LR0#$-D$:!$!O/GP/O>3`=T$!+,D!!^4"0??!&`1`;R?D*">B<`B`KP)`)0/!SX^E`&S)`,FCX`6$90) +M!-T$:!$!O`\`O)V0E`\$H)Z_^4E0`J#Y/I"4`9(K`90/!+"V`?0,$=D$!KOI`KSMX)CO!+P1T)09!+N=`O#U(+7O!-]$6```MI0"O)^0 +M#PDUGP$^J98!L\T/D@&4'P.4&0;=0%@``+N?`KR=D)B?!/#U`;6?!+,D!!7? +M!&`1`90)![R?D+^?/FB5`90/!+,D`Q#9!&@1`;SY\#YFE0'=!'`1`;S]\+__ +MV?__`,[_^93EG@"`LR0$$Y0)!]\$8!$!O)^0/MB5`;,D`RB4"02-@!81WP1H +M$0&\GY"\#0"@GHV`Z>Z4"02\#0"_F3[ME0&2*0&4#P2PE@'T#!'9!'`1`;SY +M\*#^/MJ5`=T$:!$!O/WPH/ZX^0`(`*">CP`7$;P/`)0)!+^9C0#I[KP-`.6? +M\`&S)`02B<`B`KP)`)0)!SXTE@&S)`,2C8`6$;P-`)0)!#XTE@&-`!<1DBD! +MO`W@L)8!]`T/B8`6$;P)`)0)!*"?E.D$H)\^J98!OTE/'_Z4'@3'W=']GP2/ +M``!`_9\%WR0D``&@2;SOX+_I#_C]GP3PE0&@Z;/=`+7\/O:2`;])3Q_^_9\$ +M\)5`H$F_.0_X_9\$\)4!H#D^J98!B0`7$;P)`)0.!+_IC0#I[KP-`+"V`?4, +MWOT^>)0!^T'X```````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````^4+9,!D``(U"`A`_GK*BO"T@E"0$OT.4KP/=0%@``)2I!O#D_[N?`H^^ +M_>^\G9"\+R"8G`60+0&FWO0('-DN&0``/YG$G_^\_I"FV?08"KPNDCYMEP'9 +M,1D``-\O&0``/YD___"4__#T_[PIDI"0`:8/]`@%^`C'SPGU"Y,`QSD)]1N, +M`-D$:!$!E`\$O/G@O^F,___OW01P$0&\_?#PE8#]G`2@Z;_YC8`6$;P-`)0+ +M!/"5@/V#P.4*02\(L#>1%@``+N< +M`K:4`KR>D#6?`;PO])0I!KN?`M]`6```O)^0#P*@GTD?_O\YE/&5H`*@23X) +MF0''.0GU"_D`L_T`]0"4*0:4+P.\GQ+90%@``+P9$)@9!!@;#_"40/0+(?"T +M_SW$L@I^$B,`LBH]M'Z7(P"8&00/O_V?!+49!(V`%A&\#0"4#@2_Z4\?_)`` +M@)0-!/V?!/"5D*#IH-G9!&@1`8X`Z>Z\#@"4#02\V?"_^=X$ +MT/V]`@@+,D!":4"0>/P"("W01@$0&\G9"\ +M#P"@GH]`W?V4"0>\#P`^'9P!LR0#(Y0)!(V`%A'?!&@1`;R?D+P-`*">C8#I +M[I0)!#X:G`&2*0&4#P2PE@'T#!'9!'`1`;SY\*#^/@R<`=T$:!$!O/WPH/ZX +M^0`(`*">/@R<`8G`(@*\"0"4"0<^JYL!LR0#$HV`%A&\#0"4"00^JYL!C0`7 +M$9(I`;P-X+"6`?0-#XF`%A&\"0"4"02@GY3I!*"?O!&0E!\$W418``"[^0() +M"+;T`KS]\#7Y`3[UFP&R&GY!(0#=[F```#_?O!'@E!D$NYX"$/\!(-_?1%@` +M`+:4`KR?D`\+-9\!E!\#E!D&W4!8``"[GP*\G9`/#Z"?^R&/`!<1C0#I[KP/ +M`)0)!+P-`+^?21_^__F4Q9_PLRT$4O\^;)L!^``````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````V3`9``#Y(C^=B4("$+*AO!D0E!D$OYN4K@.)OOWOE*\&O!D0 +MN_X"V4!8``#PU/^\^?"0'@&8_`6F[?0('-DN&0``/YG$G_^\_9"FZ?08"KP= +MDCYMG0'9,1D``-\O&0``/YD___"4__#T_[P9DI"0`:8/]`@%^`B4&0.4'P:\ +M^2*]E-]`6```O"\@M2D*Q\EELY0#7K(*O;1^8"0`E`D'WPA@$0&\GY"_F?"4 +M#_0;#;(:?IXF`#Z:G@&R"@L$O<1^$R``F"X$O!'PE!D$NY\"#^_PY0C][P3? +M1%@``+:4`K4N!+R?D`\'-9\!/IJ>`;.=!94`Q[D!]1ND`+\ILY0(!O@(WP1@ +M$0&4#@>\[^"\$?"4&02[GP+?1%@``+:4`KR?D`\#-9\!O^F/P"("O`\`WP`` +M`,[]GP3QE7\,E`T'H.F)0-W]O]^\"0"4&0.R"I00!KL)`ME`6```O`D`"0*@ +M"4D?_OWY!/#UL(M!?@6@WWXE:@"8"01/?__]GP2U"00^FIX!LY0`%PL$L@J] +MQ'X3(`"R"DL1#GXE:@#[(?@````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````")0@(0^3*RH;P9$-DP&0``E!,$ +M/YF_.X^^_>^\'Q#$G_^0'0&FW_0()-DN&0``/YG$GO^\[Y"FV?08$KP?DI"0 +M`:8.]`@H/FF?`=DQ&0``WR\9```_F3__\)3_\/3_O!F2D)`!I@_T"`7X"-D( +M8!$!E`X'O.D@ORG'O`3T&P7X")0?`Y09!KR?TM]`6```O-_0F-\$O92UV0I) +M]^_]^02UWP2_*:`IL\0`"L2Y`379#MD$8!$!O.G@O^F/P"("O`\`WP```,Z4 +M#0?]GP3PE2&@Z;_?B4#=_;P)`$D?_OWY!/#UL+(*H-^+07X%?B5J`+V4WR0D +M``&R"I00!+P/`*`)V=S;__Z]M+P)`'Y@)`"\$9"["0()!M]$6```M@0"O`\` +M-0D!ORF_.90?`Y09!KN?`M]`6```O)^0#P2@G_LQ^``````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````````````````````````````/DB +MV3`9```_F;*BD*T!Q)__IM_T""39+AD``#^9Q)[_O.^0IMGT&!*\KY*0F@&F +MKO08)CY8H0'9,1D``-\O&0``/YD___"4__#T_[PIDI":`::O]`@%^`B4K@?< +M"&`1`;SLD+^?OY^-P"("O*V@E*T'H)^_V8]`W?V\KZ!/'_Z2S`3]GP2\[.#Q +ME3`!H-F_[]D```#.W-S;__Z]%/WY!-DD)``!\/4AH.^4(`2]M+P)`*`!O`P` +M?F`D`+PBD)0O`[L)`I0I!KN?`M]`6```W418``"\GY`/!=S@&0``M@0"O`T` +MF)T$-0\!D)\,-?$!?\ZUD0I/]^_]WP3PY2"UG01@SOLA^``````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````^3+9,!D``(U"`A`_GK*AO!T0E!,$OS*4KP/=0%@` +M`)2I!O#D_[N?`H^^_>^\G9"\'Q"8G`60'0&FWO0('-DN&0``/YG$G_^\_I"F +MV?08"KP>DCYMHP'9,1D``-\O&0``/YD___"4__#T_[P9DI":`::O]`@%^`C' +MP`GU"Y\`QRD)]1N8`)2N!]\$8!$!O._@O^F/___OC<`B`KRMH/V?!*#IO^F/ +M0-W]E*T'O*^@WP```,[]GP3QE7\,H.F_WPGO0!_^BT%^!?'U``+]^02@W[_9 +M_9`$\)6PH-E^)6H`O!'PE!D$W418``"[GP(/`[:4`KR=D#6?`;P?])09!KN? +M`M]`6```_R`$O)^0\06@`@\"H#"@GSX+I0''*0GU"^\`LPT`ZP")P"("C4#= +M_;RIH-\$8!$!E*L'O*V@O[R4K@>\[^"_Z8\0<^^4'03]GP2@Z4D?_/W)!-DD +M)``!\,60O-G@H+R_[[P1D+O9`HG___[]^00)`:#OMM0"WT18``"\W]`UV0&4 +M&0.4'@:[Z0+90%@``$__P[SIX(D,//__*93PE8#]GP2@.9CI!*#@\90`$/0+ +M"0L!?F`D`+P1\)09!-U$6```NY\"MI0"O)V0&)X!E!\#E!D&NY\"WT!8``"\ +MGY"]]+6?!!+N"S#F`?0,#]_N8```/_D2F0$@^=GN8```/YDPE@#T'P7X"/LQ +M^``````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````````````^0+9,!D``#^9LJ"0K0'$G_^FW_0()-DN&0`` +M/YG$GO^\[Y"FV?08$KRODI":`::N]`@H/E:F`=DQ&0``WR\9```_F3__\)3_ +M\/3_O`F2D)H!IJ_T"`7X"-D$8!$!E*X'O.G@O^F/P"("O*^@WP```,Z4K`?] +MGP3PE1"@Z;_/21_^E`T#E`X&_?D$N^T"\/60V4!8``"@S[SIX)CN!+P`\)0) +M!+N?`M]$6```MI0"O)^0#P@UGP'QY``0B4#=_;RIH+/@``H+`7Y@)`"4#P.4 +M"0:[GP+?0%@``+R?D)B>!+WTM9\*3_?O_>\$M9X$^P'X```````````````` +M`````+^O^2*8K@&RH)BB",3Y![.0`0FSG0.&`0GX__F4\)4!H`G$Z0CU&W0! +MQ_F*]`L9V<`V``"8FP&R"K:U$'[&0@"SJ0%9`9@/"-D```H(__F4]`L1B0`` +M$/_YE;4)"#Z9J`&R"G[A>`"8"0C?P#8``)61',><:+7Q'[7\';,4`0\)!K7Y +M'@D"/I&G`0D'M?D>"0&U^2#'*1+T"RW'*1,*#O4;_`"S%`$-WR4:```^M:'!H``-T?&@``/.R8/-SXTP#8``/WY!/Y%`=D````1LN/_^66_X+T4!`'8+!D``-``0``)CO"PD!M3DXY/D`@'.9`'X"B?]____YE-K0-@``M>D+?F:T`+.I +M`&8"/DVJ`9@Q!K,9`&`"F!D(QYD-]1M5`K\?F!(!Q/D'LY0#)5@Z"0GX__F4 +M\)4!H!E^^7L`LZ``%;(:O;1^G`@`/LNJ`;.=`20"Q"\(]`L+`00`"S[NK`'2 +MB5P``#\IH%_'F0'T&RBTL`JP40#:`*`@$``'Z&1P"_6;.4``L_ +M*?"5`B`IOUFSE`,2LAH!!'X`IP&RH#[NK`$!!+.=!\L!^`@!!#[NK`&8/QV8 +M/B#9\!D``+(!O)^8``VUG@@^[JP!F#D'`0C'F0+U&S(`"0?0Q$@$+/NRL`0$-/NRL`0$'``8^[JP!`0,^[JP!`00`!:80]1M9_-G` +M-@``H)&S%`%XV8E<```_F?"4`?0+:M\`IP$`V?___P"R^MN=J`$`N[\"_?D$ +M_D`!W0```"&0`"S__=6P`0`,(=X"`0``?H9'`+\`LP0'"O@(/F6M`;,$`A;? +MX!D``'_YLA3PE1!@^3YSK0&S```&^`C?B5P``#_Y\)3^(/FR2O0P!/N%"/@` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````#X`+WT +M]##XO>3Y>40``+`1`#"1!+(L#4!^.\(`#@2SJ0#8`+\YM1((#@0` +M!;49!;])M1D&/MVO`1@9$#.9`*<`/92R#C49$``(/MVO`9@:"+WTF*D)M1D' +MF*D(F*X*M:\)M:\._9<$M:\/M:D(Q^D7]`L@F*D&MI48DID(L)8"]`T1OUE_ +M;_"5`O#U`J!98&_'Z5CT"PD+`GY^"0"_.0X(QYD"]!M1#@@`!C[=KP&8&068 +M&P:8'`@*\/^:I`D!WGE$``"P$0`PD00-0'X[P@`.!K.@`"4`!S[=KP$8&1`S +ME``*L@X^W:\!F!D'L@Z@.3V4-1D0``.FX/4;5_ZU'@.]I#[NKP$*`?0P"/MU +M")BI!OD2LJ&5D!CT"PK$"8`SD``&^`B8&0K'F5CT"PNR&KVT?GX)`+,)$:`` +ML`81]`PEL`8*]`P7L`8(]1BG`+,``3RS#0*"`#[6L`&S!!!Y/FFP`;,`%%*P +M!A3T#!"S"1*$`+,$$V(^N[`!L`86]`Q7/KNP`;VD/MBP`;\9QYF*]`MBF!\- +MQ_DTL)8!]`U6B?__S[(*__F4CP``(/V?!;49#3[8L`&8'PV_'@GX_>D$B?__ +MS_#E!/WY!+4?#:`>"@(^V+`!^`B8'PV_'@GX_>D$B?__S_#E`OWY!+4?#3ZQ +ML`$*`?L1OZGY`K*]]##\LL#'F8KT&QV8J0>8KPC>____!_V>!,?_E;;T&_WY +M!;6O!YBI")BN!M___P'P_9\$CP``#/V?!=____\`M:D(_>\$M:X&E9P.!H``)@9`3SL^+W4M1P$ +M/.W)_[F6\/3_M1T#M1D!=1\$#18^L;4!LNRPQ@+T#<+9`"```+6`[/D`!N8&03? +M-%L``+SYF+.0`".R#0`?/KFU`9@9!-],6P``O/F8LY``#+(-`"`^N;4!F!P' +MF!\(O92U%!RU'!6U'Q:U&0FSY``EF!D$WQP:``#N`O^?Q;4<"[/@`!4)\/^I +ME+B9`"``M9P,/D&T`9@;"@T,?M@'`)@?`U@>!-DT7```OYN0_P%VY0&U'P-U +M'@2R7;`Q`-H`M@$`#"'>B4P``'Z&1P"_.0T;LYT`/@'?,%P``#_Y#1L`%_"4 +M_2#Y/KFU`;\YLYD"*0&SG0"U_@(^1K4!^`BR#0`=/KFU`=HX(```O;1^`JX!LZ``8)@9`U@?!+(-`!Z0 +MF0%V]0&U&0-U'P0^N;4!V3@@``"8GP%)``'H&Z__Z!?M1X0OU^U'Q&SY``+OUFSF0`!!,?I`O0+(!@?)`GP_^F4N)0` +M(`"U%!0S_0'*`[(N#0(^>;L!"0&R+C49/0T"/MRW`1@9)#.4``RR+@T#/N6X +M`9@9$)@<$9@4%+49$K4<$YA/#IA.#[44%:!OH%ZU'A&U'Q#'^0+T&PVR+@T# +M``0^>[L!"?"R+O_YE`T#N)D`(`"U&10^>;L!&!D]F!P",Y0`$Y@9%::<]!L* +MF!,#/A*X`;+#OVF_6PKPL!$`_YJD"0*R/#"1!`U`WG)$``!^.\(`LZ0`#+(N +M#00^>[L!OVRU$Q0-!``%M1P0OUZU'A&R+CY[NP$8&3PSE``,LBX-!3Y[NP$8 +M&3T]]#4?/#.9``L#F!D4-1\]F!\0#/>8F0[]G`2FG_4+\P*R+@T%/E6[`9@9 +M$)@;$9@<%`KP_YJD"0&P$0`PD00-0-YR1```?CO"`+.I`)`"L@VR+@`'/GN[ +M`1@9/#.9`'X"F!\2/90U&3RS]``,LBX-!SY+NP$8&3XSE`$.LBX-!P`@/GN[ +M`9@>%9@?$I@9$PT'M1X4M1\0M1D1LBX^5;L!&!DDOQ\2F0$U&22S\``[F!H4 +MF!L0F!P1LHWY];.@`Q"SH`02LZ0"(CZ4NP$`(#Z6NP$8'R0)"+VDM1D.$/\! +M-1\D/HZ[`;(N#0@`"CY[NP&8%!2820:VE1CT"PR820:PE@#T'P\8&20SF0`` +M`CY1NP&830Z83P^8'A`,]Z!MH%__W)2FGO0;'Y@9$:;Y]!L7F!D'F!X(O?2R +M#:"?H.^R+CXUN@&8'`>_R::>]!L6F!X(F!\1O^FFG_0;":#-OU^@[Y@9$K.9 +M`)P!QYD"]`LPF!D4F)\.Q_D"]`LDF!T5F-X.Q^D"]0M\`[L!WO`9$`&_Z?"4 +M`O0;"[(N#0L^>[L!LBX-"P`4/GN[`9@9`9@4%+.9`!H!F!L0F!P1F!T5LDKY +ME;.@`AZSJ0,$`;.D`528'A#'Z0+U&_4`F!<1/GRZ`9@9$,>9`O0;"[(N#10^ +MJKH!F$H+LFNR7+:E&'YA-@"SI``&^`B820R_;[]7#12VE1NVE`:\G^"@;@`1 +M/GN[`?@(/EN[`9@<%`D!L!$`,)$$LBJR>PU`WG)$``!^.\(`LZ``;[(-LBX` +M$CY[NP$8&3PSD`!>F!D0/?0U'SS'F0+T"QF820R82@NVE1NVI1AVI`;]J05^ +M$38`L@VR+CY?NP&8&1*SD``3F!\5F!P3M1D0M1\4M1P1&!DD,Y``0Y@9$K.4 +M`""R+@T,/DN[`?@(LBZR#3Y[NP&R+@T>``(^>[L!L@VR+@`#/GN[`;(N#10` +M##Y[NP&R+@T*/GN[`;(-LBX^Y;@!LBX-!0`(LN*FT/4;K_JU'0Z]I#Z.NP$* +M`?0P"/N%"``#LBX-"#Y[NP'X```````````````````````````````````` +M```````````````````````````````````````````````````````````` +M`````````````````````````````````-[@&0``?^_T,.S9T&4``/F"\?3_ +M^_0P^#^2/;1@[SZPVP$S*2+K'#`F(O4,_@`S*1&A#3`F$?0,>#,I"$D&,"8( +M]`PX,RD$_P(P)@3T#!@S*0)6`C`F`O4,O`(S+0%1'SYBO@$S*09A!-'090`` +M,"8&]0S/!#ZNOP$S*0S]"#`F#/0,$S,I"F\',"8*]0SQ!SX-PP$S*0[]"C`F +M#O4(@0HS*0_+"S,M$`H4,"89]`PX,RD5#1,P)A7T#!@S*1,@ +M$M'090``,"83]0R\$CY#R@$S*1<'%-'090``,"87]0QY%#ZGT`$S*1TK&#`F +M'?0,&#,I&Y<5T=!E```P)AOU#`D6/E?2`3,I'Q,9,"8?]0C2&#,I('@9,RTA +MC1X^%]@!,RDS#0XP)C/U#+$`,RDJ?08P)BKT#%HS*28V`S`F)O0,*3,I)&P= +M_DH!_DT!T=!E``"0JCR0W330Q&4``#`F)/4,O0(^8=H!,RDH803^2@'^30'1 +MT&4``)"J/)#=--#$90``,"8H]0S)!3YXP0$S*2Z3"C`F+O0,*3,I+!<)_DH! +M_DT!T=!E``"0JCR0W330Q&4``#`F+/4,#PH^7L8!,RDPQPLP)C#U"$\+,RDQ +MJ`PS+3+4'3[IR@$S*3SM%3`F//0,/3,I-SX/,"8W]`P8,RDU>P[1T&4``#`F +M-?4,WPX^ILL!,RDY&Q`P)CGU"(``0``)CO#\3Y`_0+%#(K20/_`@+_^92UZ0\^L-L!W6!F``#4`!"#?8,X^O=L!V5`@``&_F?Y.`9#N/*#IV50@ +M``&_G_Y)`9"9.*"?O^GPE#_T"P7X"/Y)`9"9/+^:DID$OYN]E``"L)$`,`$$ +MW.!E```-$-XOQ```?CO"`+.@``PR"P(#/K#;`=_@&0``?_DR"_&5``1@^3ZP +MVP'?T&4``%CY''"6`/0>%M_@&0``?_D+`_&5``1@^3ZPVP'QE/]_"P-U^1P" +M!#ZPVP'9T&4``)B>!)B=!?Y/`?Y)`9#_/)"9.*#^H)V_^?"4/_0+!?@(_DD! +MD)D\OYJ2F02_F[V4L)$`"0+<\&4``#"1!`T0WB_$``!^.\(`LZ``#`L$`@4^ +ML-L!W^`9``!_^0L$\94`!&#Y/K#;`5@9''"6`/0>%M_@&0``?_D+!?&5``1@ +M^3ZPVP&8'@B8'PGQE/]_=1DD/ +M`B4^L-L!F!D&F!L'OPP/\*"I"0B@V;_9WB_$``"0F0_]GP2@V;^JO]V]E+"1 +M``D",)$$?CO"`+.@``P+)0(F/K#;`=_@&0``?_D+)?&5``1@^3ZPVP'?T&4` +M`%C]'-G$90``OYYPU@#T'A;?X!D``'_Y,BOQE0`$8/D^L-L!Y-G_?W7Y'+_O +MV0`F``$+"++JH)^8[P&0F02@GW[#VP$R*P(G/K#;`=S$90``V0`F``&_S[^9 +MW=!E``#^2@&0JCR@^=D$)@`!OYG^3@&0[C2U^0&8V0:8VP>_S*"I"0B@Z;_O +MO92PD0`)`S"1!)#_#PGP_?D$H.^_JK_MWB_$``!^.\(`LZ``#`L&`@<^L-L! +MW^`9``!_^0L&\94`!&#Y/K#;`5@?''#V`/0>%M_@&0``?_D+!_&5``1@^3ZP +MVP'9Q&4``+^:Y/G_?PL(=1D_ +M#+R?D*"IH-._V0_PWB_$``"0F0_]GP2@V;^JO]V]E+"1``D",)$$?CO"`+.@ +M``PR,@LG/K#;`=_@&0``?_D+)_&5``1@^3ZPVP'?T&4``%CY''"6`/0>%M_@ +M&0``?_D+*/&5``1@^3ZPVP'0Q&4``+\*\93_?PLH=?D+\0``#"1!'X[P@"S +MH``,"P@""3ZPVP'?X!D``'_Y"PCQE0`$8/D^L-L!T-!E``!8#QQP]@#T'A;? +MX!D``'_Y"PGQE0`$8/D^L-L!V<1E``"_FN3Y_W\+*'4)''[#VP'9)````;^9 +M"PD""I"9`;4)(3ZPVP$)0)@?!J"IOZF8&P>_#-XOQ```O)^0H*E)(`&@V;_9 +M#_"0F0_]GP2@V;^JO]V]E+"1``D",)$$?CO"`+.@``P+*0(J/K#;`=_@&0`` +M?_D+*?&5``1@^3ZPVP'>T&4``%CO''#V`/0>%M_@&0``?_DR*_&5``1@^3ZP +MVP'9Q&4``+^:2R`!Y/G_?W7I''[#VP%^@=X!,BL"*SZPVP'9T&4``)B:(7XI +M;@"QI@\G]`QHV3$9```_GMDO&0``/YD]U,3O__"4_[R?L#XVQ`&_^;_/$.X! +M\)0/]`LKQ/D/]`LEQ-G_E)\$V0AH$0$0W0&\^?#$Z?^X_``(`*:;]![2/FO$ +M`=_@&0``?_D+"O&5``1@^3ZPVP&]]-G090``"PJUGR$""SZPVP'9,1D``#VT +MLI@_FM%"0``;R>D+^?OQF\GUF_;[\9/)\YCI`6$<2Y_S]]O)GPO/GPO)Z0/XZ4 +M]`.4E@3PU/^\_Y#PY/^0_P'$K/^0E0&\WM`0NP&4\P,0J@'0Q&4``*;-]!Z. +M"4#?T&4``/Y-`9C\!I#=/*#9O]G^3@&0[C28^P>\G)"@V4D@`:#IO^F_#`_P +MD)D/_9\$H.F_VK_MO92PD0`)`]XOQ```,)$$?CO"`+.@``P+"P(,/K#;`=_@ +M&0``?_D+"_&5``1@^3ZPVP'>T&4``%CO''#V`/0>%M_@&0``?_DR*_&5``1@ +M^3ZPVP'9Q&4``+^:Y/G_?TL@`77I''[#VP'9,1D``#^^)?N_KS^\,2=#[/4 +M!PP-!0D!/OC%`;V4W@AP$0&\_O"__\3^#[/@!PRSD``*L^0&!@X%L]``"+/D +M``@-!;+>E"D"Q_]PN_D$$,P!_:\%$!$!O-GTO.F4_0\%_;D%Q,G_II/T'HW9 +M>!0``:"0D)D$H)L"#9"9!`L,H)H^L-L!26`!F!\&H*F_J9@;![\,WB_$``"\ +MGY"@J0D+\0``+R?D*"I27P!H-F_V0_PD)D/_9\$H-F_JK_=O92PD0`)`C"1!'X[ +MP@"SH``,"RT"+CZPVP'?X!D``'_Y"RWQE0`$8/D^L-L!W]!E``!8^1QPE@#T +M'A;?X!D``'_Y,BOQE0`$8/D^L-L!\93_?W7Y''X"W0'9Q&4``+^:2WP!?L/; +M`3(K`B\^L-L!?E[=`4F``=_090``_DT!F/P&D-T\H-F_V?Y.`9#N-)C[![R< +MD*#927P!H.F_Z=_$90``O_P/\)"9#_V?!*#IO]J_[;V4L)$`"0/>+\0``#"1 +M!'X[P@"SH``,,BL"$#ZPVP'?X!D``'_Y,BOQE0`$8/D^L-L!WM!E``!8[QQP +M]@#T'A;?X!D``'_Y,BOQE0`$8/D^L-L!V<1E``"_FN3Y_W]+?`%UZ1Q^P]L! +M,BL"$3ZPVP%)``/?T&4``/Y-`9C\!I#=/*#9O]G^3@$`,)#N-+R+\0``#"1!'X[P@"S +MH``,,@(++SZPVP'?X!D``'_Y"R_QE0`$8/D^L-L!WM!E``!8[QQP]@#T'A;? +MX!D``'_Y"S#QE0`$8/D^L-L!V<1E``"_F@LPY/G_?W7I''[#VP%^OMP!`C$+ +M,#ZPVP%^=MP!20`#W]!E``#^30&8_`:0W3R@V;_9_DX!D.XTF/L'O)R0H-D) +M,*#IO^G?Q&4``+_\#_"0F0_]GP2@Z;_:O^V]E+"1``D#WB_$```PD01^.\(` +MLZ``##(K`A(^L-L!W^`9``!_^3(K\94`!&#Y/K#;`5@?''#V`/0>%M_@&0`` +M?_D+$O&5``1@^3ZPVP'9Q&4``+^:Y/G_?PLP=1D%M_@&0``?_DR*_&5``1@ +M^3ZPVP'0Q&4``+\*\93_?TN``W7Y''[#VP&_"]H0#@``3(`#?E0W`#(K`C,^ +ML-L!28`#W]!E``#^30&8_`J0W3R@V;_9_DX!D.XTF/L+O)R0H-E)X`*@Z;_I +MW\1E``"__`_PD)D/_9\$H.F_VK_MO92PD0`)`MXOQ```,)$$?CO"`+.@``PR +M*P(T/K#;`=_@&0``?_DR*_&5``1@^3ZPVP%8&1QPE@#T'A;?X!D``'_Y"S3Q +ME0`$8/D^L-L!T,1E``"_"O&4_W]+X`)U&1Q^P]L!OPO:+$P``$R0`'Y4-P"_ +M"]J84@``3-P!D+O`?E0W`+\+VN!+```,0+B[G`(`?E0W`+\+VI`1```,`[B[ +MW`(`?E0W`-F0$0``/Y\)_R;Y]`L/WY06```_^1"9`2#YV9`1```8GP$)_R;Y +M]`L/WY06```_^1"9`2#YV9`1```8GP()_R;Y]`L/WY06```_^1"9`2#Y"S0" +M-3ZPVP%)8`;?T&4``/Y-`9C\"I#=/*#9O]G^3@&0[C28^PN\G)"@V4D@`J#I +MO^G?Q&4``+_\#_"0F0_]GP2@Z;_:O^V]E+"1``D"WB_$```PD01^.\(`LZ`` +M#`LU`C8^L-L!W^`9``!_^0LU\94`!&#Y/K#;`5@9''"6`/0>%M_@&0``?_D+ +M-O&5``1@^3ZPVP'0Q&4``+\*\93_?TL@`G49''[#VP&_"]K`20``3"`"`C=^ +M5#<`"S8^L-L!28`(W]!E``#^30&8_`J0W3R@V;_9_DX!D.XTF/L+O)R0H-E) +M[@*@Z;_IW\1E``"__`_PD)D/_9\$H.F_VK_MO92PD0`)`MXOQ```,)$$?CO" +M`+.@``PR*P(X/K#;`=_@&0``?_DR*_&5``1@^3ZPVP'?T&4``%CY''"6`/0> +M%M_@&0``?_D+./&5``1@^3ZPVP'0Q&4``+\*\93_?TON`G7Y''[#VP&_"]KX +M#0``#`0".7Y4-P"_"]K\#0``#`R0NP1^5#<`OPO:"`X```P$D+L0?E0W`+\+ +MV@P.```,!)"[%'Y4-P"_"]KL3```3-4"D+L8?E0W``LX/K#;`4EP"]_090`` +M_DT!F/P*D-T\H-F_V?Y.`9#N-)C["[R+\0``#"1!'X[P@"SH``,"SD".CZPVP'?X!D` +M`'_Y"SGQE0`$8/D^L-L!W]!E``!8^1QPE@#T'A;?X!D``'_Y,BOQE0`$8/D^ +ML-L!T,1E``"_"O&4_W]+U0)U^1Q^P]L!OPO:P4\``$S5`GY4-P`R*P([/K#; +M`=#$90``OPI,@`/;$`X``'Y4-P"]U+W$OPZ4WP*4V06[GP(\Z?B0W0&\Z>#P +M]`'T"PFU[`.U[`*SU"#@W]!E``"]!)C]"OY*`9"J/*"@OZG^3@&0[C28^PN\ +MG9"@J4F``Z#IO^G?Q&4``+_\#_"0F0_]GP2@Z;^JO^T)`[`!`#"1!-XOQ``` +M?CO"`+.@``P+$P(4/K#;`=_@&0``?_D+$_&5``1@^3ZPVP%8'QQP]@#T'A;? +MX!D``'_Y"Q3QE0`$8/D^L-L!V<1E``"_FN3Y_W]+@`-U&1Q^P]L!`A4+%#ZP +MVP'0Q&4``+\*VRQ,``!,D`!^5#<`OPK;F%(``$S<`9"JP'Y4-P"_"MO@2P`` +M#$"XJIP"`'Y4-P"_"@P#VY`1``"XJMP"`'Y4-P"]U+W$OPZ4WP*4V06[GP*\ +MZ>`8Z<"0W0'PE`'T"PFU[#.U[#*SU!'@28`#W]!E``#^30&8_`J0W3R@V;_9 +M_DX!D.XTF/L+O)R0H-E)X`*@Z;_IW\1E``"__`_PD)D/_9\$H.F_VK_MO92P +MD0`)`]XOQ```,)$$?CO"`+.@``P+%0(6/K#;`=_@&0``?_D+%?&5``1@^3ZP +MVP%8'QQP]@#T'A;?X!D``'_Y"Q;QE0`$8/D^L-L!V<1E``"_FN3Y_W]+X`)U +M&1Q^P]L!`A<+%CZPVP'0Q&4``+\*V\!)``!,(`)^5#<`26`&W]!E``#^30&8 +M_`J0W3R@V;_9_DX!D.XTF/L+O)R0H-E)(`*@Z;_IOPP/\)"9#_V?!*#IO]J_ +M[;V4L)$`"0/>+\0``#"1!'X[P@"SH``,"Q<"&#ZPVP'?X!D``'_Y"Q?QE0`$ +M8/D^L-L!6!\<+\0``#"1!'X[ +MP@"SH``,"QL"'#ZPVP'?X!D``'_Y"QOQE0`$8/D^L-L!6!D<<)8`]!X6W^`9 +M``!_^0L<\94`!&#Y/K#;`=#$90``OPKQE/]_2]4"=1D%M_@&0``?_DR*_&5``1@^3ZPVP'9Q&4``+^:Y/G_?TN. +M`'4)''[#VP$R*SV4`CTU"4$^L-L!T,1E``"_"1@?01B9C";Y]`@+"ST"0#ZP +MVP$+,-H@9@``?APX`+\.&!E!WT!<``#<``0``+4?&?"4_YC/#[R9D+SIX'_N +MO=3Q]0"`V3P$```+/74>*34=4+7/#[4=%K49%0(^/K#;`=X`!```F.\/Y/D` +M@'.0`".)_W____F4VB!F``"UZ0]^9K0`LZ``#`L^`C\^L-L!W^`9``!_^0L^ +M\94`!&#Y/K#;`9@=%K/4``;X")C9")C>`4__W_^?]+7?",?N`_0+%XG___W_ +M^92RVK79"'X,C``^`]4!V?__`?"UW@__^92UW@FUW@JUW@ZUV0C?T&4``!CY +M03(K`CT0F0$U^4$^L-L!V=!E``"8D2#>0#@``-/$90``O524$@8$`[PN(#[. +MU0&_*;.9`(T`OSW?0#@``)00!KP/`!C?C)@)"Y@.#/Y+`?#T_[S_\+:5&+S? +MT':4!K;E&_V>!6#9OS_^3`&0NS"0S"P8^8P0F0$U^8R8"@NVI1A^838`LZ0` +M!O@(F`H,M)`,M+`+L%$`MJ4;,$$$MJ0&L@R\J:`-0+"A#-XOQ```?CO"`+.@ +M``H-'C[8U0'X")`1`9`B0+$610#U#6?_#1_9T&4``#+2M9$@"QT^L-L!WM!E +M``!8Z1QPE@#T'A;?X!D``'_Y"Q[QE0`$8/D^L-L!F.\@\93_?PL>=>DT&4``%CO''#V`/0> +M%M_@&0``?_DR*_&5``1@^3ZPVP'9Q&4``+^:Y/G_?TN.`'7I''[#VP$R*P(A +M/K#;`4G``]_090``_DT!F/P&D-T\H-F_V?Y.`9#N-)C[![R%M_@&0`` +M?_D+0?&5``1@^3ZPVP'0Q&4``+\*\93_?PM$=?DO?39$!0``:"?3P`!D)D$H)\/`;B9]`$`H)_9Q&4``+^;VIP$ +M```,)`)"?E0W``M!/K#;`=#$90``OPK;G`0```PD?E0W`+\/V0`$``"8F1K< +MT&4``/Y*`9"J/+7Y"=G880``OP^_F?Y-`9#=--XOQ```M?D*V0!A``"_#[^9 +MM?D+V01:``"_#[^9M?D,V0A:``"_#[^9M?D-V0Q:``"_#[^9M?D.V1!:``"_ +M#[^9M?D/V3!;``"_#S^9-?E`V3%;``"_#S^9-?E!V8A<``"_#S^9-?E"2<`# +MF,\&H*F_J;R?D*"I"42@V;_?F,L'O92_#+"1`)#_#PGP_?D$H-^_JK_="0,P +MD01^.\(`LZ``##(K`B(^L-L!W^`9``!_^3(K\94`!&#Y/K#;`=[090``6.\< +MT&4``/Y/`9CM!I#_/*#YO_F8ZP?^3@&0[C2\G9"@^0D0 +MH.G9Q&4``+_ZOYR_[;V4L)$`"0+>+\0``#"1!'X[P@"SH``,"T("0SZPVP'? +MX!D``'_Y"T+QE0`$8/D^L-L!W=!E``!8WQQP]@#T'A;?X!D``'_Y,BOQE0`$ +M8/D^L-L!V<1E``"_GN3Y_W^8WP]UV1R_Z:;Y]!L,/90UV3L^!]H!WB0@``&_ +MZ0\!-=\[#_?]GP3QE0`$H.G9``0``)B=#\39"/0;!?@(WB0@``&_Z4_W_=P\ +M%``!"T/]GP2@Z;_)Q=Z`#0$RTK"1"[3P"PGU_>D$"?[]^02P\0NT\`O9``0` +M`+6>#]D08@``()V@SSZPVP&_"9@>#Z">21`$F!\&H*F_J9@;![\,WB_$``"\ +MGY"@J0D0H-F_JK_=O92PD0`)`S"1!'X[P@"SH``,"R,")#ZPVP'?X!D``'_Y +M"R/QE0`$8/D^L-L!W=!E``!8WAQPY@#T'A;?X!D``'_Y"R3QE0`$8/D^L-L! +MV0`$``"8GP_DZ?]_==D0``;6Y#SZ1VP'$R0CT"QO=)"```;_>Q``0``)CO#TGS_@M$`@']^02U[P\^L-L!^`@R*R:R]1MPX-G0 +M90``()OT,`C[A13Y,K*MLJ&RL)6Z`CTTV]!E``"RK`(!/@+<`;_9&+]`F+X/ +M-;-`D-T$\/3_O/[PO/GPM;\/DLP!II_T#08ULD"SQ`#;E*D"O!F@Q`D"]`LO +MW=!E``!_J1C?0)C>#S7<0/"3`/#T_[S^\+R?\+7?#Z:?]`T("0$UV4"0J@+$ +M"0'T"S/>T&4``)CO#QCI0#W4\)3_O)^0M>D//Z_P]/^\^?"U[P\_J?"4_Z:? +M]`T%#0$U[4#[,=D`!```WL1E``"8G1R_[[7]`9B=';7]`AB=>37]#+_OF)T@ +MM?T%F)TAM?T&&)V)-?T')C^`K6>'1C^##6>>9C^!;6>()C^!K6>(1C^'#6>B9C^";6> +M))C^"K6>)1C_+#6?F?@`^0+0Q&4``+\+VM`C``!,@`"0NQA^5#<`OP_95"0` +M`-I6)```#$@8_IB0^YH@GAC_F=E5)```()]^5#<`OPO:>`4``$R4`)"[Z'Y4 +M-P"_#]D`(P``F/\YM9]4^P'Y$M#$90``T0`C``"_"9@?+-O0(P``3(``H)^_ +M"9@?+;6?`;\)F!\NM9\"OPF8'R^UGP._"9@?,+6?!+\)F!\SM9\%OPJ0JAA^ +M5#<`OP_95"0``#^9VU8D```,2#7YF-E5)```OP\_F37YF;\*D*J:?E0W`+\* +MVW@%``!,E`"0JNA^5#<`OPF8$52UD3G[$=G$90``OY_9H%P``+_^M9X!F/X! +MH)Y8_@1UG@18_@5UG@68_@.UG@28_@2UG@58_@IUG@Q8_@MUG@V8_P:UGP?X +M`-[$90``WZ!<``"_Z9C]`:"=O_V_Z;6=`5C]!+_I=9T$6/T%O^EUG068_02_ +MZ;6=`YC]!;_IM9T$6/T,O^EUG0J_Z5C]#76="[_IF/\'M9\&^`#T,/C9,1D` +M`/F"/Y0]9#)',$$G$G^\'!"\/C#'2!3T&PFR6CY9WP%)__W_6:2/`!<1O!\0E!L$O[R)`.GN +MY*T``KP9$)7?"$$[O_?_.E/_9E90?!*"YO_F,@.GN +MO!P0_9X$_]F5H/F4/P.4.0;>3%@``+N?`KR>D!B?`S/T!!64&0?<"&`1`;R< +MD+^9/O/?`3/T`Q?>"&@1`=SXE^[^O"X@ORD^\-\!W@AP$0&\+B"_*=SXC^[^ +MO"P@QYP,QTT1"?[_J93_R>6SU`$+B0```OWI!3/T!!64&0??"&`1`;R?D+^0 +M/CO@`3/T`Q#9"&@1`;PI(#XYX`'?"'`1`;PO(+\@Q`\/21_^MO0%_^F4__D% +ML]``#K/$``I)_ +M!:!)QUG1]`L/-)`G,FL\::!^A30`$&8!$',1D``#_)/^_$<_^0 +M.@'PE/_P]/^\GY"FJ?4>ZOW[A0CX```````````````````````````````` +M```````````````````````````````````````````````````````````` +M``#X`-G`50``&)\U&)LT6)X;6)H<6)P=F)T#,_D(@0$P]@CT#"DS^0/\`##V +M`_0,$#/P`$0S_0&Y`3[)X0$S^05)`0H7,_T&J0'X`#/Y"XP!,/8+]`P1,_D) +M5P$S_0J2`3[$X@$*)C/Y,(D!"B@S_3&``?@`<^0`4'/$`DS$N1_$K@\SE``, +M\$D-\0M=D!M=H"Q,D!_9X%M=D#"@'9P%4` +M`#6D%B?__`?]9E/V?!?Y-`;;$$)#='+79`HD```']R03][`6UU`&RVK7>`W[P +MX@'[91#T,/#Y8C1@,+*ALK3^0`&RQ9``'#+2,N.R"@L0?APX`#-@``J@`3XQ +MY`&X&0`@`J`)-,`TE#D%\)0@E"X$\.00\>4`#/WI!91I!O"40(\``(#]Z06) +M__\!_UF4_9\%_DT!ML00D-T',)`Z,`8!Q/D@]`L+Y.G?_SZEY0'D^0`!]0M+`>3I__YU&0X^G^8! +M6!\.Y/[__^3I`!#T"Q#D^?_O#P=U&0X^E.4!Y.D``?0+$.3Y__X/!G49#CZ4 +MY0%R#U@=#N3>___$Z2#T"Q+DV=__=1D.<@P/"#[?Y@'DZ0`(]`L:6!\$Y-G_ +M]W(,=1D.\?4`0'4?!#[DY0'DZ0`!]!L)<@P^W^8!Y-G__G(,=1D.#P8^W^8! +MORF8'G`-]W(,_9T$H"F_/PGX_>D$M1YP_?T$"0&@/[49#`\)/M_F`9@?<+\N +M"?@,!_WY!/#U`K4?<`D#\.4(M1D,H"X/"3[?Y@':E%<```LL?APX`)@9<;44 +M=K45>G(,\)4&#P&U&7$^W^8!F!]QF!HWF!LXV=Q5``"PD0`)Q_WY!`D!\/40 +MM1]QD*I`,)$$W(!7```-0-Z>P0``?CO"`+.@`!5R#`\*/M_F`5@9#G"6`/0> +M"W(,<@\^W^8!F!EQF!X,#\?]GP3PE3"U&7&SY`(.6!D$\94`$'49!%@9#E@? +M&`P*\93_?W49#C[?Y@'X"'(/<@QR\&8,]1O]_>0/___9P%4``/0P"+6?"_M1 +M^5+9P%4``/0P^+*16)`2?<32$(`1`=-0)@`!A```#(4```@^(.D!#>3O___D^0`$]`L@F!]@Y.G_^W49#0GX<@S]^00)`O#U`;4?8#Y( +MZ`'$^2#T"PODZ=__/N3G`>3Y``'U"TL!Y.G__G49#3[>Z`%8'PWD_O__Y.D` +M$/0+$.3Y_^\/!W49#3[3YP'DZ0`!]`L0Y/G__@\&=1D-/M/G`7(/6!T-Y-[_ +M_\3I(/0+$N39W_]U&0UR#`\(/A[I`>3I``CT"QI8'P3DV?_W<@QU&0WQ]0`@ +M=1\$/B/H`>3I``'T&PER##X>Z0'DV?_^<@QU&0T/!CX>Z0&_*9@>8`W[<@S] +MG02@*;\_"?C]Z02U'F#]_00)`:`_M1D*#PD^'ND!F!]@ORX)^`P'_?D$\/4" +MM1]@"0/PY02U&0J@+@\)/A[I`=I45P``"RQ^'#@`F!EAM11FM15J<@SPE08/ +M`;4983X>Z0&8'V&8&C>8&SC9VE4``+"1``G'_?D$"0'P]3"U'V&0JH`PD03< +M0%<```U`WI[!``!^.\(`LZ``%7(,#PH^'ND!6!D-<)8`]!X+<@QR#SX>Z0&8 +M&6&8'@H/Q_V?!/"5$+498;/D`@Y8&03QE0`(=1D$6!D-6!\4#`KQE/]_=1D- +M/A[I`?@(<@]R#'+P9@SU&_W]Y`___]G`50``]#`(M9\)^U'9P%4``/0PV'W4 +M^8*RDO0P^%B0$-@H@!$!/O3S`7,)%T($<`87]0R$`',)#H8"<`8.]`Q#T!3I``$- +M`?4+2@GD^?_^=2D,/I[J`5@N#.3O___$^4#T"PODZ;__/@3K`<3Y`O0+$N3I +M_?\`"W4I#`T"/O3S`<3Y(/0+$.3IW_\`"'4I##[=Z@'D^0`!#0+U"_@(Y.G_ +M_G4I#``&/MWJ`5@N#.3O___$^0+T"R68+D#=$(`1`;_?"?C]Z00)_OWY!*#? +M\.4!``*U+D`^3.L!Y/D``?0+$N3I__X`!G4I#`T#/O3S`<3Y(`T#]0N=".3I +MW_\`"'4I##Y,ZP'=$(`1`9@N0+_?"?@``?WI!`G^_?D$H-^U+D`-!C[T\P': +MU%8```LL?APX`)@O08D```RU*4:)```X\/4&M2E*M2]!"00``;4I3@T(/O3S +M`7X"X0$-"W*@/O3S`0H!?H/D`5@I(@`.#0P^?_,!/:1^@^0!6"DB``X-#3Y_ +M\P%8+PS$^03U"^`'Y/G[_P`"=2D,#0X^]/,!&"DT6"\<"@'PE!\SD``G,Y`" +M"KVD/C'L`=K`5@``Q/D/MI0&O)J0OYGPE`>PE@+PK`L.`3W4,.$`,.$$O;0, +M`GX`Y`%8*2(`$`T//G_S`5@O#,3Y!/4+>`?D^?O_``UU*0P-$#[T\P$8*318 +M+AS$GQ\S^0"`!S/T`0KX"#[R\P$-$3/]`G,'Q.\/,_0`%=X0@!$!`!*_[PT1 +M"?X^M^P!,_T!4@__``QU*0P-%C[T\P%8*1M8)1U5GPAS\`)8$%@``#_I\)3_9I7T#05R6>2< +M__\]E`X!,)$`/=0PX03:$%@``+VT?@#D`5@I(@`8#1<^?_,!,YT`Z07?P%X` +M`+#Q$-_@7@``VO!>``#9T%X``-Y08```L)$1L.$3L/$4W>!>```_K]S`7@`` +M/YD_[C_=/\RPH1+:$%\``#^K\)3_\/3_L)$,\.3_\-3_\,3_L/$-L.$.L-$/ +ML,$+Q+G_9I7PG`@RD#.0``O$L?\^=NX!Y%'__SV4,`8`\.P+`P$PD0`P,03: +M$%\``+VTLAPR#7X`Y`$S"0`4`C(W/42]-#UD_DD!D)DLO).0OY_^2@%[40*0 +MJD#D4?__O*.@IO'PG`B0,P0RD#.0``:R\3-$!`8]!#!A`#!Q!+^J,`8`\.P+ +M$$0!O;2R'#(-?GWC`3,)`+L!,T0%KSZI\`'$GO^SX`%JL.8!]!P+L^``&CX: +M[P&SZ0*>`+/I`]T`#1<`*3[T\P&8*8B8+X"8*X'>V%4``/"4_\3]#WS9T`D" +ML.$`4-T/"O#QU/#___JD,)$$W#!?``#>GL$``'X[P@"SJ0"'!'(-`!D^]/,! +MF"F(F"^"F"N#VMA5``#'F>C$_0]0W0]\V=`)`K"A`/'4\/\*\#"1!/_ZI-PP +M7P``WI[!``!^.\(`LZD`001R#0`:/O3S`9@IB)@OA)@KA3#A!,>9\-[850`` +MQ/T/L.$`4-T/"O!\V=#_^J3QU/#_W#!?``#>GL$``'X[P@"SJ0#]`W(-`!L^ +M]/,!F"F(F"^&F"N'VMA5``"VE1C$_0]\V=`)`K"A`%#=#PKP\=3P___ZI#"1 +M!-PP7P``WI[!``!^.\(`LZD`MP,-%P`,!6"DB#1<`&#Y_\P%8+PP-&,3Y!/4+.`/D^?O_``UU*0P-&#[T\P%8 +M*0QPE@#U'_<"F"F(F"^`6"$=Q)#_Q/L/]`L3V3!?``"R#+RYL+*:?E0W`.0< +M__^FP/0-!;(,/90.`3"1`#W4,.$$VC!?``"]M'X`Y`%8*0Q8+R(`&`T9/D7R +M`5@I#`T:<)8`]1_!`I@IB)@O@E@A'<>0Z,3[#_0+$=HP7P``L@R\NK!^5#<` +ML@SD&?__I@GT#0?D'/__/90.`3"1`#W4,.$$VC!?``"]M'X`Y`%8*0Q8+R(` +M&`T:/D7R`5@I#'"6`/4?.P*8*8B8+X18(1W'D/#$^P_T"Q/>,%\``+(,O+ZP +MLNI^5#<`L@SD&?__I@GT#0?D'/__/90.`3"1`#W4,.$$VC!?``"]M'X`Y`%8 +M*0Q8+R(`&`T;/D7R`5@I#`T<<)8`]1\!`I@IB)@OAE@A'960&,3[#_0+$]\P +M7P``L@R\O["R^GY4-P#D'/__IL#T#06R##V4#@$PD0`]U##A!-HP7P``O;1^ +M`.0!6"D,6"\B`!@-'/&4_W^V]!!U*0R@CS[T\P&8*0,.`3W4,.$`L)8%\*P+ +M,.$$O;0,`7X`Y`%8*2(`'@T=/G_S`5@O#`T>Q/D$]0MQ`>3Y^_\`#74I#`T> +M/O3S`9@O`Q@I-K/T!!PSF0`R`3.=`3,!6"D$`"`-'_"5"#[,\@&S_044`3.4 +M`!98*00`(0T?\94``G4I!#[T\P$SG0$%`3[2\P%8+PS$^0CU"^H`Y/GW_P`, +M=2D,#2`^]/,!6"\,#2'$^8`SF0#W`.3Y?_\`#'4I#`TA/O3S`5@I''.0``P` +M*0TB/O3S`0X!/=0PX0`PX02]I+VT#`%^`.0!6"DB`",-(CY_\P%8+PP-(\3Y +M!/4+K0#D^?O_``UU*0P-(S[T\P$`*0TD/O3S`3V4#@$PD00]U##A`+VDO;0, +M!GX`Y`%8*2(`)PTFMI00H(D^]/,!6"\,Q/D$]`L^Y/G[_P`,=2D,#2<^]/,! +M``P-*#[T\P'=$(`1`;_?F"Y`"?@``_#U`:#?_>D$#2GPY0*U+D`^]/,!^`AR +M#3[T\P$`##[:\P$`*0T?/O3S`0`I#1<^]/,!`"D-$S[T\P$`*0T19@WU&U[U +MY`___]G`50``]#`(M9\(^X4HW\!5``#T,,#9P#8``/F"?>3T,/BR\?Y'`<68 +M!%CP!H4```R&```(D'3Y +M``'T"Q+DV?_^``%U&00.`CZ#^0'$^8`SD``1Y-E__P`0=1D$/D/U`>3Y``0. +M`O4+(`3DV?_[`!%U&00^0_4!6!\$Y/[__\3I`O0+-K\M6!X,6!D;\?3]_W4? +M!-____^`\.40_=\$MI08WP```']U'@S]GP0`!/V=!:`I/L3U`<3I@#.0`!/D +M^7__`!!U&00.`SZ#^0'DZ0`$#@/U"[,#Y/G_^P`1=1D$/L3U`5@#%@9&^3/_?]U'P3?____@/#E$/W?!+:4&-\```!_=1X,_9\$ +M_9T%H"D^@?D!Q/D$]`LEOR]8'@SDR?O_``-U&03PY1#9____@'4>#/WY!*`O +M/E;V`<3Y"/0+$N3)]_\`"G49!`X$/H/Y`<3Y@#.0`!'DR7__`!!U&00^5O8! +MY/D`!/4+#0/DR?_[`!%U&00^5O8!6!T$Y-___\3Y@#.0`!'DV7__`!!U&00^ +ML/8!Y/D``O0+$N39__T`#749!`X%/H/Y`>3Y``0.!?4+QP+DV?_[`!%U&00^ +ML/8!F!HWF!LXVP0``,)$$W,!7```-0'X[P@!R#K.I`)$" +M``<^@_D!6!D$<)8`]1]^`O&4_W\`"'49!`X'/H/Y`9@:-Y@;.-G(50``L)$` +M"0+>GL$``#"1!)"J0-Q`5P``38``?CO"`'(.LZD`1`(`"0X(/H/Y`5@9!'"6 +M`/4?+P*U%6:R>MM`5P``#$"U%FJU%7:U%GI^5#<`VD!7``#;@%<```Q`?E0W +M`-J`5P``LGL,0'Y4-P"8&6&8'W%8'00.QP`!_9X$_?X$\)40\/4P\=3_?[49 +M8;4?<74=!`X)/H/Y`5@9#0`+#@KQE0`$/GCX`5@>!.3I``CU"[,!6!\.Y.G_ +M]P`,=1D$\?4`!`X+=1\./H/Y`5@9!`X,\90`$/4+CP$)#]X8@!$!H$F_Z0_P +M_9\$\)4-H.F_3K/D#?[9%(`1`;WTH)^@3K\I\)4!H"F_*?"4`?0+^U@9"%@> +M#+\_6!T$ORSPE0+PY0AU&0C9____@/#U`74>#/WY!/'4_^_9````?W4=!/W) +M!``%_?P%#@R@/SZ#^0%8&0T`#@X-\94`"'49#3Z#^0%8'00.#N39`"#U"_L` +M6!\.Y-G_WP`/=1D$\?4`"`X.=1\./H/Y`5@#?#5(*`Y=1\,=1T.``(.$#Z#^0&_*=_^__^`WA"`$0']GP2@*;_I#_#] +MGP2@Z;\\Q,D!]`L&\,406!X-6!\,6!T.V?[__X#QY0`!_\F4\?4``74>#?'5 +M``&@.74?#'4=#@`!#A$^@_D!^`AR#F8.]1O$^N0/___9P%4``/0P"+6?`_N% +M0-G`50``F)D!]##\^0*SD`!$T*!>```+$+(*?APX`-FP70``6)N#V0````&U +M"0*)`(@`_DP!L@JU"0.0S`1^`#X`,Z0`$-]4)@`!O_GPE0&@^?L%!-G`50`` +M]##X?Y[Y@MDP&0``/YG$G_]F[_0()=DN&0``/YGD[/__Q)W_O-^0ILGT'P^\ +MSZ*FK?0>*#Y+^@'9,1D``#^?V2\9```_F?#C`/#T_[SOHO"4_Z:I]!X%^`C> +MP%4``%CI`=\$8!$!C0```K+B\),`MI0'O)^0D)\$OY&_^=]8)@`!O_.RU\24 +M#UC@"K*FQYX,QS71QYEP,.$DMI0*E$@%_YW5??2PT0H^E@`"R!3X^_P%S"0DA!7,-"J0%/F```KWDWP1@$0$^B/\!6"D(\)0! +M]0N,!;WDWP1@$0$^+OL!6"D!\),`INGT"P^_^=W__P"._9T$H/F0[@&0_X#= +M+AD``#_9\)3_INGT"-?<5"8``;_-W\!5``!__M____\`_=\$3Q_^MN08_>T% +MM-`*Q3D#H,[]GP1/_\/]F`7]GP3_G3796"8``:"3LU0`"'Z;^0%8*00``P\" +M\)4!=2D$/I8``E@N".3O___$^0'U"^(!QQX1,^``833P)#/P`%I8*0&."0`+ +MW01@$0'?````SO"3`/\?]+:4![R=D/_^%;)JH)%+$0Y^)6H`6"\$6"X,6"D! +M\/5`\.4!=2\$\),`=2X,3Z`"CD("$+R>D+:4!*"?/G;]`94=%I49%_V=!?"4 +M`?0+>;-$!'98*0'?__\`SO\?]-X``,``__X5WP1@$0'PDP"VE`>\GY"/__^_ +MH)%)'?[_.93PE8#]GP2/``!`_9\%W___?__]GP3?``"``/^?-=E8)@`!H).S +M5``(?IOY`5@I!%@O#``%\94``?#U0'4I!'4O##YV_0&5&165'Q/]GP7PE`'T +M"PD`"3YV_0$SX``.LT0%"@`(/G;]`<!&`1`;R>D(\``$"@D4D?_O\YE/^?-=E8)@`!H).S5``(?IOY`5@I +M"`\#/I?^`<3Y`O4+#`/DZ?W_``1U*0@/`SZ6``)8+@CD[___Q/D!]0L#`949 +M%94?$_V?!?"4`?0+"0`)/I+^`<<9$3.0``ZS1`4*``@^DOX!QQ\0,_``.+-$ +M`S18*0'?__\`SO\?](X```'PDP#__A6VE`??!&`1`;R?D(]@`$"@D4D?_O\Y +ME#Z`_@''&18SD`!%LT0/05@O`8X``$#9__\`SO\9E/#S`/^>%93Y!]X$8!$! +MO)Z0C<`B`J"1O/WPMO0'O_E.'_[PE1#]G@2@^3Z2_@&S\`!<0`0E@I`=__ +M_P#._Q_TC@``0?"3`/_^%;:4!]\$8!$!O)^0CP``0*"121_^_SF4_Y\UV5@F +M``&@D[-4``A^F_D!6"D(#P3QE/[_=2D(/I8``L3Y!/4+Z0'DZ?O_``-U*0@/ +M!#Z6``+_%Y3U"]D!LTT%U0&-```(_QV4]1O)`0`(D/_?%0`*H)$^-?\!_Q>4]`L3LT0%$(\```C_'Y3T&P4`"%@I"`\& +M/I?^`5@N",3I`?4+2@&5&165'Q/]GP7PE`'T"PD`"3YI_P'_%Y3T"PFS1`4& +M``CDZ?[_#P=U*0@^E@`"O_G=````0)#N`?V=!:#YD/^`W2X9```_V?"4_Z;I +M]`CB"_^R:GXC:@"R:HM!?@5^)6H`WE0F``&_Z=____\`_9\$H.F/H``"V5@F +M``&@G[-4``A^F_D!6"D$6"\,6"X-6"T.\94`!/'U``%U*01U+PQ]E/'E``'Q +MU0`!=2X-=2T.=2D!8"D``@\(/I8``E@I`=\$8!$!W0"`$0'>__\`SO"3`+:4 +M![R?D/\>Y(\!`&K_[Q6@D;_96"X$WP```(``!OV?!4\?_J#9"?W_.93PE1#] +MGP3PY8#%DZ!U+@396"8``0\)H),^E@`"3Q_^">__.93PE0+]GP2/```@_Y\U +MV5@F``&@D[-4``A^F_D!``,/"CZ6``+X"'(//I8``@\%9@_U&P?ZY`___]G` +M50``M9\%^X4(^2(!"@+_T,!5```^)P$"6`D$V1P8$`&@G[B9_`$`OYGDZ_\!L)8`]!X%^`@/_]D8&A`!H)^2F0B_ +MF96?&.>9:`&\G_"0F0&4_0B4G@B\FY"[GP*VE`@^C`@"^ND$N.X``0"XF0`! +M`*;M]`CQ^`>]Y-E4`0`!H)[?````(-D4&A`!H)^XF0P"`J">D)D$H)Z0F02@ +MGI"9#*">CP``$)*9&*"?#Q.0F3R@GT\`$9"9!*"?N)G``0"_GI"9!+^=DID( +MOY_9=!T``*">V7@=``"@G=E\'0``H)^QYO\`]`P%^`A)`/"X[P`!`OWY!-E( +M&!`!H)^RZ=X`__\/O)Z0NY\"WTP8$`&@_8\```;ZGP7X`[WTF/D-F/X,O_V8 +M_P[PE?^[G@*\GY"FG?0(!?@(O?28^0.__Y2^"+R?D*;I]!@%^`B]E)B9#=]T +M'0``O_U/`/^0F?_]GP3?"!@0`;:5!/&4_S^4GA"@_M\```!`MI0$_9\%WS`: +M$`&@^=DT&A`!H)V2F2R_GY"9,`YDW4`:$`&@G]\````'D)D$H)_^3P&0_P0^ +MV`D"DNX!L^0!#+_9H/D^R0D"L^0`\;_9H/F_^;"6`/0>"0YD/LD)`ME`&A`! +MWP```$"@GYCI#KWD/@L*`OKN!+CN``$`INGT"/;X![V4F)\-F)T,20#_D/__ +M_?D$/C0*`OK>!+C=``$`N.X``0"FW_0(\?@'V5@!``&VY0BRO+R^\@H!H)_9 +M)!D``&">/ET*`K;%`1"J`;/$`/J8S@Z8R1%/`/CG[N@!N)G_!P#]GP2VE`C] +MG@7?4`$``:#YF,D/3P#_D)G__Y^TE;D$Y)#_/]D(&!`!E`\0H)^8S1"8SA$) +M`=\F&0``NYH$4ID!8/F[[0*)`$`!INGT#07X"+/D``JROCX_"P+9````!/\) +ME=\,&!`!N+T`0`"@^979!/&4_S^0_P2@^=D4&A`!WP```$'>&!H0`:"?21`G +MO^^P]@#T'@V2F0'T&_4^%PL"LY0`!O@(W@```$#9&!H0`?W^!:"?D)D(H)[? +M^/CX^)"9"*"?D-Z`DID$H)_9`!@0`;^?"<"0[C_]Z03P]`^V]`^5[02\_L+Q +MU/\_WP08$`&5R03QE/\_MI00_9T%H/D.`[WTV2`8$`$8_4R@GI"9"*"?D)D$ +MH)^2F0B@G#/0`&])``'?[[ZMWJ"?D)D$LYX``OM)`/^]U/_)](X``08^Q`L" +MN-D`(`#ZG@:XW0`!`/@#IM_T".^RSXX``0(^W@L"N-D`(`#ZG@:0W1"FW_0( +M\[+/3@`!/O<+`KC9`"``^IX&D-T$IM_T"//X`WX)#`)^&T$`^P4$V8`=``"] +M]*"?V80=``"@G]F8'0``H)_9C!T``*"?V9`=``"@G]F4'0``H)_9`6(``""? +MV0)B```@G]D`8@``()_9G!T``-J<&@``2T`!H)]^OS<`VMP;``!+F`%^OS<` +M^`#X^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +M^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX^/CX +0^/CX^/CX^/CX^/CX^/CX^``` +` +end Index: stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1-emc.dtsi =================================================================== --- stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1-emc.dtsi (revision 332009) +++ stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1-emc.dtsi (revision 332010) @@ -1,2421 +1,2422 @@ +// SPDX-License-Identifier: GPL-2.0 / { - clock@0,60006000 { + clock@60006000 { emc-timings-3 { nvidia,ram-code = <3>; timing-12750000 { clock-frequency = <12750000>; nvidia,parent-clock-frequency = <408000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "emc-parent"; }; timing-20400000 { clock-frequency = <20400000>; nvidia,parent-clock-frequency = <408000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "emc-parent"; }; timing-40800000 { clock-frequency = <40800000>; nvidia,parent-clock-frequency = <408000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "emc-parent"; }; timing-68000000 { clock-frequency = <68000000>; nvidia,parent-clock-frequency = <408000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "emc-parent"; }; timing-102000000 { clock-frequency = <102000000>; nvidia,parent-clock-frequency = <408000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "emc-parent"; }; timing-204000000 { clock-frequency = <204000000>; nvidia,parent-clock-frequency = <408000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "emc-parent"; }; timing-300000000 { clock-frequency = <300000000>; nvidia,parent-clock-frequency = <600000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_C>; clock-names = "emc-parent"; }; timing-396000000 { clock-frequency = <396000000>; nvidia,parent-clock-frequency = <792000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_M>; clock-names = "emc-parent"; }; timing-528000000 { clock-frequency = <528000000>; nvidia,parent-clock-frequency = <528000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>; clock-names = "emc-parent"; }; timing-600000000 { clock-frequency = <600000000>; nvidia,parent-clock-frequency = <600000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_C_UD>; clock-names = "emc-parent"; }; timing-792000000 { clock-frequency = <792000000>; nvidia,parent-clock-frequency = <792000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>; clock-names = "emc-parent"; }; timing-924000000 { clock-frequency = <924000000>; nvidia,parent-clock-frequency = <924000000>; clocks = <&tegra_car TEGRA124_CLK_PLL_M_UD>; clock-names = "emc-parent"; }; }; }; - emc@0,7001b000 { + emc@7001b000 { emc-timings-3 { nvidia,ram-code = <3>; timing-12750000 { clock-frequency = <12750000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000008>; nvidia,emc-cfg = <0x73240000>; nvidia,emc-cfg-2 = <0x000008c5>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100003>; nvidia,emc-mode-2 = <0x80200008>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80001221>; nvidia,emc-mrs-wait-cnt = <0x000e000e>; nvidia,emc-sel-dpd-ctrl = <0x00040128>; nvidia,emc-xm2dqspadctrl2 = <0x0130b118>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00000000>; nvidia,emc-configuration = < 0x00000000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000004 0x0000000a 0x00000005 0x0000000b 0x00000000 0x00000000 0x00000003 0x00000003 0x00000000 0x00000006 0x00000006 0x00000006 0x00000002 0x00000000 0x00000005 0x00000005 0x00010000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x0000000c 0x0000000d 0x0000000f 0x00000060 0x00000000 0x00000018 0x00000002 0x00000002 0x00000001 0x00000000 0x00000007 0x0000000f 0x00000005 0x00000005 0x00000004 0x00000005 0x00000004 0x00000000 0x00000000 0x00000005 0x00000005 0x00000064 0x00000000 0x00000000 0x00000000 0x106aa298 0x002c00a0 0x00008000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000fc000 0x000fc000 0x000fc000 0x000fc000 0x0000fc00 0x0000fc00 0x0000fc00 0x0000fc00 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000e0e 0x81f1f108 0x07070004 0x0000003f 0x016eeeee 0x51451400 0x00514514 0x00514514 0x51451400 0x0000003f 0x00000007 0x00000000 0x00000042 0x000e000e 0x00000000 0x00000003 0x0000f2f3 0x800001c5 0x0000000a >; }; timing-20400000 { clock-frequency = <20400000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000008>; nvidia,emc-cfg = <0x73240000>; nvidia,emc-cfg-2 = <0x000008c5>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100003>; nvidia,emc-mode-2 = <0x80200008>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80001221>; nvidia,emc-mrs-wait-cnt = <0x000e000e>; nvidia,emc-sel-dpd-ctrl = <0x00040128>; nvidia,emc-xm2dqspadctrl2 = <0x0130b118>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00000000>; nvidia,emc-configuration = < 0x00000000 0x00000005 0x00000000 0x00000000 0x00000000 0x00000004 0x0000000a 0x00000005 0x0000000b 0x00000000 0x00000000 0x00000003 0x00000003 0x00000000 0x00000006 0x00000006 0x00000006 0x00000002 0x00000000 0x00000005 0x00000005 0x00010000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x0000000c 0x0000000d 0x0000000f 0x0000009a 0x00000000 0x00000026 0x00000002 0x00000002 0x00000001 0x00000000 0x00000007 0x0000000f 0x00000006 0x00000006 0x00000004 0x00000005 0x00000004 0x00000000 0x00000000 0x00000005 0x00000005 0x000000a0 0x00000000 0x00000000 0x00000000 0x106aa298 0x002c00a0 0x00008000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000fc000 0x000fc000 0x000fc000 0x000fc000 0x0000fc00 0x0000fc00 0x0000fc00 0x0000fc00 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000e0e 0x81f1f108 0x07070004 0x0000003f 0x016eeeee 0x51451400 0x00514514 0x00514514 0x51451400 0x0000003f 0x0000000b 0x00000000 0x00000042 0x000e000e 0x00000000 0x00000003 0x0000f2f3 0x8000023a 0x0000000a >; }; timing-40800000 { clock-frequency = <40800000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000008>; nvidia,emc-cfg = <0x73240000>; nvidia,emc-cfg-2 = <0x000008c5>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100003>; nvidia,emc-mode-2 = <0x80200008>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80001221>; nvidia,emc-mrs-wait-cnt = <0x000e000e>; nvidia,emc-sel-dpd-ctrl = <0x00040128>; nvidia,emc-xm2dqspadctrl2 = <0x0130b118>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00000000>; nvidia,emc-configuration = < 0x00000001 0x0000000a 0x00000000 0x00000001 0x00000000 0x00000004 0x0000000a 0x00000005 0x0000000b 0x00000000 0x00000000 0x00000003 0x00000003 0x00000000 0x00000006 0x00000006 0x00000006 0x00000002 0x00000000 0x00000005 0x00000005 0x00010000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x0000000c 0x0000000d 0x0000000f 0x00000134 0x00000000 0x0000004d 0x00000002 0x00000002 0x00000001 0x00000000 0x00000008 0x0000000f 0x0000000c 0x0000000c 0x00000004 0x00000005 0x00000004 0x00000000 0x00000000 0x00000005 0x00000005 0x0000013f 0x00000000 0x00000000 0x00000000 0x106aa298 0x002c00a0 0x00008000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000fc000 0x000fc000 0x000fc000 0x000fc000 0x0000fc00 0x0000fc00 0x0000fc00 0x0000fc00 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000e0e 0x81f1f108 0x07070004 0x0000003f 0x016eeeee 0x51451400 0x00514514 0x00514514 0x51451400 0x0000003f 0x00000015 0x00000000 0x00000042 0x000e000e 0x00000000 0x00000003 0x0000f2f3 0x80000370 0x0000000a >; }; timing-68000000 { clock-frequency = <68000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000008>; nvidia,emc-cfg = <0x73240000>; nvidia,emc-cfg-2 = <0x000008c5>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100003>; nvidia,emc-mode-2 = <0x80200008>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80001221>; nvidia,emc-mrs-wait-cnt = <0x000e000e>; nvidia,emc-sel-dpd-ctrl = <0x00040128>; nvidia,emc-xm2dqspadctrl2 = <0x0130b118>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00000000>; nvidia,emc-configuration = < 0x00000003 0x00000011 0x00000000 0x00000002 0x00000000 0x00000004 0x0000000a 0x00000005 0x0000000b 0x00000000 0x00000000 0x00000003 0x00000003 0x00000000 0x00000006 0x00000006 0x00000006 0x00000002 0x00000000 0x00000005 0x00000005 0x00010000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x0000000c 0x0000000d 0x0000000f 0x00000202 0x00000000 0x00000080 0x00000002 0x00000002 0x00000001 0x00000000 0x0000000f 0x0000000f 0x00000013 0x00000013 0x00000004 0x00000005 0x00000004 0x00000001 0x00000000 0x00000005 0x00000005 0x00000213 0x00000000 0x00000000 0x00000000 0x106aa298 0x002c00a0 0x00008000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000fc000 0x000fc000 0x000fc000 0x000fc000 0x0000fc00 0x0000fc00 0x0000fc00 0x0000fc00 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000e0e 0x81f1f108 0x07070004 0x0000003f 0x016eeeee 0x51451400 0x00514514 0x00514514 0x51451400 0x0000003f 0x00000022 0x00000000 0x00000042 0x000e000e 0x00000000 0x00000003 0x0000f2f3 0x8000050e 0x0000000a >; }; timing-102000000 { clock-frequency = <102000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000008>; nvidia,emc-cfg = <0x73240000>; nvidia,emc-cfg-2 = <0x000008c5>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100003>; nvidia,emc-mode-2 = <0x80200008>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80001221>; nvidia,emc-mrs-wait-cnt = <0x000e000e>; nvidia,emc-sel-dpd-ctrl = <0x00040128>; nvidia,emc-xm2dqspadctrl2 = <0x0130b118>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00000000>; nvidia,emc-configuration = < 0x00000004 0x0000001a 0x00000000 0x00000003 0x00000001 0x00000004 0x0000000a 0x00000005 0x0000000b 0x00000001 0x00000001 0x00000003 0x00000003 0x00000000 0x00000006 0x00000006 0x00000006 0x00000002 0x00000000 0x00000005 0x00000005 0x00010000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x0000000c 0x0000000d 0x0000000f 0x00000304 0x00000000 0x000000c1 0x00000002 0x00000002 0x00000001 0x00000000 0x00000018 0x0000000f 0x0000001c 0x0000001c 0x00000004 0x00000005 0x00000004 0x00000002 0x00000000 0x00000005 0x00000005 0x0000031c 0x00000000 0x00000000 0x00000000 0x106aa298 0x002c00a0 0x00008000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x000fc000 0x000fc000 0x000fc000 0x000fc000 0x0000fc00 0x0000fc00 0x0000fc00 0x0000fc00 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000e0e 0x81f1f108 0x07070004 0x0000003f 0x016eeeee 0x51451400 0x00514514 0x00514514 0x51451400 0x0000003f 0x00000033 0x00000000 0x00000042 0x000e000e 0x00000000 0x00000003 0x0000f2f3 0x80000713 0x0000000a >; }; timing-204000000 { clock-frequency = <204000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000008>; nvidia,emc-cfg = <0x73240000>; nvidia,emc-cfg-2 = <0x000008cd>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100003>; nvidia,emc-mode-2 = <0x80200008>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80001221>; nvidia,emc-mrs-wait-cnt = <0x000e000e>; nvidia,emc-sel-dpd-ctrl = <0x00040128>; nvidia,emc-xm2dqspadctrl2 = <0x0130b118>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00020000>; nvidia,emc-configuration = < 0x00000009 0x00000035 0x00000000 0x00000006 0x00000002 0x00000005 0x0000000a 0x00000005 0x0000000b 0x00000002 0x00000002 0x00000003 0x00000003 0x00000000 0x00000005 0x00000005 0x00000006 0x00000002 0x00000000 0x00000004 0x00000006 0x00010000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000003 0x0000000d 0x0000000f 0x00000011 0x00000607 0x00000000 0x00000181 0x00000002 0x00000002 0x00000001 0x00000000 0x00000032 0x0000000f 0x00000038 0x00000038 0x00000004 0x00000005 0x00000004 0x00000006 0x00000000 0x00000005 0x00000005 0x00000638 0x00000000 0x00000000 0x00000000 0x106aa298 0x002c00a0 0x00008000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00080000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00008000 0x00000000 0x00000000 0x00008000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00090000 0x00090000 0x00090000 0x00090000 0x00009000 0x00009000 0x00009000 0x00009000 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000707 0x81f1f108 0x07070004 0x0000003f 0x016eeeee 0x51451400 0x00514514 0x00514514 0x51451400 0x0000003f 0x00000066 0x00000000 0x00000100 0x000e000e 0x00000000 0x00000003 0x0000d2b3 0x80000d22 0x0000000a >; }; timing-300000000 { clock-frequency = <300000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000000>; nvidia,emc-cfg = <0x73340000>; nvidia,emc-cfg-2 = <0x000008d5>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100002>; nvidia,emc-mode-2 = <0x80200000>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80000321>; nvidia,emc-mrs-wait-cnt = <0x0173000e>; nvidia,emc-sel-dpd-ctrl = <0x00040128>; nvidia,emc-xm2dqspadctrl2 = <0x01231339>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00020000>; nvidia,emc-configuration = < 0x0000000d 0x0000004d 0x00000000 0x00000009 0x00000003 0x00000004 0x00000008 0x00000002 0x00000009 0x00000003 0x00000003 0x00000002 0x00000002 0x00000000 0x00000003 0x00000003 0x00000005 0x00000002 0x00000000 0x00000002 0x00000007 0x00020000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x0000000e 0x00000010 0x00000012 0x000008e4 0x00000000 0x00000239 0x00000001 0x00000008 0x00000001 0x00000000 0x0000004b 0x0000000e 0x00000052 0x00000200 0x00000004 0x00000005 0x00000004 0x00000008 0x00000000 0x00000005 0x00000005 0x00000924 0x00000000 0x00000000 0x00000000 0x104ab098 0x002c00a0 0x00008000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00098000 0x00098000 0x00000000 0x00098000 0x00098000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00050000 0x00050000 0x00050000 0x00050000 0x00005000 0x00005000 0x00005000 0x00005000 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000505 0x81f1f108 0x07070004 0x00000000 0x016eeeee 0x51451420 0x00514514 0x00514514 0x51451400 0x0000003f 0x00000096 0x00000000 0x00000100 0x0173000e 0x00000000 0x00000003 0x000052a3 0x800012d7 0x00000009 >; }; timing-396000000 { clock-frequency = <396000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000000>; nvidia,emc-cfg = <0x73340000>; nvidia,emc-cfg-2 = <0x00000895>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100002>; nvidia,emc-mode-2 = <0x80200000>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80000521>; nvidia,emc-mrs-wait-cnt = <0x015b000e>; nvidia,emc-sel-dpd-ctrl = <0x00040008>; nvidia,emc-xm2dqspadctrl2 = <0x01231339>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00020000>; nvidia,emc-configuration = < 0x00000011 0x00000066 0x00000000 0x0000000c 0x00000004 0x00000004 0x00000008 0x00000002 0x0000000a 0x00000004 0x00000004 0x00000002 0x00000002 0x00000000 0x00000003 0x00000003 0x00000005 0x00000002 0x00000000 0x00000001 0x00000008 0x00020000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000f 0x00000010 0x00000012 0x00000bd1 0x00000000 0x000002f4 0x00000001 0x00000008 0x00000001 0x00000000 0x00000063 0x0000000f 0x0000006c 0x00000200 0x00000004 0x00000005 0x00000004 0x0000000b 0x00000000 0x00000005 0x00000005 0x00000c11 0x00000000 0x00000000 0x00000000 0x104ab098 0x002c00a0 0x00008000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00030000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00070000 0x00070000 0x00000000 0x00070000 0x00070000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00038000 0x00038000 0x00038000 0x00038000 0x00003800 0x00003800 0x00003800 0x00003800 0x10000280 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc081 0x00000505 0x81f1f108 0x07070004 0x00000000 0x016eeeee 0x51451420 0x00514514 0x00514514 0x51451400 0x0000003f 0x000000c6 0x00000000 0x00000100 0x015b000e 0x00000000 0x00000003 0x000052a3 0x8000188b 0x00000009 >; }; timing-528000000 { clock-frequency = <528000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000000>; nvidia,emc-cfg = <0x73300000>; nvidia,emc-cfg-2 = <0x0000089d>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100002>; nvidia,emc-mode-2 = <0x80200008>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80000941>; nvidia,emc-mrs-wait-cnt = <0x0139000e>; nvidia,emc-sel-dpd-ctrl = <0x00040008>; nvidia,emc-xm2dqspadctrl2 = <0x0123133d>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00020000>; nvidia,emc-configuration = < 0x00000018 0x00000088 0x00000000 0x00000010 0x00000006 0x00000006 0x00000009 0x00000002 0x0000000d 0x00000006 0x00000006 0x00000002 0x00000002 0x00000000 0x00000003 0x00000003 0x00000006 0x00000002 0x00000000 0x00000001 0x00000009 0x00030000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000010 0x00000012 0x00000014 0x00000fd6 0x00000000 0x000003f5 0x00000002 0x0000000b 0x00000001 0x00000000 0x00000085 0x00000012 0x00000090 0x00000200 0x00000004 0x00000005 0x00000004 0x00000010 0x00000000 0x00000006 0x00000006 0x00001017 0x00000000 0x00000000 0x00000000 0x104ab098 0xe01200b1 0x00008000 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00054000 0x00054000 0x00000000 0x00054000 0x00054000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000c 0x0000000c 0x0000000c 0x0000000c 0x0000000c 0x0000000c 0x0000000c 0x0000000c 0x100002a0 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc085 0x00000505 0x81f1f108 0x07070004 0x00000000 0x016eeeee 0x51451420 0x00514514 0x00514514 0x51451400 0x0606003f 0x00000000 0x00000000 0x00000100 0x0139000e 0x00000000 0x00000003 0x000042a0 0x80002062 0x0000000a >; }; timing-600000000 { clock-frequency = <600000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000000>; nvidia,emc-cfg = <0x73300000>; nvidia,emc-cfg-2 = <0x0000089d>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100002>; nvidia,emc-mode-2 = <0x80200010>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80000b61>; nvidia,emc-mrs-wait-cnt = <0x0127000e>; nvidia,emc-sel-dpd-ctrl = <0x00040008>; nvidia,emc-xm2dqspadctrl2 = <0x0121113d>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00020000>; nvidia,emc-configuration = < 0x0000001b 0x0000009b 0x00000000 0x00000013 0x00000007 0x00000007 0x0000000b 0x00000003 0x00000010 0x00000007 0x00000007 0x00000002 0x00000002 0x00000000 0x00000005 0x00000005 0x0000000a 0x00000002 0x00000000 0x00000003 0x0000000b 0x00070000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000002 0x00000012 0x00000016 0x00000018 0x00001208 0x00000000 0x00000482 0x00000002 0x0000000d 0x00000001 0x00000000 0x00000097 0x00000015 0x000000a3 0x00000200 0x00000004 0x00000005 0x00000004 0x00000013 0x00000000 0x00000006 0x00000006 0x00001248 0x00000000 0x00000000 0x00000000 0x104ab098 0xe00e00b1 0x00008000 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00048000 0x00048000 0x00000000 0x00048000 0x00048000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000d 0x0000000d 0x0000000d 0x0000000d 0x0000000d 0x0000000d 0x0000000d 0x0000000d 0x100002a0 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc085 0x00000505 0x81f1f108 0x07070004 0x00000000 0x016eeeee 0x51451420 0x00514514 0x00514514 0x51451400 0x0606003f 0x00000000 0x00000000 0x00000100 0x0127000e 0x00000000 0x00000003 0x000040a0 0x800024aa 0x0000000e >; }; timing-792000000 { clock-frequency = <792000000>; nvidia,emc-auto-cal-config = <0xa1430000>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000000>; nvidia,emc-cfg = <0x73300000>; nvidia,emc-cfg-2 = <0x0000089d>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100002>; nvidia,emc-mode-2 = <0x80200018>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80000d71>; nvidia,emc-mrs-wait-cnt = <0x00f7000e>; nvidia,emc-sel-dpd-ctrl = <0x00040000>; nvidia,emc-xm2dqspadctrl2 = <0x0120113d>; nvidia,emc-zcal-cnt-long = <0x00000042>; nvidia,emc-zcal-interval = <0x00020000>; nvidia,emc-configuration = < 0x00000024 0x000000cd 0x00000000 0x00000019 0x0000000a 0x00000008 0x0000000d 0x00000004 0x00000013 0x0000000a 0x0000000a 0x00000004 0x00000002 0x00000000 0x00000006 0x00000006 0x0000000b 0x00000002 0x00000000 0x00000002 0x0000000d 0x00080000 0x00000004 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x00000014 0x00000018 0x0000001a 0x000017e2 0x00000000 0x000005f8 0x00000003 0x00000011 0x00000001 0x00000000 0x000000c7 0x00000018 0x000000d7 0x00000200 0x00000005 0x00000006 0x00000005 0x00000019 0x00000000 0x00000008 0x00000008 0x00001822 0x00000000 0x00000000 0x00000000 0x104ab098 0xe00700b1 0x00008000 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x007fc008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00034000 0x00034000 0x00000000 0x00034000 0x00034000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x00000005 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x0000000a 0x100002a0 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc085 0x00000000 0x81f1f108 0x07070004 0x00000000 0x016eeeee 0x61861820 0x00514514 0x00514514 0x61861800 0x0606003f 0x00000000 0x00000000 0x00000100 0x00f7000e 0x00000000 0x00000004 0x00004080 0x80003012 0x0000000f >; }; timing-924000000 { clock-frequency = <924000000>; nvidia,emc-auto-cal-config = <0xa1430303>; nvidia,emc-auto-cal-config2 = <0x00000000>; nvidia,emc-auto-cal-config3 = <0x00000000>; nvidia,emc-auto-cal-interval = <0x001fffff>; nvidia,emc-bgbias-ctl0 = <0x00000000>; nvidia,emc-cfg = <0x73300000>; nvidia,emc-cfg-2 = <0x0000089d>; nvidia,emc-ctt-term-ctrl = <0x00000802>; nvidia,emc-mode-1 = <0x80100002>; nvidia,emc-mode-2 = <0x80200020>; nvidia,emc-mode-4 = <0x00000000>; nvidia,emc-mode-reset = <0x80000f15>; nvidia,emc-mrs-wait-cnt = <0x00cd000e>; nvidia,emc-sel-dpd-ctrl = <0x00040000>; nvidia,emc-xm2dqspadctrl2 = <0x0120113d>; nvidia,emc-zcal-cnt-long = <0x0000004c>; nvidia,emc-zcal-interval = <0x00020000>; nvidia,emc-configuration = < 0x0000002b 0x000000f0 0x00000000 0x0000001e 0x0000000b 0x00000009 0x0000000f 0x00000005 0x00000016 0x0000000b 0x0000000b 0x00000004 0x00000002 0x00000000 0x00000007 0x00000007 0x0000000d 0x00000002 0x00000000 0x00000002 0x0000000f 0x000a0000 0x00000004 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x00000016 0x0000001a 0x0000001c 0x00001be7 0x00000000 0x000006f9 0x00000004 0x00000015 0x00000001 0x00000000 0x000000e7 0x0000001b 0x000000fb 0x00000200 0x00000006 0x00000007 0x00000006 0x0000001e 0x00000000 0x0000000a 0x0000000a 0x00001c28 0x00000000 0x00000000 0x00000000 0x104ab898 0xe00400b1 0x00008000 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x007f800a 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x0002c000 0x0002c000 0x00000000 0x0002c000 0x0002c000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000004 0x00000008 0x00000008 0x00000008 0x00000008 0x00000008 0x00000008 0x00000008 0x00000008 0x100002a0 0x00000000 0x00111111 0x00000000 0x00000000 0x77ffc085 0x00000000 0x81f1f108 0x07070004 0x00000000 0x016eeeee 0x5d75d720 0x00514514 0x00514514 0x5d75d700 0x0606003f 0x00000000 0x00000000 0x00000128 0x00cd000e 0x00000000 0x00000004 0x00004080 0x800037ea 0x00000011 >; }; }; }; - memory-controller@0,70019000 { + memory-controller@70019000 { emc-timings-3 { nvidia,ram-code = <3>; timing-12750000 { clock-frequency = <12750000>; nvidia,emem-configuration = < 0x40040001 0x8000000a 0x00000001 0x00000001 0x00000002 0x00000000 0x00000002 0x00000001 0x00000003 0x00000008 0x00000003 0x00000002 0x00000003 0x00000006 0x06030203 0x000a0502 0x77e30303 0x70000f03 0x001f0000 >; }; timing-20400000 { clock-frequency = <20400000>; nvidia,emem-configuration = < 0x40020001 0x80000012 0x00000001 0x00000001 0x00000002 0x00000000 0x00000002 0x00000001 0x00000003 0x00000008 0x00000003 0x00000002 0x00000003 0x00000006 0x06030203 0x000a0502 0x76230303 0x70000f03 0x001f0000 >; }; timing-40800000 { clock-frequency = <40800000>; nvidia,emem-configuration = < 0xa0000001 0x80000017 0x00000001 0x00000001 0x00000002 0x00000000 0x00000002 0x00000001 0x00000003 0x00000008 0x00000003 0x00000002 0x00000003 0x00000006 0x06030203 0x000a0502 0x74a30303 0x70000f03 0x001f0000 >; }; timing-68000000 { clock-frequency = <68000000>; nvidia,emem-configuration = < 0x00000001 0x8000001e 0x00000001 0x00000001 0x00000002 0x00000000 0x00000002 0x00000001 0x00000003 0x00000008 0x00000003 0x00000002 0x00000003 0x00000006 0x06030203 0x000a0502 0x74230403 0x70000f03 0x001f0000 >; }; timing-102000000 { clock-frequency = <102000000>; nvidia,emem-configuration = < 0x08000001 0x80000026 0x00000001 0x00000001 0x00000003 0x00000000 0x00000002 0x00000001 0x00000003 0x00000008 0x00000003 0x00000002 0x00000003 0x00000006 0x06030203 0x000a0503 0x73c30504 0x70000f03 0x001f0000 >; }; timing-204000000 { clock-frequency = <204000000>; nvidia,emem-configuration = < 0x01000003 0x80000040 0x00000001 0x00000001 0x00000004 0x00000002 0x00000003 0x00000001 0x00000003 0x00000008 0x00000003 0x00000002 0x00000004 0x00000006 0x06040203 0x000a0504 0x73840a05 0x70000f03 0x001f0000 >; }; timing-300000000 { clock-frequency = <300000000>; nvidia,emem-configuration = < 0x08000004 0x80000040 0x00000001 0x00000002 0x00000007 0x00000004 0x00000004 0x00000001 0x00000002 0x00000007 0x00000002 0x00000002 0x00000004 0x00000006 0x06040202 0x000b0607 0x77450e08 0x70000f03 0x001f0000 >; }; timing-396000000 { clock-frequency = <396000000>; nvidia,emem-configuration = < 0x0f000005 0x80000040 0x00000001 0x00000002 0x00000009 0x00000005 0x00000006 0x00000001 0x00000002 0x00000008 0x00000002 0x00000002 0x00000004 0x00000006 0x06040202 0x000d0709 0x7586120a 0x70000f03 0x001f0000 >; }; timing-528000000 { clock-frequency = <528000000>; nvidia,emem-configuration = < 0x0f000007 0x80000040 0x00000002 0x00000003 0x0000000c 0x00000007 0x00000008 0x00000001 0x00000002 0x00000009 0x00000002 0x00000002 0x00000005 0x00000006 0x06050202 0x0010090c 0x7428180d 0x70000f03 0x001f0000 >; }; timing-600000000 { clock-frequency = <600000000>; nvidia,emem-configuration = < 0x00000009 0x80000040 0x00000003 0x00000004 0x0000000e 0x00000009 0x0000000a 0x00000001 0x00000003 0x0000000b 0x00000002 0x00000002 0x00000005 0x00000007 0x07050202 0x00130b0e 0x73a91b0f 0x70000f03 0x001f0000 >; }; timing-792000000 { clock-frequency = <792000000>; nvidia,emem-configuration = < 0x0e00000b 0x80000040 0x00000004 0x00000005 0x00000013 0x0000000c 0x0000000d 0x00000002 0x00000003 0x0000000c 0x00000002 0x00000002 0x00000006 0x00000008 0x08060202 0x00170e13 0x736c2414 0x70000f02 0x001f0000 >; }; timing-924000000 { clock-frequency = <924000000>; nvidia,emem-configuration = < 0x0e00000d 0x80000040 0x00000005 0x00000006 0x00000016 0x0000000e 0x0000000f 0x00000002 0x00000004 0x0000000e 0x00000002 0x00000002 0x00000006 0x00000009 0x09060202 0x001a1016 0x734e2a17 0x70000f02 0x001f0000 >; }; }; }; }; Property changes on: stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1-emc.dtsi ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1.dts =================================================================== --- stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1.dts (revision 332009) +++ stable/11/sys/gnu/dts/arm/tegra124-jetson-tk1.dts (revision 332010) @@ -1,1974 +1,2091 @@ +// SPDX-License-Identifier: GPL-2.0 /dts-v1/; #include #include "tegra124.dtsi" #include "tegra124-jetson-tk1-emc.dtsi" / { model = "NVIDIA Tegra124 Jetson TK1"; compatible = "nvidia,jetson-tk1", "nvidia,tegra124"; aliases { - rtc0 = "/i2c@0,7000d000/pmic@40"; - rtc1 = "/rtc@0,7000e000"; + rtc0 = "/i2c@7000d000/pmic@40"; + rtc1 = "/rtc@7000e000"; + + /* This order keeps the mapping DB9 connector <-> ttyS0 */ serial0 = &uartd; + serial1 = &uarta; + serial2 = &uartb; }; + chosen { + stdout-path = "serial0:115200n8"; + }; + memory { reg = <0x0 0x80000000 0x0 0x80000000>; }; - pcie-controller@0,01003000 { + pcie@1003000 { status = "okay"; avddio-pex-supply = <&vdd_1v05_run>; dvddio-pex-supply = <&vdd_1v05_run>; avdd-pex-pll-supply = <&vdd_1v05_run>; hvdd-pex-supply = <&vdd_3v3_lp0>; hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>; vddio-pex-ctl-supply = <&vdd_3v3_lp0>; avdd-pll-erefe-supply = <&avdd_1v05_run>; + /* Mini PCIe */ pci@1,0 { + phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>; + phy-names = "pcie-0"; status = "okay"; }; + /* Gigabit Ethernet */ pci@2,0 { + phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>; + phy-names = "pcie-0"; status = "okay"; }; }; - host1x@0,50000000 { - hdmi@0,54280000 { + host1x@50000000 { + hdmi@54280000 { status = "okay"; hdmi-supply = <&vdd_5v0_hdmi>; pll-supply = <&vdd_hdmi_pll>; vdd-supply = <&vdd_3v3_hdmi>; nvidia,ddc-i2c-bus = <&hdmi_ddc>; nvidia,hpd-gpio = <&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>; }; }; + cec@70015000 { + status = "okay"; + }; + gpu@0,57000000 { /* * Node left disabled on purpose - the bootloader will enable * it after having set the VPR up */ vdd-supply = <&vdd_gpu>; }; - pinmux: pinmux@0,70000868 { + pinmux: pinmux@70000868 { pinctrl-names = "boot"; pinctrl-0 = <&state_boot>; state_boot: pinmux { clk_32k_out_pa0 { nvidia,pins = "clk_32k_out_pa0"; nvidia,function = "soc"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart3_cts_n_pa1 { nvidia,pins = "uart3_cts_n_pa1"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap2_fs_pa2 { nvidia,pins = "dap2_fs_pa2"; nvidia,function = "i2s1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap2_sclk_pa3 { nvidia,pins = "dap2_sclk_pa3"; nvidia,function = "i2s1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap2_din_pa4 { nvidia,pins = "dap2_din_pa4"; nvidia,function = "i2s1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap2_dout_pa5 { nvidia,pins = "dap2_dout_pa5"; nvidia,function = "i2s1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_clk_pa6 { nvidia,pins = "sdmmc3_clk_pa6"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_cmd_pa7 { nvidia,pins = "sdmmc3_cmd_pa7"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pb0 { nvidia,pins = "pb0"; nvidia,function = "uartd"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pb1 { nvidia,pins = "pb1"; nvidia,function = "uartd"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_dat3_pb4 { nvidia,pins = "sdmmc3_dat3_pb4"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_dat2_pb5 { nvidia,pins = "sdmmc3_dat2_pb5"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_dat1_pb6 { nvidia,pins = "sdmmc3_dat1_pb6"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_dat0_pb7 { nvidia,pins = "sdmmc3_dat0_pb7"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart3_rts_n_pc0 { nvidia,pins = "uart3_rts_n_pc0"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart2_txd_pc2 { nvidia,pins = "uart2_txd_pc2"; nvidia,function = "irda"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart2_rxd_pc3 { nvidia,pins = "uart2_rxd_pc3"; nvidia,function = "irda"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gen1_i2c_scl_pc4 { nvidia,pins = "gen1_i2c_scl_pc4"; nvidia,function = "i2c1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; gen1_i2c_sda_pc5 { nvidia,pins = "gen1_i2c_sda_pc5"; nvidia,function = "i2c1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; pc7 { nvidia,pins = "pc7"; nvidia,function = "rsvd1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg0 { nvidia,pins = "pg0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg1 { nvidia,pins = "pg1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg2 { nvidia,pins = "pg2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg3 { nvidia,pins = "pg3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg4 { nvidia,pins = "pg4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg5 { nvidia,pins = "pg5"; nvidia,function = "spi4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg6 { nvidia,pins = "pg6"; nvidia,function = "spi4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pg7 { nvidia,pins = "pg7"; nvidia,function = "spi4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph0 { nvidia,pins = "ph0"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph1 { nvidia,pins = "ph1"; nvidia,function = "pwm1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph2 { nvidia,pins = "ph2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph3 { nvidia,pins = "ph3"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph4 { nvidia,pins = "ph4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph5 { nvidia,pins = "ph5"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph6 { nvidia,pins = "ph6"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ph7 { nvidia,pins = "ph7"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi0 { nvidia,pins = "pi0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi1 { nvidia,pins = "pi1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi2 { nvidia,pins = "pi2"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi3 { nvidia,pins = "pi3"; nvidia,function = "spi4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi4 { nvidia,pins = "pi4"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi5 { nvidia,pins = "pi5"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi6 { nvidia,pins = "pi6"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pi7 { nvidia,pins = "pi7"; nvidia,function = "rsvd1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pj0 { nvidia,pins = "pj0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pj2 { nvidia,pins = "pj2"; nvidia,function = "rsvd1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart2_cts_n_pj5 { nvidia,pins = "uart2_cts_n_pj5"; nvidia,function = "uartb"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart2_rts_n_pj6 { nvidia,pins = "uart2_rts_n_pj6"; nvidia,function = "uartb"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pj7 { nvidia,pins = "pj7"; nvidia,function = "uartd"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pk0 { nvidia,pins = "pk0"; nvidia,function = "rsvd1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pk1 { nvidia,pins = "pk1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pk2 { nvidia,pins = "pk2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pk3 { nvidia,pins = "pk3"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pk4 { nvidia,pins = "pk4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; spdif_out_pk5 { nvidia,pins = "spdif_out_pk5"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; spdif_in_pk6 { nvidia,pins = "spdif_in_pk6"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pk7 { nvidia,pins = "pk7"; nvidia,function = "uartd"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap1_fs_pn0 { nvidia,pins = "dap1_fs_pn0"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap1_din_pn1 { nvidia,pins = "dap1_din_pn1"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap1_dout_pn2 { nvidia,pins = "dap1_dout_pn2"; nvidia,function = "sata"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap1_sclk_pn3 { nvidia,pins = "dap1_sclk_pn3"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; usb_vbus_en0_pn4 { nvidia,pins = "usb_vbus_en0_pn4"; nvidia,function = "usb"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; usb_vbus_en1_pn5 { nvidia,pins = "usb_vbus_en1_pn5"; nvidia,function = "usb"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; hdmi_int_pn7 { nvidia,pins = "hdmi_int_pn7"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,rcv-sel = ; }; ulpi_data7_po0 { nvidia,pins = "ulpi_data7_po0"; nvidia,function = "ulpi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_data0_po1 { nvidia,pins = "ulpi_data0_po1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_data1_po2 { nvidia,pins = "ulpi_data1_po2"; nvidia,function = "ulpi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_data2_po3 { nvidia,pins = "ulpi_data2_po3"; nvidia,function = "ulpi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_data3_po4 { nvidia,pins = "ulpi_data3_po4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_data4_po5 { nvidia,pins = "ulpi_data4_po5"; nvidia,function = "ulpi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_data5_po6 { nvidia,pins = "ulpi_data5_po6"; nvidia,function = "ulpi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_data6_po7 { nvidia,pins = "ulpi_data6_po7"; nvidia,function = "ulpi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap3_fs_pp0 { nvidia,pins = "dap3_fs_pp0"; nvidia,function = "i2s2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap3_din_pp1 { nvidia,pins = "dap3_din_pp1"; nvidia,function = "i2s2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap3_dout_pp2 { nvidia,pins = "dap3_dout_pp2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap3_sclk_pp3 { nvidia,pins = "dap3_sclk_pp3"; nvidia,function = "rsvd3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap4_fs_pp4 { nvidia,pins = "dap4_fs_pp4"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap4_din_pp5 { nvidia,pins = "dap4_din_pp5"; nvidia,function = "rsvd3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap4_dout_pp6 { nvidia,pins = "dap4_dout_pp6"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap4_sclk_pp7 { nvidia,pins = "dap4_sclk_pp7"; nvidia,function = "rsvd3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col0_pq0 { nvidia,pins = "kb_col0_pq0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col1_pq1 { nvidia,pins = "kb_col1_pq1"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col2_pq2 { nvidia,pins = "kb_col2_pq2"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col3_pq3 { nvidia,pins = "kb_col3_pq3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col4_pq4 { nvidia,pins = "kb_col4_pq4"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col5_pq5 { nvidia,pins = "kb_col5_pq5"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col6_pq6 { nvidia,pins = "kb_col6_pq6"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_col7_pq7 { nvidia,pins = "kb_col7_pq7"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row0_pr0 { nvidia,pins = "kb_row0_pr0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row1_pr1 { nvidia,pins = "kb_row1_pr1"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row2_pr2 { nvidia,pins = "kb_row2_pr2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row3_pr3 { nvidia,pins = "kb_row3_pr3"; nvidia,function = "kbc"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row4_pr4 { nvidia,pins = "kb_row4_pr4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row5_pr5 { nvidia,pins = "kb_row5_pr5"; nvidia,function = "rsvd3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row6_pr6 { nvidia,pins = "kb_row6_pr6"; nvidia,function = "displaya_alt"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row7_pr7 { nvidia,pins = "kb_row7_pr7"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row8_ps0 { nvidia,pins = "kb_row8_ps0"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row9_ps1 { nvidia,pins = "kb_row9_ps1"; nvidia,function = "uarta"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row10_ps2 { nvidia,pins = "kb_row10_ps2"; nvidia,function = "uarta"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row11_ps3 { nvidia,pins = "kb_row11_ps3"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row12_ps4 { nvidia,pins = "kb_row12_ps4"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row13_ps5 { nvidia,pins = "kb_row13_ps5"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row14_ps6 { nvidia,pins = "kb_row14_ps6"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row15_ps7 { nvidia,pins = "kb_row15_ps7"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row16_pt0 { nvidia,pins = "kb_row16_pt0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; kb_row17_pt1 { nvidia,pins = "kb_row17_pt1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gen2_i2c_scl_pt5 { nvidia,pins = "gen2_i2c_scl_pt5"; nvidia,function = "i2c2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; gen2_i2c_sda_pt6 { nvidia,pins = "gen2_i2c_sda_pt6"; nvidia,function = "i2c2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; sdmmc4_cmd_pt7 { nvidia,pins = "sdmmc4_cmd_pt7"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pu0 { nvidia,pins = "pu0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pu1 { nvidia,pins = "pu1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pu2 { nvidia,pins = "pu2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pu3 { nvidia,pins = "pu3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pu4 { nvidia,pins = "pu4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pu5 { nvidia,pins = "pu5"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pu6 { nvidia,pins = "pu6"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pv0 { nvidia,pins = "pv0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pv1 { nvidia,pins = "pv1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_cd_n_pv2 { nvidia,pins = "sdmmc3_cd_n_pv2"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc1_wp_n_pv3 { nvidia,pins = "sdmmc1_wp_n_pv3"; nvidia,function = "sdmmc1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ddc_scl_pv4 { nvidia,pins = "ddc_scl_pv4"; nvidia,function = "i2c4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,rcv-sel = ; }; ddc_sda_pv5 { nvidia,pins = "ddc_sda_pv5"; nvidia,function = "i2c4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,rcv-sel = ; }; gpio_w2_aud_pw2 { nvidia,pins = "gpio_w2_aud_pw2"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gpio_w3_aud_pw3 { nvidia,pins = "gpio_w3_aud_pw3"; nvidia,function = "spi6"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap_mclk1_pw4 { nvidia,pins = "dap_mclk1_pw4"; nvidia,function = "extperiph1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; clk2_out_pw5 { nvidia,pins = "clk2_out_pw5"; nvidia,function = "extperiph2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart3_txd_pw6 { nvidia,pins = "uart3_txd_pw6"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; uart3_rxd_pw7 { nvidia,pins = "uart3_rxd_pw7"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dvfs_pwm_px0 { nvidia,pins = "dvfs_pwm_px0"; nvidia,function = "cldvfs"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gpio_x1_aud_px1 { nvidia,pins = "gpio_x1_aud_px1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dvfs_clk_px2 { nvidia,pins = "dvfs_clk_px2"; nvidia,function = "cldvfs"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gpio_x3_aud_px3 { nvidia,pins = "gpio_x3_aud_px3"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gpio_x4_aud_px4 { nvidia,pins = "gpio_x4_aud_px4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gpio_x5_aud_px5 { nvidia,pins = "gpio_x5_aud_px5"; nvidia,function = "rsvd4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gpio_x6_aud_px6 { nvidia,pins = "gpio_x6_aud_px6"; nvidia,function = "gmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; gpio_x7_aud_px7 { nvidia,pins = "gpio_x7_aud_px7"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_clk_py0 { nvidia,pins = "ulpi_clk_py0"; nvidia,function = "spi1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_dir_py1 { nvidia,pins = "ulpi_dir_py1"; nvidia,function = "spi1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_nxt_py2 { nvidia,pins = "ulpi_nxt_py2"; nvidia,function = "spi1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; ulpi_stp_py3 { nvidia,pins = "ulpi_stp_py3"; nvidia,function = "spi1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc1_dat3_py4 { nvidia,pins = "sdmmc1_dat3_py4"; nvidia,function = "sdmmc1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc1_dat2_py5 { nvidia,pins = "sdmmc1_dat2_py5"; nvidia,function = "sdmmc1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc1_dat1_py6 { nvidia,pins = "sdmmc1_dat1_py6"; nvidia,function = "sdmmc1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc1_dat0_py7 { nvidia,pins = "sdmmc1_dat0_py7"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc1_clk_pz0 { nvidia,pins = "sdmmc1_clk_pz0"; nvidia,function = "rsvd3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc1_cmd_pz1 { nvidia,pins = "sdmmc1_cmd_pz1"; nvidia,function = "sdmmc1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pwr_i2c_scl_pz6 { nvidia,pins = "pwr_i2c_scl_pz6"; nvidia,function = "i2cpwr"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; pwr_i2c_sda_pz7 { nvidia,pins = "pwr_i2c_sda_pz7"; nvidia,function = "i2cpwr"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; sdmmc4_dat0_paa0 { nvidia,pins = "sdmmc4_dat0_paa0"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_dat1_paa1 { nvidia,pins = "sdmmc4_dat1_paa1"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_dat2_paa2 { nvidia,pins = "sdmmc4_dat2_paa2"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_dat3_paa3 { nvidia,pins = "sdmmc4_dat3_paa3"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_dat4_paa4 { nvidia,pins = "sdmmc4_dat4_paa4"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_dat5_paa5 { nvidia,pins = "sdmmc4_dat5_paa5"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_dat6_paa6 { nvidia,pins = "sdmmc4_dat6_paa6"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_dat7_paa7 { nvidia,pins = "sdmmc4_dat7_paa7"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pbb0 { nvidia,pins = "pbb0"; nvidia,function = "vimclk2_alt"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; cam_i2c_scl_pbb1 { nvidia,pins = "cam_i2c_scl_pbb1"; nvidia,function = "i2c3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; cam_i2c_sda_pbb2 { nvidia,pins = "cam_i2c_sda_pbb2"; nvidia,function = "i2c3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; pbb3 { nvidia,pins = "pbb3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pbb4 { nvidia,pins = "pbb4"; nvidia,function = "vgp4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pbb5 { nvidia,pins = "pbb5"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pbb6 { nvidia,pins = "pbb6"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pbb7 { nvidia,pins = "pbb7"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; cam_mclk_pcc0 { nvidia,pins = "cam_mclk_pcc0"; nvidia,function = "vi_alt3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pcc1 { nvidia,pins = "pcc1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pcc2 { nvidia,pins = "pcc2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc4_clk_pcc4 { nvidia,pins = "sdmmc4_clk_pcc4"; nvidia,function = "sdmmc4"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; clk2_req_pcc5 { nvidia,pins = "clk2_req_pcc5"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pex_l0_rst_n_pdd1 { nvidia,pins = "pex_l0_rst_n_pdd1"; nvidia,function = "pe0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pex_l0_clkreq_n_pdd2 { nvidia,pins = "pex_l0_clkreq_n_pdd2"; nvidia,function = "pe0"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pex_wake_n_pdd3 { nvidia,pins = "pex_wake_n_pdd3"; nvidia,function = "pe"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pex_l1_rst_n_pdd5 { nvidia,pins = "pex_l1_rst_n_pdd5"; nvidia,function = "pe1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pex_l1_clkreq_n_pdd6 { nvidia,pins = "pex_l1_clkreq_n_pdd6"; nvidia,function = "pe1"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; clk3_out_pee0 { nvidia,pins = "clk3_out_pee0"; nvidia,function = "extperiph3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; clk3_req_pee1 { nvidia,pins = "clk3_req_pee1"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dap_mclk1_req_pee2 { nvidia,pins = "dap_mclk1_req_pee2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; hdmi_cec_pee3 { nvidia,pins = "hdmi_cec_pee3"; nvidia,function = "cec"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; sdmmc3_clk_lb_out_pee4 { nvidia,pins = "sdmmc3_clk_lb_out_pee4"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; sdmmc3_clk_lb_in_pee5 { nvidia,pins = "sdmmc3_clk_lb_in_pee5"; nvidia,function = "sdmmc3"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; dp_hpd_pff0 { nvidia,pins = "dp_hpd_pff0"; nvidia,function = "dp"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; usb_vbus_en2_pff1 { nvidia,pins = "usb_vbus_en2_pff1"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; pff2 { nvidia,pins = "pff2"; nvidia,function = "rsvd2"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; nvidia,open-drain = ; }; core_pwr_req { nvidia,pins = "core_pwr_req"; nvidia,function = "pwron"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; cpu_pwr_req { nvidia,pins = "cpu_pwr_req"; nvidia,function = "cpu"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; pwr_int_n { nvidia,pins = "pwr_int_n"; nvidia,function = "pmi"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; reset_out_n { nvidia,pins = "reset_out_n"; nvidia,function = "reset_out_n"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; - owr { - nvidia,pins = "owr"; - nvidia,function = "rsvd2"; - nvidia,pull = ; - nvidia,tristate = ; - nvidia,enable-input = ; - nvidia,rcv-sel = ; - }; clk_32k_in { nvidia,pins = "clk_32k_in"; nvidia,function = "clk"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; jtag_rtck { nvidia,pins = "jtag_rtck"; nvidia,function = "rtck"; nvidia,pull = ; nvidia,tristate = ; nvidia,enable-input = ; }; + dsi_b { + nvidia,pins = "mipi_pad_ctrl_dsi_b"; + nvidia,function = "dsi_b"; + }; }; }; + /* + * First high speed UART, exposed on the expansion connector J3A2 + * Pin 41: BR_UART1_TXD + * Pin 44: BR_UART1_RXD + */ + serial@70006000 { + compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart"; + status = "okay"; + }; + + /* + * Second high speed UART, exposed on the expansion connector J3A2 + * Pin 65: UART2_RXD + * Pin 68: UART2_TXD + * Pin 71: UART2_CTS_L + * Pin 74: UART2_RTS_L + */ + serial@70006040 { + compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart"; + status = "okay"; + }; + /* DB9 serial port */ - serial@0,70006300 { + serial@70006300 { status = "okay"; }; /* Expansion GEN1_I2C_*, mini-PCIe I2C, on-board components */ - i2c@0,7000c000 { + i2c@7000c000 { status = "okay"; clock-frequency = <100000>; rt5639: audio-codec@1c { compatible = "realtek,rt5639"; reg = <0x1c>; interrupt-parent = <&gpio>; interrupts = ; realtek,ldo1-en-gpios = <&gpio TEGRA_GPIO(R, 2) GPIO_ACTIVE_HIGH>; }; temperature-sensor@4c { compatible = "ti,tmp451"; reg = <0x4c>; interrupt-parent = <&gpio>; interrupts = ; }; eeprom@56 { compatible = "atmel,24c02"; reg = <0x56>; pagesize = <8>; }; }; /* Expansion GEN2_I2C_* */ - i2c@0,7000c400 { + i2c@7000c400 { status = "okay"; clock-frequency = <100000>; }; /* Expansion CAM_I2C_* */ - i2c@0,7000c500 { + i2c@7000c500 { status = "okay"; clock-frequency = <100000>; }; /* HDMI DDC */ - hdmi_ddc: i2c@0,7000c700 { + hdmi_ddc: i2c@7000c700 { status = "okay"; clock-frequency = <100000>; }; /* Expansion PWR_I2C_*, on-board components */ - i2c@0,7000d000 { + i2c@7000d000 { status = "okay"; clock-frequency = <400000>; pmic: pmic@40 { compatible = "ams,as3722"; reg = <0x40>; interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>; ams,system-power-controller; #interrupt-cells = <2>; interrupt-controller; gpio-controller; #gpio-cells = <2>; pinctrl-names = "default"; pinctrl-0 = <&as3722_default>; as3722_default: pinmux { gpio0 { pins = "gpio0"; function = "gpio"; bias-pull-down; }; gpio1_2_4_7 { pins = "gpio1", "gpio2", "gpio4", "gpio7"; function = "gpio"; bias-pull-up; }; gpio3_5_6 { pins = "gpio3", "gpio5", "gpio6"; bias-high-impedance; }; }; regulators { vsup-sd2-supply = <&vdd_5v0_sys>; vsup-sd3-supply = <&vdd_5v0_sys>; vsup-sd4-supply = <&vdd_5v0_sys>; vsup-sd5-supply = <&vdd_5v0_sys>; vin-ldo0-supply = <&vdd_1v35_lp0>; vin-ldo1-6-supply = <&vdd_3v3_run>; vin-ldo2-5-7-supply = <&vddio_1v8>; vin-ldo3-4-supply = <&vdd_3v3_sys>; vin-ldo9-10-supply = <&vdd_5v0_sys>; vin-ldo11-supply = <&vdd_3v3_run>; vdd_cpu: sd0 { regulator-name = "+VDD_CPU_AP"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1400000>; regulator-min-microamp = <3500000>; regulator-max-microamp = <3500000>; regulator-always-on; regulator-boot-on; ams,ext-control = <2>; }; sd1 { regulator-name = "+VDD_CORE"; regulator-min-microvolt = <700000>; regulator-max-microvolt = <1350000>; regulator-min-microamp = <2500000>; regulator-max-microamp = <2500000>; regulator-always-on; regulator-boot-on; ams,ext-control = <1>; }; vdd_1v35_lp0: sd2 { regulator-name = "+1.35V_LP0(sd2)"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-boot-on; }; sd3 { regulator-name = "+1.35V_LP0(sd3)"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-boot-on; }; vdd_1v05_run: sd4 { regulator-name = "+1.05V_RUN"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; }; vddio_1v8: sd5 { regulator-name = "+1.8V_VDDIO"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-boot-on; regulator-always-on; }; vdd_gpu: sd6 { regulator-name = "+VDD_GPU_AP"; regulator-min-microvolt = <650000>; regulator-max-microvolt = <1200000>; regulator-min-microamp = <3500000>; regulator-max-microamp = <3500000>; regulator-boot-on; regulator-always-on; }; avdd_1v05_run: ldo0 { regulator-name = "+1.05V_RUN_AVDD"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; regulator-boot-on; regulator-always-on; ams,ext-control = <1>; }; ldo1 { regulator-name = "+1.8V_RUN_CAM"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; ldo2 { regulator-name = "+1.2V_GEN_AVDD"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-boot-on; regulator-always-on; }; ldo3 { regulator-name = "+1.05V_LP0_VDD_RTC"; regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-boot-on; regulator-always-on; ams,enable-tracking; }; ldo4 { regulator-name = "+2.8V_RUN_CAM"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; }; ldo5 { regulator-name = "+1.2V_RUN_CAM_FRONT"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; }; vddio_sdmmc3: ldo6 { regulator-name = "+VDDIO_SDMMC3"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; }; ldo7 { regulator-name = "+1.05V_RUN_CAM_REAR"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; }; ldo9 { regulator-name = "+3.3V_RUN_TOUCH"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; }; ldo10 { regulator-name = "+2.8V_RUN_CAM_AF"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; }; ldo11 { regulator-name = "+1.8V_RUN_VPP_FUSE"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; }; }; }; /* Expansion TS_SPI_* */ - spi@0,7000d400 { + spi@7000d400 { status = "okay"; }; /* Internal SPI */ - spi@0,7000da00 { + spi@7000da00 { status = "okay"; spi-max-frequency = <25000000>; spi-flash@0 { compatible = "winbond,w25q32dw"; reg = <0>; spi-max-frequency = <20000000>; }; }; - pmc@0,7000e400 { + pmc@7000e400 { nvidia,invert-interrupt; nvidia,suspend-mode = <1>; nvidia,cpu-pwr-good-time = <500>; nvidia,cpu-pwr-off-time = <300>; nvidia,core-pwr-good-time = <641 3845>; nvidia,core-pwr-off-time = <61036>; nvidia,core-power-req-active-high; nvidia,sys-clock-req-active-high; i2c-thermtrip { nvidia,i2c-controller-id = <4>; nvidia,bus-addr = <0x40>; nvidia,reg-addr = <0x36>; nvidia,reg-data = <0x2>; }; }; /* Serial ATA */ - sata@0,70020000 { + sata@70020000 { status = "okay"; + phys = <&{/padctl@7009f000/pads/sata/lanes/sata-0}>; + phy-names = "sata-0"; + hvdd-supply = <&vdd_3v3_lp0>; vddio-supply = <&vdd_1v05_run>; avdd-supply = <&vdd_1v05_run>; target-5v-supply = <&vdd_5v0_sata>; target-12v-supply = <&vdd_12v0_sata>; }; - hda@0,70030000 { + hda@70030000 { status = "okay"; }; - padctl@0,7009f000 { - pinctrl-0 = <&padctl_default>; - pinctrl-names = "default"; + usb@70090000 { + phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>, /* Micro A/B */ + <&{/padctl@7009f000/pads/usb2/lanes/usb2-1}>, /* Mini PCIe */ + <&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>, /* USB3 */ + <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>; /* USB3 */ + phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0"; - padctl_default: pinmux { - usb3 { - nvidia,lanes = "pcie-0", "pcie-1"; - nvidia,function = "usb3"; - nvidia,iddq = <0>; + avddio-pex-supply = <&vdd_1v05_run>; + dvddio-pex-supply = <&vdd_1v05_run>; + avdd-usb-supply = <&vdd_3v3_lp0>; + avdd-pll-utmip-supply = <&vddio_1v8>; + avdd-pll-erefe-supply = <&avdd_1v05_run>; + avdd-usb-ss-pll-supply = <&vdd_1v05_run>; + hvdd-usb-ss-supply = <&vdd_3v3_lp0>; + hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>; + + status = "okay"; + }; + + padctl@7009f000 { + status = "okay"; + + pads { + usb2 { + status = "okay"; + + lanes { + usb2-0 { + nvidia,function = "snps"; + status = "okay"; + }; + + usb2-1 { + nvidia,function = "xusb"; + status = "okay"; + }; + + usb2-2 { + nvidia,function = "xusb"; + status = "okay"; + }; + }; }; pcie { - nvidia,lanes = "pcie-2", "pcie-3", - "pcie-4"; - nvidia,function = "pcie"; - nvidia,iddq = <0>; + status = "okay"; + + lanes { + pcie-0 { + nvidia,function = "usb3-ss"; + status = "okay"; + }; + + pcie-2 { + nvidia,function = "pcie"; + status = "okay"; + }; + + pcie-4 { + nvidia,function = "pcie"; + status = "okay"; + }; + }; }; sata { - nvidia,lanes = "sata-0"; - nvidia,function = "sata"; - nvidia,iddq = <0>; + status = "okay"; + + lanes { + sata-0 { + nvidia,function = "sata"; + status = "okay"; + }; + }; }; }; + + ports { + /* Micro A/B */ + usb2-0 { + status = "okay"; + mode = "otg"; + }; + + /* Mini PCIe */ + usb2-1 { + status = "okay"; + mode = "host"; + }; + + /* USB3 */ + usb2-2 { + status = "okay"; + mode = "host"; + + vbus-supply = <&vdd_usb3_vbus>; + }; + + usb3-0 { + nvidia,usb2-companion = <2>; + status = "okay"; + }; + }; }; /* SD card */ - sdhci@0,700b0400 { + sdhci@700b0400 { status = "okay"; cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>; power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>; wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_HIGH>; bus-width = <4>; vqmmc-supply = <&vddio_sdmmc3>; }; /* eMMC */ - sdhci@0,700b0600 { + sdhci@700b0600 { status = "okay"; bus-width = <8>; non-removable; }; /* CPU DFLL clock */ - clock@0,70110000 { + clock@70110000 { status = "okay"; vdd-cpu-supply = <&vdd_cpu>; nvidia,i2c-fs-rate = <400000>; }; - ahub@0,70300000 { - i2s@0,70301100 { + ahub@70300000 { + i2s@70301100 { status = "okay"; }; }; + usb@7d000000 { + compatible = "nvidia,tegra124-udc"; + status = "okay"; + dr_mode = "peripheral"; + }; + + usb-phy@7d000000 { + status = "okay"; + }; + /* mini-PCIe USB */ - usb@0,7d004000 { + usb@7d004000 { status = "okay"; }; - usb-phy@0,7d004000 { + usb-phy@7d004000 { status = "okay"; }; /* USB A connector */ - usb@0,7d008000 { + usb@7d008000 { status = "okay"; }; - usb-phy@0,7d008000 { + usb-phy@7d008000 { status = "okay"; vbus-supply = <&vdd_usb3_vbus>; }; clocks { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <0>; clk32k_in: clock@0 { compatible = "fixed-clock"; reg = <0>; #clock-cells = <0>; clock-frequency = <32768>; }; }; cpus { cpu@0 { vdd-cpu-supply = <&vdd_cpu>; }; }; gpio-keys { compatible = "gpio-keys"; power { label = "Power"; gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <10>; - gpio-key,wakeup; + wakeup-source; }; }; regulators { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <0>; vdd_mux: regulator@0 { compatible = "regulator-fixed"; reg = <0>; regulator-name = "+VDD_MUX"; regulator-min-microvolt = <12000000>; regulator-max-microvolt = <12000000>; regulator-always-on; regulator-boot-on; }; vdd_5v0_sys: regulator@1 { compatible = "regulator-fixed"; reg = <1>; regulator-name = "+5V_SYS"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; regulator-boot-on; vin-supply = <&vdd_mux>; }; vdd_3v3_sys: regulator@2 { compatible = "regulator-fixed"; reg = <2>; regulator-name = "+3.3V_SYS"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; vin-supply = <&vdd_mux>; }; vdd_3v3_run: regulator@3 { compatible = "regulator-fixed"; reg = <3>; regulator-name = "+3.3V_RUN"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; gpio = <&pmic 1 GPIO_ACTIVE_HIGH>; enable-active-high; vin-supply = <&vdd_3v3_sys>; }; vdd_3v3_hdmi: regulator@4 { compatible = "regulator-fixed"; reg = <4>; regulator-name = "+3.3V_AVDD_HDMI_AP_GATED"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; vin-supply = <&vdd_3v3_run>; }; vdd_usb1_vbus: regulator@7 { compatible = "regulator-fixed"; reg = <7>; regulator-name = "+USB0_VBUS_SW"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; gpio = <&gpio TEGRA_GPIO(N, 4) GPIO_ACTIVE_HIGH>; enable-active-high; gpio-open-drain; vin-supply = <&vdd_5v0_sys>; }; vdd_usb3_vbus: regulator@8 { compatible = "regulator-fixed"; reg = <8>; regulator-name = "+5V_USB_HS"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; gpio = <&gpio TEGRA_GPIO(N, 5) GPIO_ACTIVE_HIGH>; enable-active-high; gpio-open-drain; vin-supply = <&vdd_5v0_sys>; }; vdd_3v3_lp0: regulator@10 { compatible = "regulator-fixed"; reg = <10>; regulator-name = "+3.3V_LP0"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; gpio = <&pmic 2 GPIO_ACTIVE_HIGH>; enable-active-high; vin-supply = <&vdd_3v3_sys>; }; vdd_hdmi_pll: regulator@11 { compatible = "regulator-fixed"; reg = <11>; regulator-name = "+1.05V_RUN_AVDD_HDMI_PLL"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1050000>; gpio = <&gpio TEGRA_GPIO(H, 7) GPIO_ACTIVE_LOW>; vin-supply = <&vdd_1v05_run>; }; vdd_5v0_hdmi: regulator@12 { compatible = "regulator-fixed"; reg = <12>; regulator-name = "+5V_HDMI_CON"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; gpio = <&gpio TEGRA_GPIO(K, 6) GPIO_ACTIVE_HIGH>; enable-active-high; vin-supply = <&vdd_5v0_sys>; }; /* Molex power connector */ vdd_5v0_sata: regulator@13 { compatible = "regulator-fixed"; reg = <13>; regulator-name = "+5V_SATA"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; gpio = <&gpio TEGRA_GPIO(EE, 2) GPIO_ACTIVE_HIGH>; enable-active-high; vin-supply = <&vdd_5v0_sys>; }; vdd_12v0_sata: regulator@14 { compatible = "regulator-fixed"; reg = <14>; regulator-name = "+12V_SATA"; regulator-min-microvolt = <12000000>; regulator-max-microvolt = <12000000>; gpio = <&gpio TEGRA_GPIO(EE, 2) GPIO_ACTIVE_HIGH>; enable-active-high; vin-supply = <&vdd_mux>; }; }; sound { compatible = "nvidia,tegra-audio-rt5640-jetson-tk1", "nvidia,tegra-audio-rt5640"; nvidia,model = "NVIDIA Tegra Jetson TK1"; nvidia,audio-routing = "Headphones", "HPOR", "Headphones", "HPOL", "Mic Jack", "MICBIAS1", "IN2P", "Mic Jack"; nvidia,i2s-controller = <&tegra_i2s1>; nvidia,audio-codec = <&rt5639>; nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_LOW>; clocks = <&tegra_car TEGRA124_CLK_PLL_A>, <&tegra_car TEGRA124_CLK_PLL_A_OUT0>, <&tegra_car TEGRA124_CLK_EXTERN1>; clock-names = "pll_a", "pll_a_out0", "mclk"; }; thermal-zones { cpu { trips { - trip@0 { + cpu-shutdown-trip { temperature = <101000>; hysteresis = <0>; type = "critical"; }; }; - - cooling-maps { - /* There are currently no cooling maps because there are no cooling devices */ - }; }; mem { trips { - trip@0 { + mem-shutdown-trip { temperature = <101000>; hysteresis = <0>; type = "critical"; }; }; - - cooling-maps { - /* There are currently no cooling maps because there are no cooling devices */ - }; }; gpu { trips { - trip@0 { + gpu-shutdown-trip { temperature = <101000>; hysteresis = <0>; type = "critical"; }; - }; - - cooling-maps { - /* There are currently no cooling maps because there are no cooling devices */ }; }; }; }; Index: stable/11/sys/gnu/dts/arm/tegra124.dtsi =================================================================== --- stable/11/sys/gnu/dts/arm/tegra124.dtsi (revision 332009) +++ stable/11/sys/gnu/dts/arm/tegra124.dtsi (revision 332010) @@ -1,1038 +1,1291 @@ +// SPDX-License-Identifier: GPL-2.0 #include #include #include #include -#include #include #include #include #include "skeleton.dtsi" / { compatible = "nvidia,tegra124"; interrupt-parent = <&lic>; #address-cells = <2>; #size-cells = <2>; - pcie-controller@0,01003000 { + pcie@1003000 { compatible = "nvidia,tegra124-pcie"; device_type = "pci"; reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ 0x0 0x01003800 0x0 0x00000800 /* AFI registers */ 0x0 0x02000000 0x0 0x10000000>; /* configuration space */ reg-names = "pads", "afi", "cs"; interrupts = , /* controller interrupt */ ; /* MSI interrupt */ interrupt-names = "intr", "msi"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; bus-range = <0x00 0xff>; #address-cells = <3>; #size-cells = <2>; ranges = <0x82000000 0 0x01000000 0x0 0x01000000 0 0x00001000 /* port 0 configuration space */ 0x82000000 0 0x01001000 0x0 0x01001000 0 0x00001000 /* port 1 configuration space */ 0x81000000 0 0x0 0x0 0x12000000 0 0x00010000 /* downstream I/O (64 KiB) */ 0x82000000 0 0x13000000 0x0 0x13000000 0 0x0d000000 /* non-prefetchable memory (208 MiB) */ 0xc2000000 0 0x20000000 0x0 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */ clocks = <&tegra_car TEGRA124_CLK_PCIE>, <&tegra_car TEGRA124_CLK_AFI>, <&tegra_car TEGRA124_CLK_PLL_E>, <&tegra_car TEGRA124_CLK_CML0>; clock-names = "pex", "afi", "pll_e", "cml"; resets = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 74>; reset-names = "pex", "afi", "pcie_x"; status = "disabled"; - phys = <&padctl TEGRA_XUSB_PADCTL_PCIE>; - phy-names = "pcie"; - pci@1,0 { device_type = "pci"; assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>; reg = <0x000800 0 0 0 0>; + bus-range = <0x00 0xff>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <2>; }; pci@2,0 { device_type = "pci"; assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>; reg = <0x001000 0 0 0 0>; + bus-range = <0x00 0xff>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <1>; }; }; - host1x@0,50000000 { + host1x@50000000 { compatible = "nvidia,tegra124-host1x", "simple-bus"; reg = <0x0 0x50000000 0x0 0x00034000>; interrupts = , /* syncpt */ ; /* general */ clocks = <&tegra_car TEGRA124_CLK_HOST1X>; resets = <&tegra_car 28>; reset-names = "host1x"; + iommus = <&mc TEGRA_SWGROUP_HC>; #address-cells = <2>; #size-cells = <2>; ranges = <0 0x54000000 0 0x54000000 0 0x01000000>; - dc@0,54200000 { + dc@54200000 { compatible = "nvidia,tegra124-dc"; reg = <0x0 0x54200000 0x0 0x00040000>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_DISP1>, <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "dc", "parent"; resets = <&tegra_car 27>; reset-names = "dc"; iommus = <&mc TEGRA_SWGROUP_DC>; nvidia,head = <0>; }; - dc@0,54240000 { + dc@54240000 { compatible = "nvidia,tegra124-dc"; reg = <0x0 0x54240000 0x0 0x00040000>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_DISP2>, <&tegra_car TEGRA124_CLK_PLL_P>; clock-names = "dc", "parent"; resets = <&tegra_car 26>; reset-names = "dc"; iommus = <&mc TEGRA_SWGROUP_DCB>; nvidia,head = <1>; }; - hdmi@0,54280000 { + hdmi: hdmi@54280000 { compatible = "nvidia,tegra124-hdmi"; reg = <0x0 0x54280000 0x0 0x00040000>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_HDMI>, <&tegra_car TEGRA124_CLK_PLL_D2_OUT0>; clock-names = "hdmi", "parent"; resets = <&tegra_car 51>; reset-names = "hdmi"; status = "disabled"; }; - sor@0,54540000 { + sor@54540000 { compatible = "nvidia,tegra124-sor"; reg = <0x0 0x54540000 0x0 0x00040000>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_SOR0>, <&tegra_car TEGRA124_CLK_PLL_D_OUT0>, <&tegra_car TEGRA124_CLK_PLL_DP>, <&tegra_car TEGRA124_CLK_CLK_M>; clock-names = "sor", "parent", "dp", "safe"; resets = <&tegra_car 182>; reset-names = "sor"; status = "disabled"; }; - dpaux: dpaux@0,545c0000 { + dpaux: dpaux@545c0000 { compatible = "nvidia,tegra124-dpaux"; reg = <0x0 0x545c0000 0x0 0x00040000>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_DPAUX>, <&tegra_car TEGRA124_CLK_PLL_DP>; clock-names = "dpaux", "parent"; resets = <&tegra_car 181>; reset-names = "dpaux"; status = "disabled"; }; }; - gic: interrupt-controller@0,50041000 { + gic: interrupt-controller@50041000 { compatible = "arm,cortex-a15-gic"; #interrupt-cells = <3>; interrupt-controller; reg = <0x0 0x50041000 0x0 0x1000>, <0x0 0x50042000 0x0 0x1000>, <0x0 0x50044000 0x0 0x2000>, <0x0 0x50046000 0x0 0x2000>; interrupts = ; interrupt-parent = <&gic>; }; + /* + * Please keep the following 0, notation in place as a former mainline + * U-Boot version was looking for that particular notation in order to + * perform required fix-ups on that GPU node. + */ gpu@0,57000000 { compatible = "nvidia,gk20a"; reg = <0x0 0x57000000 0x0 0x01000000>, <0x0 0x58000000 0x0 0x01000000>; interrupts = , ; interrupt-names = "stall", "nonstall"; clocks = <&tegra_car TEGRA124_CLK_GPU>, <&tegra_car TEGRA124_CLK_PLL_P_OUT5>; clock-names = "gpu", "pwr"; resets = <&tegra_car 184>; reset-names = "gpu"; iommus = <&mc TEGRA_SWGROUP_GPU>; status = "disabled"; }; lic: interrupt-controller@60004000 { compatible = "nvidia,tegra124-ictlr", "nvidia,tegra30-ictlr"; reg = <0x0 0x60004000 0x0 0x100>, <0x0 0x60004100 0x0 0x100>, <0x0 0x60004200 0x0 0x100>, <0x0 0x60004300 0x0 0x100>, <0x0 0x60004400 0x0 0x100>; interrupt-controller; #interrupt-cells = <3>; interrupt-parent = <&gic>; }; - timer@0,60005000 { - compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer"; + timer@60005000 { + compatible = "nvidia,tegra124-timer", "nvidia,tegra30-timer", "nvidia,tegra20-timer"; reg = <0x0 0x60005000 0x0 0x400>; interrupts = , , , , , ; clocks = <&tegra_car TEGRA124_CLK_TIMER>; }; - tegra_car: clock@0,60006000 { + tegra_car: clock@60006000 { compatible = "nvidia,tegra124-car"; reg = <0x0 0x60006000 0x0 0x1000>; #clock-cells = <1>; #reset-cells = <1>; nvidia,external-memory-controller = <&emc>; }; - flow-controller@0,60007000 { + flow-controller@60007000 { compatible = "nvidia,tegra124-flowctrl"; reg = <0x0 0x60007000 0x0 0x1000>; }; - actmon@0,6000c800 { + actmon@6000c800 { compatible = "nvidia,tegra124-actmon"; reg = <0x0 0x6000c800 0x0 0x400>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_ACTMON>, <&tegra_car TEGRA124_CLK_EMC>; clock-names = "actmon", "emc"; resets = <&tegra_car 119>; reset-names = "actmon"; }; - gpio: gpio@0,6000d000 { + gpio: gpio@6000d000 { compatible = "nvidia,tegra124-gpio", "nvidia,tegra30-gpio"; reg = <0x0 0x6000d000 0x0 0x1000>; interrupts = , , , , , , , ; #gpio-cells = <2>; gpio-controller; #interrupt-cells = <2>; interrupt-controller; /* gpio-ranges = <&pinmux 0 0 251>; */ }; - apbdma: dma@0,60020000 { + apbdma: dma@60020000 { compatible = "nvidia,tegra124-apbdma", "nvidia,tegra148-apbdma"; reg = <0x0 0x60020000 0x0 0x1400>; interrupts = , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ; clocks = <&tegra_car TEGRA124_CLK_APBDMA>; resets = <&tegra_car 34>; reset-names = "dma"; #dma-cells = <1>; }; - apbmisc@0,70000800 { + apbmisc@70000800 { compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc"; reg = <0x0 0x70000800 0x0 0x64>, /* Chip revision */ <0x0 0x7000e864 0x0 0x04>; /* Strapping options */ }; - pinmux: pinmux@0,70000868 { + pinmux: pinmux@70000868 { compatible = "nvidia,tegra124-pinmux"; reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */ <0x0 0x70003000 0x0 0x434>, /* Mux registers */ <0x0 0x70000820 0x0 0x008>; /* MIPI pad control */ }; /* * There are two serial driver i.e. 8250 based simple serial * driver and APB DMA based serial driver for higher baudrate * and performace. To enable the 8250 based driver, the compatible * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable - * the APB DMA based serial driver, the comptible is + * the APB DMA based serial driver, the compatible is * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart". */ - uarta: serial@0,70006000 { + uarta: serial@70006000 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006000 0x0 0x40>; reg-shift = <2>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_UARTA>; resets = <&tegra_car 6>; reset-names = "serial"; dmas = <&apbdma 8>, <&apbdma 8>; dma-names = "rx", "tx"; status = "disabled"; }; - uartb: serial@0,70006040 { + uartb: serial@70006040 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006040 0x0 0x40>; reg-shift = <2>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_UARTB>; resets = <&tegra_car 7>; reset-names = "serial"; dmas = <&apbdma 9>, <&apbdma 9>; dma-names = "rx", "tx"; status = "disabled"; }; - uartc: serial@0,70006200 { + uartc: serial@70006200 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006200 0x0 0x40>; reg-shift = <2>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_UARTC>; resets = <&tegra_car 55>; reset-names = "serial"; dmas = <&apbdma 10>, <&apbdma 10>; dma-names = "rx", "tx"; status = "disabled"; }; - uartd: serial@0,70006300 { + uartd: serial@70006300 { compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart"; reg = <0x0 0x70006300 0x0 0x40>; reg-shift = <2>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_UARTD>; resets = <&tegra_car 65>; reset-names = "serial"; dmas = <&apbdma 19>, <&apbdma 19>; dma-names = "rx", "tx"; status = "disabled"; }; - pwm: pwm@0,7000a000 { + pwm: pwm@7000a000 { compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm"; reg = <0x0 0x7000a000 0x0 0x100>; #pwm-cells = <2>; clocks = <&tegra_car TEGRA124_CLK_PWM>; resets = <&tegra_car 17>; reset-names = "pwm"; status = "disabled"; }; - i2c@0,7000c000 { + i2c@7000c000 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c000 0x0 0x100>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_I2C1>; clock-names = "div-clk"; resets = <&tegra_car 12>; reset-names = "i2c"; dmas = <&apbdma 21>, <&apbdma 21>; dma-names = "rx", "tx"; status = "disabled"; }; - i2c@0,7000c400 { + i2c@7000c400 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c400 0x0 0x100>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_I2C2>; clock-names = "div-clk"; resets = <&tegra_car 54>; reset-names = "i2c"; dmas = <&apbdma 22>, <&apbdma 22>; dma-names = "rx", "tx"; status = "disabled"; }; - i2c@0,7000c500 { + i2c@7000c500 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c500 0x0 0x100>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_I2C3>; clock-names = "div-clk"; resets = <&tegra_car 67>; reset-names = "i2c"; dmas = <&apbdma 23>, <&apbdma 23>; dma-names = "rx", "tx"; status = "disabled"; }; - i2c@0,7000c700 { + i2c@7000c700 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000c700 0x0 0x100>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_I2C4>; clock-names = "div-clk"; resets = <&tegra_car 103>; reset-names = "i2c"; dmas = <&apbdma 26>, <&apbdma 26>; dma-names = "rx", "tx"; status = "disabled"; }; - i2c@0,7000d000 { + i2c@7000d000 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000d000 0x0 0x100>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_I2C5>; clock-names = "div-clk"; resets = <&tegra_car 47>; reset-names = "i2c"; dmas = <&apbdma 24>, <&apbdma 24>; dma-names = "rx", "tx"; status = "disabled"; }; - i2c@0,7000d100 { + i2c@7000d100 { compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c"; reg = <0x0 0x7000d100 0x0 0x100>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_I2C6>; clock-names = "div-clk"; resets = <&tegra_car 166>; reset-names = "i2c"; dmas = <&apbdma 30>, <&apbdma 30>; dma-names = "rx", "tx"; status = "disabled"; }; - spi@0,7000d400 { + spi@7000d400 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d400 0x0 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_SBC1>; clock-names = "spi"; resets = <&tegra_car 41>; reset-names = "spi"; dmas = <&apbdma 15>, <&apbdma 15>; dma-names = "rx", "tx"; status = "disabled"; }; - spi@0,7000d600 { + spi@7000d600 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d600 0x0 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_SBC2>; clock-names = "spi"; resets = <&tegra_car 44>; reset-names = "spi"; dmas = <&apbdma 16>, <&apbdma 16>; dma-names = "rx", "tx"; status = "disabled"; }; - spi@0,7000d800 { + spi@7000d800 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000d800 0x0 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_SBC3>; clock-names = "spi"; resets = <&tegra_car 46>; reset-names = "spi"; dmas = <&apbdma 17>, <&apbdma 17>; dma-names = "rx", "tx"; status = "disabled"; }; - spi@0,7000da00 { + spi@7000da00 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000da00 0x0 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_SBC4>; clock-names = "spi"; resets = <&tegra_car 68>; reset-names = "spi"; dmas = <&apbdma 18>, <&apbdma 18>; dma-names = "rx", "tx"; status = "disabled"; }; - spi@0,7000dc00 { + spi@7000dc00 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000dc00 0x0 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_SBC5>; clock-names = "spi"; resets = <&tegra_car 104>; reset-names = "spi"; dmas = <&apbdma 27>, <&apbdma 27>; dma-names = "rx", "tx"; status = "disabled"; }; - spi@0,7000de00 { + spi@7000de00 { compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi"; reg = <0x0 0x7000de00 0x0 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&tegra_car TEGRA124_CLK_SBC6>; clock-names = "spi"; resets = <&tegra_car 105>; reset-names = "spi"; dmas = <&apbdma 28>, <&apbdma 28>; dma-names = "rx", "tx"; status = "disabled"; }; - rtc@0,7000e000 { + rtc@7000e000 { compatible = "nvidia,tegra124-rtc", "nvidia,tegra20-rtc"; reg = <0x0 0x7000e000 0x0 0x100>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_RTC>; }; - pmc@0,7000e400 { + pmc@7000e400 { compatible = "nvidia,tegra124-pmc"; reg = <0x0 0x7000e400 0x0 0x400>; clocks = <&tegra_car TEGRA124_CLK_PCLK>, <&clk32k_in>; clock-names = "pclk", "clk32k_in"; }; - fuse@0,7000f800 { + fuse@7000f800 { compatible = "nvidia,tegra124-efuse"; reg = <0x0 0x7000f800 0x0 0x400>; clocks = <&tegra_car TEGRA124_CLK_FUSE>; clock-names = "fuse"; resets = <&tegra_car 39>; reset-names = "fuse"; }; - mc: memory-controller@0,70019000 { + mc: memory-controller@70019000 { compatible = "nvidia,tegra124-mc"; reg = <0x0 0x70019000 0x0 0x1000>; clocks = <&tegra_car TEGRA124_CLK_MC>; clock-names = "mc"; interrupts = ; #iommu-cells = <1>; }; - emc: emc@0,7001b000 { + emc: emc@7001b000 { compatible = "nvidia,tegra124-emc"; reg = <0x0 0x7001b000 0x0 0x1000>; nvidia,memory-controller = <&mc>; }; - sata@0,70020000 { + sata@70020000 { compatible = "nvidia,tegra124-ahci"; reg = <0x0 0x70027000 0x0 0x2000>, /* AHCI */ <0x0 0x70020000 0x0 0x7000>; /* SATA */ interrupts = ; clocks = <&tegra_car TEGRA124_CLK_SATA>, <&tegra_car TEGRA124_CLK_SATA_OOB>, <&tegra_car TEGRA124_CLK_CML1>, <&tegra_car TEGRA124_CLK_PLL_E>; clock-names = "sata", "sata-oob", "cml1", "pll_e"; resets = <&tegra_car 124>, <&tegra_car 123>, <&tegra_car 129>; reset-names = "sata", "sata-oob", "sata-cold"; - phys = <&padctl TEGRA_XUSB_PADCTL_SATA>; - phy-names = "sata-phy"; status = "disabled"; }; - hda@0,70030000 { + hda@70030000 { compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda"; reg = <0x0 0x70030000 0x0 0x10000>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_HDA>, <&tegra_car TEGRA124_CLK_HDA2HDMI>, <&tegra_car TEGRA124_CLK_HDA2CODEC_2X>; clock-names = "hda", "hda2hdmi", "hda2codec_2x"; resets = <&tegra_car 125>, /* hda */ <&tegra_car 128>, /* hda2hdmi */ <&tegra_car 111>; /* hda2codec_2x */ reset-names = "hda", "hda2hdmi", "hda2codec_2x"; status = "disabled"; }; - padctl: padctl@0,7009f000 { + usb@70090000 { + compatible = "nvidia,tegra124-xusb"; + reg = <0x0 0x70090000 0x0 0x8000>, + <0x0 0x70098000 0x0 0x1000>, + <0x0 0x70099000 0x0 0x1000>; + reg-names = "hcd", "fpci", "ipfs"; + + interrupts = , + ; + + clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>, + <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>, + <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>, + <&tegra_car TEGRA124_CLK_XUSB_SS>, + <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>, + <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>, + <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>, + <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>, + <&tegra_car TEGRA124_CLK_PLL_U_480M>, + <&tegra_car TEGRA124_CLK_CLK_M>, + <&tegra_car TEGRA124_CLK_PLL_E>; + clock-names = "xusb_host", "xusb_host_src", + "xusb_falcon_src", "xusb_ss", + "xusb_ss_div2", "xusb_ss_src", + "xusb_hs_src", "xusb_fs_src", + "pll_u_480m", "clk_m", "pll_e"; + resets = <&tegra_car 89>, <&tegra_car 156>, + <&tegra_car 143>; + reset-names = "xusb_host", "xusb_ss", "xusb_src"; + + nvidia,xusb-padctl = <&padctl>; + + status = "disabled"; + }; + + padctl: padctl@7009f000 { compatible = "nvidia,tegra124-xusb-padctl"; reg = <0x0 0x7009f000 0x0 0x1000>; resets = <&tegra_car 142>; reset-names = "padctl"; - #phy-cells = <1>; + pads { + usb2 { + status = "disabled"; + + lanes { + usb2-0 { + status = "disabled"; + #phy-cells = <0>; + }; + + usb2-1 { + status = "disabled"; + #phy-cells = <0>; + }; + + usb2-2 { + status = "disabled"; + #phy-cells = <0>; + }; + }; + }; + + ulpi { + status = "disabled"; + + lanes { + ulpi-0 { + status = "disabled"; + #phy-cells = <0>; + }; + }; + }; + + hsic { + status = "disabled"; + + lanes { + hsic-0 { + status = "disabled"; + #phy-cells = <0>; + }; + + hsic-1 { + status = "disabled"; + #phy-cells = <0>; + }; + }; + }; + + pcie { + status = "disabled"; + + lanes { + pcie-0 { + status = "disabled"; + #phy-cells = <0>; + }; + + pcie-1 { + status = "disabled"; + #phy-cells = <0>; + }; + + pcie-2 { + status = "disabled"; + #phy-cells = <0>; + }; + + pcie-3 { + status = "disabled"; + #phy-cells = <0>; + }; + + pcie-4 { + status = "disabled"; + #phy-cells = <0>; + }; + }; + }; + + sata { + status = "disabled"; + + lanes { + sata-0 { + status = "disabled"; + #phy-cells = <0>; + }; + }; + }; + }; + + ports { + usb2-0 { + status = "disabled"; + }; + + usb2-1 { + status = "disabled"; + }; + + usb2-2 { + status = "disabled"; + }; + + ulpi-0 { + status = "disabled"; + }; + + hsic-0 { + status = "disabled"; + }; + + hsic-1 { + status = "disabled"; + }; + + usb3-0 { + status = "disabled"; + }; + + usb3-1 { + status = "disabled"; + }; + }; }; - sdhci@0,700b0000 { + sdhci@700b0000 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0000 0x0 0x200>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_SDMMC1>; resets = <&tegra_car 14>; reset-names = "sdhci"; status = "disabled"; }; - sdhci@0,700b0200 { + sdhci@700b0200 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0200 0x0 0x200>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_SDMMC2>; resets = <&tegra_car 9>; reset-names = "sdhci"; status = "disabled"; }; - sdhci@0,700b0400 { + sdhci@700b0400 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0400 0x0 0x200>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_SDMMC3>; resets = <&tegra_car 69>; reset-names = "sdhci"; status = "disabled"; }; - sdhci@0,700b0600 { + sdhci@700b0600 { compatible = "nvidia,tegra124-sdhci"; reg = <0x0 0x700b0600 0x0 0x200>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_SDMMC4>; resets = <&tegra_car 15>; reset-names = "sdhci"; status = "disabled"; }; - soctherm: thermal-sensor@0,700e2000 { + cec@70015000 { + compatible = "nvidia,tegra124-cec"; + reg = <0x0 0x70015000 0x0 0x00001000>; + interrupts = ; + clocks = <&tegra_car TEGRA124_CLK_CEC>; + clock-names = "cec"; + status = "disabled"; + hdmi-phandle = <&hdmi>; + }; + + soctherm: thermal-sensor@700e2000 { compatible = "nvidia,tegra124-soctherm"; - reg = <0x0 0x700e2000 0x0 0x1000>; + reg = <0x0 0x700e2000 0x0 0x600 /* SOC_THERM reg_base */ + 0x0 0x60006000 0x0 0x400>; /* CAR reg_base */ + reg-names = "soctherm-reg", "car-reg"; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_TSENSOR>, <&tegra_car TEGRA124_CLK_SOC_THERM>; clock-names = "tsensor", "soctherm"; resets = <&tegra_car 78>; reset-names = "soctherm"; #thermal-sensor-cells = <1>; + + throttle-cfgs { + throttle_heavy: heavy { + nvidia,priority = <100>; + nvidia,cpu-throt-percent = <85>; + + #cooling-cells = <2>; + }; + }; }; - dfll: clock@0,70110000 { + dfll: clock@70110000 { compatible = "nvidia,tegra124-dfll"; reg = <0 0x70110000 0 0x100>, /* DFLL control */ <0 0x70110000 0 0x100>, /* I2C output control */ <0 0x70110100 0 0x100>, /* Integrated I2C controller */ <0 0x70110200 0 0x100>; /* Look-up table RAM */ interrupts = ; clocks = <&tegra_car TEGRA124_CLK_DFLL_SOC>, <&tegra_car TEGRA124_CLK_DFLL_REF>, <&tegra_car TEGRA124_CLK_I2C5>; clock-names = "soc", "ref", "i2c"; resets = <&tegra_car TEGRA124_RST_DFLL_DVCO>; reset-names = "dvco"; #clock-cells = <0>; clock-output-names = "dfllCPU_out"; nvidia,sample-rate = <12500>; nvidia,droop-ctrl = <0x00000f00>; nvidia,force-mode = <1>; nvidia,cf = <10>; nvidia,ci = <0>; nvidia,cg = <2>; status = "disabled"; }; - ahub@0,70300000 { + ahub@70300000 { compatible = "nvidia,tegra124-ahub"; reg = <0x0 0x70300000 0x0 0x200>, <0x0 0x70300800 0x0 0x800>, <0x0 0x70300200 0x0 0x600>; interrupts = ; clocks = <&tegra_car TEGRA124_CLK_D_AUDIO>, <&tegra_car TEGRA124_CLK_APBIF>; clock-names = "d_audio", "apbif"; resets = <&tegra_car 106>, /* d_audio */ <&tegra_car 107>, /* apbif */ <&tegra_car 30>, /* i2s0 */ <&tegra_car 11>, /* i2s1 */ <&tegra_car 18>, /* i2s2 */ <&tegra_car 101>, /* i2s3 */ <&tegra_car 102>, /* i2s4 */ <&tegra_car 108>, /* dam0 */ <&tegra_car 109>, /* dam1 */ <&tegra_car 110>, /* dam2 */ <&tegra_car 10>, /* spdif */ <&tegra_car 153>, /* amx */ <&tegra_car 185>, /* amx1 */ <&tegra_car 154>, /* adx */ <&tegra_car 180>, /* adx1 */ <&tegra_car 186>, /* afc0 */ <&tegra_car 187>, /* afc1 */ <&tegra_car 188>, /* afc2 */ <&tegra_car 189>, /* afc3 */ <&tegra_car 190>, /* afc4 */ <&tegra_car 191>; /* afc5 */ reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2", "i2s3", "i2s4", "dam0", "dam1", "dam2", "spdif", "amx", "amx1", "adx", "adx1", "afc0", "afc1", "afc2", "afc3", "afc4", "afc5"; dmas = <&apbdma 1>, <&apbdma 1>, <&apbdma 2>, <&apbdma 2>, <&apbdma 3>, <&apbdma 3>, <&apbdma 4>, <&apbdma 4>, <&apbdma 6>, <&apbdma 6>, <&apbdma 7>, <&apbdma 7>, <&apbdma 12>, <&apbdma 12>, <&apbdma 13>, <&apbdma 13>, <&apbdma 14>, <&apbdma 14>, <&apbdma 29>, <&apbdma 29>; dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3", "rx4", "tx4", "rx5", "tx5", "rx6", "tx6", "rx7", "tx7", "rx8", "tx8", "rx9", "tx9"; ranges; #address-cells = <2>; #size-cells = <2>; - tegra_i2s0: i2s@0,70301000 { + tegra_i2s0: i2s@70301000 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301000 0x0 0x100>; nvidia,ahub-cif-ids = <4 4>; clocks = <&tegra_car TEGRA124_CLK_I2S0>; resets = <&tegra_car 30>; reset-names = "i2s"; status = "disabled"; }; - tegra_i2s1: i2s@0,70301100 { + tegra_i2s1: i2s@70301100 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301100 0x0 0x100>; nvidia,ahub-cif-ids = <5 5>; clocks = <&tegra_car TEGRA124_CLK_I2S1>; resets = <&tegra_car 11>; reset-names = "i2s"; status = "disabled"; }; - tegra_i2s2: i2s@0,70301200 { + tegra_i2s2: i2s@70301200 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301200 0x0 0x100>; nvidia,ahub-cif-ids = <6 6>; clocks = <&tegra_car TEGRA124_CLK_I2S2>; resets = <&tegra_car 18>; reset-names = "i2s"; status = "disabled"; }; - tegra_i2s3: i2s@0,70301300 { + tegra_i2s3: i2s@70301300 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301300 0x0 0x100>; nvidia,ahub-cif-ids = <7 7>; clocks = <&tegra_car TEGRA124_CLK_I2S3>; resets = <&tegra_car 101>; reset-names = "i2s"; status = "disabled"; }; - tegra_i2s4: i2s@0,70301400 { + tegra_i2s4: i2s@70301400 { compatible = "nvidia,tegra124-i2s"; reg = <0x0 0x70301400 0x0 0x100>; nvidia,ahub-cif-ids = <8 8>; clocks = <&tegra_car TEGRA124_CLK_I2S4>; resets = <&tegra_car 102>; reset-names = "i2s"; status = "disabled"; }; }; - usb@0,7d000000 { + usb@7d000000 { compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d000000 0x0 0x4000>; interrupts = ; phy_type = "utmi"; clocks = <&tegra_car TEGRA124_CLK_USBD>; resets = <&tegra_car 22>; reset-names = "usb"; nvidia,phy = <&phy1>; status = "disabled"; }; - phy1: usb-phy@0,7d000000 { + phy1: usb-phy@7d000000 { compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d000000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; phy_type = "utmi"; clocks = <&tegra_car TEGRA124_CLK_USBD>, <&tegra_car TEGRA124_CLK_PLL_U>, <&tegra_car TEGRA124_CLK_USBD>; clock-names = "reg", "pll_u", "utmi-pads"; resets = <&tegra_car 22>, <&tegra_car 22>; reset-names = "usb", "utmi-pads"; nvidia,hssync-start-delay = <0>; nvidia,idle-wait-delay = <17>; nvidia,elastic-limit = <16>; nvidia,term-range-adj = <6>; nvidia,xcvr-setup = <9>; nvidia,xcvr-lsfslew = <0>; nvidia,xcvr-lsrslew = <3>; nvidia,hssquelch-level = <2>; nvidia,hsdiscon-level = <5>; nvidia,xcvr-hsslew = <12>; nvidia,has-utmi-pad-registers; status = "disabled"; }; - usb@0,7d004000 { + usb@7d004000 { compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d004000 0x0 0x4000>; interrupts = ; phy_type = "utmi"; clocks = <&tegra_car TEGRA124_CLK_USB2>; resets = <&tegra_car 58>; reset-names = "usb"; nvidia,phy = <&phy2>; status = "disabled"; }; - phy2: usb-phy@0,7d004000 { + phy2: usb-phy@7d004000 { compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d004000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; phy_type = "utmi"; clocks = <&tegra_car TEGRA124_CLK_USB2>, <&tegra_car TEGRA124_CLK_PLL_U>, <&tegra_car TEGRA124_CLK_USBD>; clock-names = "reg", "pll_u", "utmi-pads"; resets = <&tegra_car 58>, <&tegra_car 22>; reset-names = "usb", "utmi-pads"; nvidia,hssync-start-delay = <0>; nvidia,idle-wait-delay = <17>; nvidia,elastic-limit = <16>; nvidia,term-range-adj = <6>; nvidia,xcvr-setup = <9>; nvidia,xcvr-lsfslew = <0>; nvidia,xcvr-lsrslew = <3>; nvidia,hssquelch-level = <2>; nvidia,hsdiscon-level = <5>; nvidia,xcvr-hsslew = <12>; status = "disabled"; }; - usb@0,7d008000 { + usb@7d008000 { compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci"; reg = <0x0 0x7d008000 0x0 0x4000>; interrupts = ; phy_type = "utmi"; clocks = <&tegra_car TEGRA124_CLK_USB3>; resets = <&tegra_car 59>; reset-names = "usb"; nvidia,phy = <&phy3>; status = "disabled"; }; - phy3: usb-phy@0,7d008000 { + phy3: usb-phy@7d008000 { compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy"; reg = <0x0 0x7d008000 0x0 0x4000>, <0x0 0x7d000000 0x0 0x4000>; phy_type = "utmi"; clocks = <&tegra_car TEGRA124_CLK_USB3>, <&tegra_car TEGRA124_CLK_PLL_U>, <&tegra_car TEGRA124_CLK_USBD>; clock-names = "reg", "pll_u", "utmi-pads"; resets = <&tegra_car 59>, <&tegra_car 22>; reset-names = "usb", "utmi-pads"; nvidia,hssync-start-delay = <0>; nvidia,idle-wait-delay = <17>; nvidia,elastic-limit = <16>; nvidia,term-range-adj = <6>; nvidia,xcvr-setup = <9>; nvidia,xcvr-lsfslew = <0>; nvidia,xcvr-lsrslew = <3>; nvidia,hssquelch-level = <2>; nvidia,hsdiscon-level = <5>; nvidia,xcvr-hsslew = <12>; status = "disabled"; }; cpus { #address-cells = <1>; #size-cells = <0>; cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <0>; clocks = <&tegra_car TEGRA124_CLK_CCLK_G>, <&tegra_car TEGRA124_CLK_CCLK_LP>, <&tegra_car TEGRA124_CLK_PLL_X>, <&tegra_car TEGRA124_CLK_PLL_P>, <&dfll>; clock-names = "cpu_g", "cpu_lp", "pll_x", "pll_p", "dfll"; /* FIXME: what's the actual transition time? */ clock-latency = <300000>; }; cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <1>; }; cpu@2 { device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <2>; }; cpu@3 { device_type = "cpu"; compatible = "arm,cortex-a15"; reg = <3>; }; }; pmu { compatible = "arm,cortex-a15-pmu"; interrupts = , , , ; interrupt-affinity = <&{/cpus/cpu@0}>, <&{/cpus/cpu@1}>, <&{/cpus/cpu@2}>, <&{/cpus/cpu@3}>; }; thermal-zones { cpu { polling-delay-passive = <1000>; polling-delay = <1000>; thermal-sensors = <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>; + + trips { + cpu-shutdown-trip { + temperature = <103000>; + hysteresis = <0>; + type = "critical"; + }; + cpu_throttle_trip: throttle-trip { + temperature = <100000>; + hysteresis = <1000>; + type = "hot"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_throttle_trip>; + cooling-device = <&throttle_heavy 1 1>; + }; + }; }; mem { polling-delay-passive = <1000>; polling-delay = <1000>; thermal-sensors = <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>; + + trips { + mem-shutdown-trip { + temperature = <103000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + /* + * There are currently no cooling maps, + * because there are no cooling devices. + */ + }; }; gpu { polling-delay-passive = <1000>; polling-delay = <1000>; thermal-sensors = <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>; + + trips { + gpu-shutdown-trip { + temperature = <101000>; + hysteresis = <0>; + type = "critical"; + }; + gpu_throttle_trip: throttle-trip { + temperature = <99000>; + hysteresis = <1000>; + type = "hot"; + }; + }; + + cooling-maps { + map0 { + trip = <&gpu_throttle_trip>; + cooling-device = <&throttle_heavy 1 1>; + }; + }; }; pllx { polling-delay-passive = <1000>; polling-delay = <1000>; thermal-sensors = <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>; + + trips { + pllx-shutdown-trip { + temperature = <103000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + /* + * There are currently no cooling maps, + * because there are no cooling devices. + */ + }; }; }; timer { compatible = "arm,armv7-timer"; interrupts = , , , ; interrupt-parent = <&gic>; }; }; Index: stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car-common.h =================================================================== --- stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car-common.h (revision 332009) +++ stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car-common.h (revision 332010) @@ -1,345 +1,346 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This header provides constants for binding nvidia,tegra124-car or * nvidia,tegra132-car. * * The first 192 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB * registers. These IDs often match those in the CAR's RST_DEVICES registers, * but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In * this case, those clocks are assigned IDs above 185 in order to highlight * this issue. Implementations that interpret these clock IDs as bit values * within the CLK_OUT_ENB or RST_DEVICES registers should be careful to * explicitly handle these special cases. * * The balance of the clocks controlled by the CAR are assigned IDs of 185 and * above. */ #ifndef _DT_BINDINGS_CLOCK_TEGRA124_CAR_COMMON_H #define _DT_BINDINGS_CLOCK_TEGRA124_CAR_COMMON_H /* 0 */ /* 1 */ /* 2 */ #define TEGRA124_CLK_ISPB 3 #define TEGRA124_CLK_RTC 4 #define TEGRA124_CLK_TIMER 5 #define TEGRA124_CLK_UARTA 6 /* 7 (register bit affects uartb and vfir) */ /* 8 */ #define TEGRA124_CLK_SDMMC2 9 /* 10 (register bit affects spdif_in and spdif_out) */ #define TEGRA124_CLK_I2S1 11 #define TEGRA124_CLK_I2C1 12 /* 13 */ #define TEGRA124_CLK_SDMMC1 14 #define TEGRA124_CLK_SDMMC4 15 /* 16 */ #define TEGRA124_CLK_PWM 17 #define TEGRA124_CLK_I2S2 18 /* 20 (register bit affects vi and vi_sensor) */ /* 21 */ #define TEGRA124_CLK_USBD 22 #define TEGRA124_CLK_ISP 23 /* 26 */ /* 25 */ #define TEGRA124_CLK_DISP2 26 #define TEGRA124_CLK_DISP1 27 #define TEGRA124_CLK_HOST1X 28 #define TEGRA124_CLK_VCP 29 #define TEGRA124_CLK_I2S0 30 /* 31 */ #define TEGRA124_CLK_MC 32 /* 33 */ #define TEGRA124_CLK_APBDMA 34 /* 35 */ #define TEGRA124_CLK_KBC 36 /* 37 */ /* 38 */ /* 39 (register bit affects fuse and fuse_burn) */ #define TEGRA124_CLK_KFUSE 40 #define TEGRA124_CLK_SBC1 41 #define TEGRA124_CLK_NOR 42 /* 43 */ #define TEGRA124_CLK_SBC2 44 /* 45 */ #define TEGRA124_CLK_SBC3 46 #define TEGRA124_CLK_I2C5 47 #define TEGRA124_CLK_DSIA 48 /* 49 */ #define TEGRA124_CLK_MIPI 50 #define TEGRA124_CLK_HDMI 51 #define TEGRA124_CLK_CSI 52 /* 53 */ #define TEGRA124_CLK_I2C2 54 #define TEGRA124_CLK_UARTC 55 #define TEGRA124_CLK_MIPI_CAL 56 #define TEGRA124_CLK_EMC 57 #define TEGRA124_CLK_USB2 58 #define TEGRA124_CLK_USB3 59 /* 60 */ #define TEGRA124_CLK_VDE 61 #define TEGRA124_CLK_BSEA 62 #define TEGRA124_CLK_BSEV 63 /* 64 */ #define TEGRA124_CLK_UARTD 65 /* 66 */ #define TEGRA124_CLK_I2C3 67 #define TEGRA124_CLK_SBC4 68 #define TEGRA124_CLK_SDMMC3 69 #define TEGRA124_CLK_PCIE 70 #define TEGRA124_CLK_OWR 71 #define TEGRA124_CLK_AFI 72 #define TEGRA124_CLK_CSITE 73 /* 74 */ /* 75 */ #define TEGRA124_CLK_LA 76 #define TEGRA124_CLK_TRACE 77 #define TEGRA124_CLK_SOC_THERM 78 #define TEGRA124_CLK_DTV 79 /* 80 */ #define TEGRA124_CLK_I2CSLOW 81 #define TEGRA124_CLK_DSIB 82 #define TEGRA124_CLK_TSEC 83 /* 84 */ /* 85 */ /* 86 */ /* 87 */ /* 88 */ #define TEGRA124_CLK_XUSB_HOST 89 /* 90 */ #define TEGRA124_CLK_MSENC 91 #define TEGRA124_CLK_CSUS 92 /* 93 */ /* 94 */ /* 95 (bit affects xusb_dev and xusb_dev_src) */ /* 96 */ /* 97 */ /* 98 */ #define TEGRA124_CLK_MSELECT 99 #define TEGRA124_CLK_TSENSOR 100 #define TEGRA124_CLK_I2S3 101 #define TEGRA124_CLK_I2S4 102 #define TEGRA124_CLK_I2C4 103 #define TEGRA124_CLK_SBC5 104 #define TEGRA124_CLK_SBC6 105 #define TEGRA124_CLK_D_AUDIO 106 #define TEGRA124_CLK_APBIF 107 #define TEGRA124_CLK_DAM0 108 #define TEGRA124_CLK_DAM1 109 #define TEGRA124_CLK_DAM2 110 #define TEGRA124_CLK_HDA2CODEC_2X 111 /* 112 */ #define TEGRA124_CLK_AUDIO0_2X 113 #define TEGRA124_CLK_AUDIO1_2X 114 #define TEGRA124_CLK_AUDIO2_2X 115 #define TEGRA124_CLK_AUDIO3_2X 116 #define TEGRA124_CLK_AUDIO4_2X 117 #define TEGRA124_CLK_SPDIF_2X 118 #define TEGRA124_CLK_ACTMON 119 #define TEGRA124_CLK_EXTERN1 120 #define TEGRA124_CLK_EXTERN2 121 #define TEGRA124_CLK_EXTERN3 122 #define TEGRA124_CLK_SATA_OOB 123 #define TEGRA124_CLK_SATA 124 #define TEGRA124_CLK_HDA 125 /* 126 */ #define TEGRA124_CLK_SE 127 #define TEGRA124_CLK_HDA2HDMI 128 #define TEGRA124_CLK_SATA_COLD 129 /* 130 */ /* 131 */ /* 132 */ /* 133 */ /* 134 */ /* 135 */ -/* 136 */ +#define TEGRA124_CLK_CEC 136 /* 137 */ /* 138 */ /* 139 */ /* 140 */ /* 141 */ /* 142 */ /* 143 (bit affects xusb_falcon_src, xusb_fs_src, */ /* xusb_host_src and xusb_ss_src) */ #define TEGRA124_CLK_CILAB 144 #define TEGRA124_CLK_CILCD 145 #define TEGRA124_CLK_CILE 146 #define TEGRA124_CLK_DSIALP 147 #define TEGRA124_CLK_DSIBLP 148 #define TEGRA124_CLK_ENTROPY 149 #define TEGRA124_CLK_DDS 150 /* 151 */ #define TEGRA124_CLK_DP2 152 #define TEGRA124_CLK_AMX 153 #define TEGRA124_CLK_ADX 154 /* 155 (bit affects dfll_ref and dfll_soc) */ #define TEGRA124_CLK_XUSB_SS 156 /* 157 */ /* 158 */ /* 159 */ /* 160 */ /* 161 */ /* 162 */ /* 163 */ /* 164 */ /* 165 */ #define TEGRA124_CLK_I2C6 166 /* 167 */ /* 168 */ /* 169 */ /* 170 */ #define TEGRA124_CLK_VIM2_CLK 171 /* 172 */ /* 173 */ /* 174 */ /* 175 */ #define TEGRA124_CLK_HDMI_AUDIO 176 #define TEGRA124_CLK_CLK72MHZ 177 #define TEGRA124_CLK_VIC03 178 /* 179 */ #define TEGRA124_CLK_ADX1 180 #define TEGRA124_CLK_DPAUX 181 #define TEGRA124_CLK_SOR0 182 /* 183 */ #define TEGRA124_CLK_GPU 184 #define TEGRA124_CLK_AMX1 185 /* 186 */ /* 187 */ /* 188 */ /* 189 */ /* 190 */ /* 191 */ #define TEGRA124_CLK_UARTB 192 #define TEGRA124_CLK_VFIR 193 #define TEGRA124_CLK_SPDIF_IN 194 #define TEGRA124_CLK_SPDIF_OUT 195 #define TEGRA124_CLK_VI 196 #define TEGRA124_CLK_VI_SENSOR 197 #define TEGRA124_CLK_FUSE 198 #define TEGRA124_CLK_FUSE_BURN 199 #define TEGRA124_CLK_CLK_32K 200 #define TEGRA124_CLK_CLK_M 201 #define TEGRA124_CLK_CLK_M_DIV2 202 #define TEGRA124_CLK_CLK_M_DIV4 203 #define TEGRA124_CLK_PLL_REF 204 #define TEGRA124_CLK_PLL_C 205 #define TEGRA124_CLK_PLL_C_OUT1 206 #define TEGRA124_CLK_PLL_C2 207 #define TEGRA124_CLK_PLL_C3 208 #define TEGRA124_CLK_PLL_M 209 #define TEGRA124_CLK_PLL_M_OUT1 210 #define TEGRA124_CLK_PLL_P 211 #define TEGRA124_CLK_PLL_P_OUT1 212 #define TEGRA124_CLK_PLL_P_OUT2 213 #define TEGRA124_CLK_PLL_P_OUT3 214 #define TEGRA124_CLK_PLL_P_OUT4 215 #define TEGRA124_CLK_PLL_A 216 #define TEGRA124_CLK_PLL_A_OUT0 217 #define TEGRA124_CLK_PLL_D 218 #define TEGRA124_CLK_PLL_D_OUT0 219 #define TEGRA124_CLK_PLL_D2 220 #define TEGRA124_CLK_PLL_D2_OUT0 221 #define TEGRA124_CLK_PLL_U 222 #define TEGRA124_CLK_PLL_U_480M 223 #define TEGRA124_CLK_PLL_U_60M 224 #define TEGRA124_CLK_PLL_U_48M 225 #define TEGRA124_CLK_PLL_U_12M 226 /* 227 */ /* 228 */ #define TEGRA124_CLK_PLL_RE_VCO 229 #define TEGRA124_CLK_PLL_RE_OUT 230 #define TEGRA124_CLK_PLL_E 231 #define TEGRA124_CLK_SPDIF_IN_SYNC 232 #define TEGRA124_CLK_I2S0_SYNC 233 #define TEGRA124_CLK_I2S1_SYNC 234 #define TEGRA124_CLK_I2S2_SYNC 235 #define TEGRA124_CLK_I2S3_SYNC 236 #define TEGRA124_CLK_I2S4_SYNC 237 #define TEGRA124_CLK_VIMCLK_SYNC 238 #define TEGRA124_CLK_AUDIO0 239 #define TEGRA124_CLK_AUDIO1 240 #define TEGRA124_CLK_AUDIO2 241 #define TEGRA124_CLK_AUDIO3 242 #define TEGRA124_CLK_AUDIO4 243 #define TEGRA124_CLK_SPDIF 244 #define TEGRA124_CLK_CLK_OUT_1 245 #define TEGRA124_CLK_CLK_OUT_2 246 #define TEGRA124_CLK_CLK_OUT_3 247 #define TEGRA124_CLK_BLINK 248 /* 249 */ /* 250 */ /* 251 */ #define TEGRA124_CLK_XUSB_HOST_SRC 252 #define TEGRA124_CLK_XUSB_FALCON_SRC 253 #define TEGRA124_CLK_XUSB_FS_SRC 254 #define TEGRA124_CLK_XUSB_SS_SRC 255 #define TEGRA124_CLK_XUSB_DEV_SRC 256 #define TEGRA124_CLK_XUSB_DEV 257 #define TEGRA124_CLK_XUSB_HS_SRC 258 #define TEGRA124_CLK_SCLK 259 #define TEGRA124_CLK_HCLK 260 #define TEGRA124_CLK_PCLK 261 /* 262 */ /* 263 */ #define TEGRA124_CLK_DFLL_REF 264 #define TEGRA124_CLK_DFLL_SOC 265 #define TEGRA124_CLK_VI_SENSOR2 266 #define TEGRA124_CLK_PLL_P_OUT5 267 #define TEGRA124_CLK_CML0 268 #define TEGRA124_CLK_CML1 269 #define TEGRA124_CLK_PLL_C4 270 #define TEGRA124_CLK_PLL_DP 271 #define TEGRA124_CLK_PLL_E_MUX 272 #define TEGRA124_CLK_PLL_D_DSI_OUT 273 /* 274 */ /* 275 */ /* 276 */ /* 277 */ /* 278 */ /* 279 */ /* 280 */ /* 281 */ /* 282 */ /* 283 */ /* 284 */ /* 285 */ /* 286 */ /* 287 */ /* 288 */ /* 289 */ /* 290 */ /* 291 */ /* 292 */ /* 293 */ /* 294 */ /* 295 */ /* 296 */ /* 297 */ /* 298 */ /* 299 */ #define TEGRA124_CLK_AUDIO0_MUX 300 #define TEGRA124_CLK_AUDIO1_MUX 301 #define TEGRA124_CLK_AUDIO2_MUX 302 #define TEGRA124_CLK_AUDIO3_MUX 303 #define TEGRA124_CLK_AUDIO4_MUX 304 #define TEGRA124_CLK_SPDIF_MUX 305 #define TEGRA124_CLK_CLK_OUT_1_MUX 306 #define TEGRA124_CLK_CLK_OUT_2_MUX 307 #define TEGRA124_CLK_CLK_OUT_3_MUX 308 /* 309 */ /* 310 */ #define TEGRA124_CLK_SOR0_LVDS 311 #define TEGRA124_CLK_XUSB_SS_DIV2 312 #define TEGRA124_CLK_PLL_M_UD 313 #define TEGRA124_CLK_PLL_C_UD 314 #endif /* _DT_BINDINGS_CLOCK_TEGRA124_CAR_COMMON_H */ Index: stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car.h =================================================================== --- stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car.h (revision 332009) +++ stable/11/sys/gnu/dts/include/dt-bindings/clock/tegra124-car.h (revision 332010) @@ -1,19 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This header provides Tegra124-specific constants for binding * nvidia,tegra124-car. */ #include #ifndef _DT_BINDINGS_CLOCK_TEGRA124_CAR_H #define _DT_BINDINGS_CLOCK_TEGRA124_CAR_H #define TEGRA124_CLK_PLL_X 227 #define TEGRA124_CLK_PLL_X_OUT0 228 #define TEGRA124_CLK_CCLK_G 262 #define TEGRA124_CLK_CCLK_LP 263 #define TEGRA124_CLK_CLK_MAX 315 #endif /* _DT_BINDINGS_CLOCK_TEGRA124_CAR_H */ Index: stable/11/sys/gnu/dts/include/dt-bindings/gpio/tegra-gpio.h =================================================================== --- stable/11/sys/gnu/dts/include/dt-bindings/gpio/tegra-gpio.h (revision 332009) +++ stable/11/sys/gnu/dts/include/dt-bindings/gpio/tegra-gpio.h (revision 332010) @@ -1,51 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This header provides constants for binding nvidia,tegra*-gpio. * * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below * provide names for this. * * The second cell contains standard flag values specified in gpio.h. */ #ifndef _DT_BINDINGS_GPIO_TEGRA_GPIO_H #define _DT_BINDINGS_GPIO_TEGRA_GPIO_H #include -#define TEGRA_GPIO_BANK_ID_A 0 -#define TEGRA_GPIO_BANK_ID_B 1 -#define TEGRA_GPIO_BANK_ID_C 2 -#define TEGRA_GPIO_BANK_ID_D 3 -#define TEGRA_GPIO_BANK_ID_E 4 -#define TEGRA_GPIO_BANK_ID_F 5 -#define TEGRA_GPIO_BANK_ID_G 6 -#define TEGRA_GPIO_BANK_ID_H 7 -#define TEGRA_GPIO_BANK_ID_I 8 -#define TEGRA_GPIO_BANK_ID_J 9 -#define TEGRA_GPIO_BANK_ID_K 10 -#define TEGRA_GPIO_BANK_ID_L 11 -#define TEGRA_GPIO_BANK_ID_M 12 -#define TEGRA_GPIO_BANK_ID_N 13 -#define TEGRA_GPIO_BANK_ID_O 14 -#define TEGRA_GPIO_BANK_ID_P 15 -#define TEGRA_GPIO_BANK_ID_Q 16 -#define TEGRA_GPIO_BANK_ID_R 17 -#define TEGRA_GPIO_BANK_ID_S 18 -#define TEGRA_GPIO_BANK_ID_T 19 -#define TEGRA_GPIO_BANK_ID_U 20 -#define TEGRA_GPIO_BANK_ID_V 21 -#define TEGRA_GPIO_BANK_ID_W 22 -#define TEGRA_GPIO_BANK_ID_X 23 -#define TEGRA_GPIO_BANK_ID_Y 24 -#define TEGRA_GPIO_BANK_ID_Z 25 -#define TEGRA_GPIO_BANK_ID_AA 26 -#define TEGRA_GPIO_BANK_ID_BB 27 -#define TEGRA_GPIO_BANK_ID_CC 28 -#define TEGRA_GPIO_BANK_ID_DD 29 -#define TEGRA_GPIO_BANK_ID_EE 30 -#define TEGRA_GPIO_BANK_ID_FF 31 +#define TEGRA_GPIO_PORT_A 0 +#define TEGRA_GPIO_PORT_B 1 +#define TEGRA_GPIO_PORT_C 2 +#define TEGRA_GPIO_PORT_D 3 +#define TEGRA_GPIO_PORT_E 4 +#define TEGRA_GPIO_PORT_F 5 +#define TEGRA_GPIO_PORT_G 6 +#define TEGRA_GPIO_PORT_H 7 +#define TEGRA_GPIO_PORT_I 8 +#define TEGRA_GPIO_PORT_J 9 +#define TEGRA_GPIO_PORT_K 10 +#define TEGRA_GPIO_PORT_L 11 +#define TEGRA_GPIO_PORT_M 12 +#define TEGRA_GPIO_PORT_N 13 +#define TEGRA_GPIO_PORT_O 14 +#define TEGRA_GPIO_PORT_P 15 +#define TEGRA_GPIO_PORT_Q 16 +#define TEGRA_GPIO_PORT_R 17 +#define TEGRA_GPIO_PORT_S 18 +#define TEGRA_GPIO_PORT_T 19 +#define TEGRA_GPIO_PORT_U 20 +#define TEGRA_GPIO_PORT_V 21 +#define TEGRA_GPIO_PORT_W 22 +#define TEGRA_GPIO_PORT_X 23 +#define TEGRA_GPIO_PORT_Y 24 +#define TEGRA_GPIO_PORT_Z 25 +#define TEGRA_GPIO_PORT_AA 26 +#define TEGRA_GPIO_PORT_BB 27 +#define TEGRA_GPIO_PORT_CC 28 +#define TEGRA_GPIO_PORT_DD 29 +#define TEGRA_GPIO_PORT_EE 30 +#define TEGRA_GPIO_PORT_FF 31 -#define TEGRA_GPIO(bank, offset) \ - ((TEGRA_GPIO_BANK_ID_##bank * 8) + offset) +#define TEGRA_GPIO(port, offset) \ + ((TEGRA_GPIO_PORT_##port * 8) + offset) #endif Index: stable/11/sys/gnu/dts/include/dt-bindings/memory/tegra124-mc.h =================================================================== --- stable/11/sys/gnu/dts/include/dt-bindings/memory/tegra124-mc.h (revision 332009) +++ stable/11/sys/gnu/dts/include/dt-bindings/memory/tegra124-mc.h (revision 332010) @@ -1,31 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef DT_BINDINGS_MEMORY_TEGRA124_MC_H #define DT_BINDINGS_MEMORY_TEGRA124_MC_H #define TEGRA_SWGROUP_PTC 0 #define TEGRA_SWGROUP_DC 1 #define TEGRA_SWGROUP_DCB 2 #define TEGRA_SWGROUP_AFI 3 #define TEGRA_SWGROUP_AVPC 4 #define TEGRA_SWGROUP_HDA 5 #define TEGRA_SWGROUP_HC 6 #define TEGRA_SWGROUP_MSENC 7 #define TEGRA_SWGROUP_PPCS 8 #define TEGRA_SWGROUP_SATA 9 #define TEGRA_SWGROUP_VDE 10 #define TEGRA_SWGROUP_MPCORELP 11 #define TEGRA_SWGROUP_MPCORE 12 #define TEGRA_SWGROUP_ISP2 13 #define TEGRA_SWGROUP_XUSB_HOST 14 #define TEGRA_SWGROUP_XUSB_DEV 15 #define TEGRA_SWGROUP_ISP2B 16 #define TEGRA_SWGROUP_TSEC 17 #define TEGRA_SWGROUP_A9AVP 18 #define TEGRA_SWGROUP_GPU 19 #define TEGRA_SWGROUP_SDMMC1A 20 #define TEGRA_SWGROUP_SDMMC2A 21 #define TEGRA_SWGROUP_SDMMC3A 22 #define TEGRA_SWGROUP_SDMMC4A 23 #define TEGRA_SWGROUP_VIC 24 #define TEGRA_SWGROUP_VI 25 #endif Index: stable/11/sys/gnu/dts/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h =================================================================== --- stable/11/sys/gnu/dts/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h (revision 332009) +++ stable/11/sys/gnu/dts/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h (revision 332010) @@ -1,7 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H #define _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H 1 #define TEGRA_XUSB_PADCTL_PCIE 0 #define TEGRA_XUSB_PADCTL_SATA 1 #endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */ Index: stable/11/sys/gnu/dts/include/dt-bindings/reset/tegra124-car.h =================================================================== --- stable/11/sys/gnu/dts/include/dt-bindings/reset/tegra124-car.h (revision 332009) +++ stable/11/sys/gnu/dts/include/dt-bindings/reset/tegra124-car.h (revision 332010) @@ -1,12 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This header provides Tegra124-specific constants for binding * nvidia,tegra124-car. */ #ifndef _DT_BINDINGS_RESET_TEGRA124_CAR_H #define _DT_BINDINGS_RESET_TEGRA124_CAR_H #define TEGRA124_RESET(x) (6 * 32 + (x)) #define TEGRA124_RST_DFLL_DVCO TEGRA124_RESET(0) #endif /* _DT_BINDINGS_RESET_TEGRA124_CAR_H */ Property changes on: stable/11/sys/gnu/dts/include/dt-bindings/reset/tegra124-car.h ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: stable/11/sys/gnu/dts/include/dt-bindings/thermal/tegra124-soctherm.h =================================================================== --- stable/11/sys/gnu/dts/include/dt-bindings/thermal/tegra124-soctherm.h (revision 332009) +++ stable/11/sys/gnu/dts/include/dt-bindings/thermal/tegra124-soctherm.h (revision 332010) @@ -1,13 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This header provides constants for binding nvidia,tegra124-soctherm. */ #ifndef _DT_BINDINGS_THERMAL_TEGRA124_SOCTHERM_H #define _DT_BINDINGS_THERMAL_TEGRA124_SOCTHERM_H #define TEGRA124_SOCTHERM_SENSOR_CPU 0 #define TEGRA124_SOCTHERM_SENSOR_MEM 1 #define TEGRA124_SOCTHERM_SENSOR_GPU 2 #define TEGRA124_SOCTHERM_SENSOR_PLLX 3 +#define TEGRA124_SOCTHERM_SENSOR_NUM 4 + +#define TEGRA_SOCTHERM_THROT_LEVEL_LOW 0 +#define TEGRA_SOCTHERM_THROT_LEVEL_MED 1 +#define TEGRA_SOCTHERM_THROT_LEVEL_HIGH 2 +#define TEGRA_SOCTHERM_THROT_LEVEL_NONE -1 #endif Index: stable/11 =================================================================== --- stable/11 (revision 332009) +++ stable/11 (revision 332010) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r306327-306328,308390-308391,310600,314703