From 2f3ec3402714d2ad20475b016487c7559ccba383 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 7 Feb 2013 07:16:24 +0000 Subject: [PATCH 01/39] tegra: usb: set USB_PORTS_MAX to correct value Both Tegra20 and Tegra30 have a max of 3 USB controllers. Signed-off-by: Lucas Stach Acked-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra20/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/armv7/tegra20/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c index 1bccf2b0b2..f151fb2c3b 100644 --- a/arch/arm/cpu/armv7/tegra20/usb.c +++ b/arch/arm/cpu/armv7/tegra20/usb.c @@ -44,7 +44,7 @@ #endif enum { - USB_PORTS_MAX = 4, /* Maximum ports we allow */ + USB_PORTS_MAX = 3, /* Maximum ports we allow */ }; /* Parameters we need for USB */ From b0bbab8a149ad4c3f764fa7ecff79788769cab99 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 7 Feb 2013 07:16:25 +0000 Subject: [PATCH 02/39] tegra: usb: make controller init functions more self contained There is no need to pass around all those parameters. The init functions are able to easily extract all the needed setup info on their own. This allows to move out the controller init into ehci_hcd_init later on, without having to save away global state for later use and thus bloating the file global state. Signed-off-by: Lucas Stach Acked-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra20/usb.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm/cpu/armv7/tegra20/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c index f151fb2c3b..07c1adefe3 100644 --- a/arch/arm/cpu/armv7/tegra20/usb.c +++ b/arch/arm/cpu/armv7/tegra20/usb.c @@ -198,11 +198,12 @@ void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) } /* set up the UTMI USB controller with the parameters provided */ -static int init_utmi_usb_controller(struct fdt_usb *config, - struct usb_ctlr *usbctlr, const u32 timing[]) +static int init_utmi_usb_controller(struct fdt_usb *config) { u32 val; int loop_count; + const unsigned *timing; + struct usb_ctlr *usbctlr = config->reg; clock_enable(config->periph_id); @@ -229,6 +230,8 @@ static int init_utmi_usb_controller(struct fdt_usb *config, * PLL Delay CONFIGURATION settings. The following parameters control * the bring up of the plls. */ + timing = usb_pll[clock_get_osc_freq()]; + val = readl(&usbctlr->utmip_misc_cfg1); clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT); @@ -331,12 +334,12 @@ static int init_utmi_usb_controller(struct fdt_usb *config, #endif /* set up the ULPI USB controller with the parameters provided */ -static int init_ulpi_usb_controller(struct fdt_usb *config, - struct usb_ctlr *usbctlr) +static int init_ulpi_usb_controller(struct fdt_usb *config) { u32 val; int loop_count; struct ulpi_viewport ulpi_vp; + struct usb_ctlr *usbctlr = config->reg; /* set up ULPI reference clock on pllp_out4 */ clock_enable(PERIPH_ID_DEV2_OUT); @@ -408,8 +411,7 @@ static int init_ulpi_usb_controller(struct fdt_usb *config, return 0; } #else -static int init_ulpi_usb_controller(struct fdt_usb *config, - struct usb_ctlr *usbctlr) +static int init_ulpi_usb_controller(struct fdt_usb *config) { printf("No code to set up ULPI controller, please enable" "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT"); @@ -430,22 +432,20 @@ static void config_clock(const u32 timing[]) * @param config USB port configuration * @return 0 if ok, -1 if error (too many ports) */ -static int add_port(struct fdt_usb *config, const u32 timing[]) +static int add_port(struct fdt_usb *config) { - struct usb_ctlr *usbctlr = config->reg; - if (port_count == USB_PORTS_MAX) { printf("tegrausb: Cannot register more than %d ports\n", USB_PORTS_MAX); return -1; } - if (config->utmi && init_utmi_usb_controller(config, usbctlr, timing)) { + if (config->utmi && init_utmi_usb_controller(config)) { printf("tegrausb: Cannot init port\n"); return -1; } - if (config->ulpi && init_ulpi_usb_controller(config, usbctlr)) { + if (config->ulpi && init_ulpi_usb_controller(config)) { printf("tegrausb: Cannot init port\n"); return -1; } @@ -558,7 +558,7 @@ int board_usb_init(const void *blob) return -1; } - if (add_port(&config, usb_pll[freq])) + if (add_port(&config)) return -1; set_host_mode(&config); } From a4bdcc38c94f5d693b3ad65a70fd1aeac9436d64 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 7 Feb 2013 07:16:26 +0000 Subject: [PATCH 03/39] tegra: usb: remove unneeded function parameter Just a dead parameter, never actually used. Signed-off-by: Lucas Stach Acked-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra20/usb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/cpu/armv7/tegra20/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c index 07c1adefe3..2007483c9b 100644 --- a/arch/arm/cpu/armv7/tegra20/usb.c +++ b/arch/arm/cpu/armv7/tegra20/usb.c @@ -486,8 +486,7 @@ int tegrausb_stop_port(int portnum) return 0; } -int fdt_decode_usb(const void *blob, int node, unsigned osc_frequency_mhz, - struct fdt_usb *config) +int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) { const char *phy, *mode; @@ -535,7 +534,6 @@ int fdt_decode_usb(const void *blob, int node, unsigned osc_frequency_mhz, int board_usb_init(const void *blob) { struct fdt_usb config; - unsigned osc_freq = clock_get_rate(CLOCK_ID_OSC); enum clock_osc_freq freq; int node_list[USB_PORTS_MAX]; int node, count, i; @@ -552,7 +550,7 @@ int board_usb_init(const void *blob) node = node_list[i]; if (!node) continue; - if (fdt_decode_usb(blob, node, osc_freq, &config)) { + if (fdt_decode_usb(blob, node, &config)) { debug("Cannot decode USB node %s\n", fdt_get_name(blob, node, NULL)); return -1; From fdb4b9a71c93d5bd9e04df52be4587516ade6fb1 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 7 Feb 2013 07:16:27 +0000 Subject: [PATCH 04/39] tegra: usb: move controller init into start_port There is no need to init a USB controller before the upper layers indicate that they are actually going to use it. board_usb_init now only parses the device tree and sets up the common pll. Signed-off-by: Lucas Stach Acked-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra20/usb.c | 69 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/arch/arm/cpu/armv7/tegra20/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c index 2007483c9b..e4165e04a5 100644 --- a/arch/arm/cpu/armv7/tegra20/usb.c +++ b/arch/arm/cpu/armv7/tegra20/usb.c @@ -79,6 +79,7 @@ struct fdt_usb { unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ unsigned enabled:1; /* 1 to enable, 0 to disable */ unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ + unsigned initialized:1; /* has this port already been initialized? */ enum dr_mode dr_mode; /* dual role mode */ enum periph_id periph_id;/* peripheral id */ struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ @@ -426,44 +427,36 @@ static void config_clock(const u32 timing[]) timing[PARAM_CPCON], timing[PARAM_LFCON]); } -/** - * Add a new USB port to the list of available ports. - * - * @param config USB port configuration - * @return 0 if ok, -1 if error (too many ports) - */ -static int add_port(struct fdt_usb *config) -{ - if (port_count == USB_PORTS_MAX) { - printf("tegrausb: Cannot register more than %d ports\n", - USB_PORTS_MAX); - return -1; - } - - if (config->utmi && init_utmi_usb_controller(config)) { - printf("tegrausb: Cannot init port\n"); - return -1; - } - - if (config->ulpi && init_ulpi_usb_controller(config)) { - printf("tegrausb: Cannot init port\n"); - return -1; - } - - port[port_count++] = *config; - - return 0; -} - int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor) { + struct fdt_usb *config; struct usb_ctlr *usbctlr; if (portnum >= port_count) return -1; - set_host_mode(&port[portnum]); - usbctlr = port[portnum].reg; + config = &port[portnum]; + + /* skip init, if the port is already initialized */ + if (config->initialized) + goto success; + + if (config->utmi && init_utmi_usb_controller(config)) { + printf("tegrausb: Cannot init port %d\n", portnum); + return -1; + } + + if (config->ulpi && init_ulpi_usb_controller(config)) { + printf("tegrausb: Cannot init port %d\n", portnum); + return -1; + } + + set_host_mode(config); + + config->initialized = 1; + +success: + usbctlr = config->reg; *hccr = (u32)&usbctlr->cap_length; *hcor = (u32)&usbctlr->usb_cmd; return 0; @@ -483,6 +476,8 @@ int tegrausb_stop_port(int portnum) writel(2, &usbctlr->usb_cmd); udelay(1000); + port[portnum].initialized = 0; + return 0; } @@ -546,6 +541,12 @@ int board_usb_init(const void *blob) count = fdtdec_find_aliases_for_id(blob, "usb", COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX); for (i = 0; i < count; i++) { + if (port_count == USB_PORTS_MAX) { + printf("tegrausb: Cannot register more than %d ports\n", + USB_PORTS_MAX); + return -1; + } + debug("USB %d: ", i); node = node_list[i]; if (!node) @@ -555,10 +556,10 @@ int board_usb_init(const void *blob) fdt_get_name(blob, node, NULL)); return -1; } + config.initialized = 0; - if (add_port(&config)) - return -1; - set_host_mode(&config); + /* add new USB port to the list of available ports */ + port[port_count++] = config; } return 0; From a63eb6bbcc73c6bde716b23383139b8079f02144 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 7 Feb 2013 07:16:28 +0000 Subject: [PATCH 05/39] tegra: usb: various small cleanups Remove unneeded headers, function prototype and stale comment, that doesn't match the actual codebase anymore. Signed-off-by: Lucas Stach Acked-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra20/usb.c | 13 +------------ arch/arm/include/asm/arch-tegra20/usb.h | 3 --- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/arch/arm/cpu/armv7/tegra20/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c index e4165e04a5..3fdd5df066 100644 --- a/arch/arm/cpu/armv7/tegra20/usb.c +++ b/arch/arm/cpu/armv7/tegra20/usb.c @@ -25,21 +25,15 @@ #include #include #include -#include -#include -#include #include #include -#include -#include -#include #include #include #ifdef CONFIG_USB_ULPI #ifndef CONFIG_USB_ULPI_VIEWPORT #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ - define CONFIG_USB_ULPI_VIEWPORT" + define CONFIG_USB_ULPI_VIEWPORT" #endif #endif @@ -191,11 +185,6 @@ void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) /* Enable the UTMIP PHY */ if (config->utmi) setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); - - /* - * TODO: where do we take the USB1 out of reset? The old code would - * take USB3 out of reset, but not USB1. This code doesn't do either. - */ } /* set up the UTMI USB controller with the parameters provided */ diff --git a/arch/arm/include/asm/arch-tegra20/usb.h b/arch/arm/include/asm/arch-tegra20/usb.h index fdbd127e6c..b18c85080b 100644 --- a/arch/arm/include/asm/arch-tegra20/usb.h +++ b/arch/arm/include/asm/arch-tegra20/usb.h @@ -243,9 +243,6 @@ struct usb_ctlr { #define VBUS_VLD_STS (1 << 26) -/* Change the USB host port into host mode */ -void usb_set_host_mode(void); - /* Setup USB on the board */ int board_usb_init(const void *blob); From 7ae18f3725fe3e2033888cf431f71ac08aaa8e1c Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 7 Feb 2013 07:16:29 +0000 Subject: [PATCH 06/39] tegra: usb: move implementation into right directory This moves the Tegra USB implementation into the drivers/usb/host directory. Note that this merges the old /arch/arm/cpu/armv7/tegra20/usb.c file into ehci-tegra.c. No code changes, just moving stuff around. v2: While at it also move some defines and the usb.h header file to make usb driver usable for Tegra30. NOTE: A lot more work is required to properly init the PHYs and PLL_U on Tegra30, this is just to make porting easier and it does no harm here. Signed-off-by: Lucas Stach Acked-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/cpu/armv7/tegra20/Makefile | 1 - arch/arm/cpu/armv7/tegra20/usb.c | 555 ------------------ .../asm/{arch-tegra20 => arch-tegra}/usb.h | 0 arch/arm/include/asm/arch-tegra20/tegra.h | 1 - arch/arm/include/asm/arch-tegra30/tegra.h | 2 + board/nvidia/common/board.c | 2 +- drivers/usb/host/ehci-tegra.c | 535 ++++++++++++++++- 7 files changed, 536 insertions(+), 560 deletions(-) delete mode 100644 arch/arm/cpu/armv7/tegra20/usb.c rename arch/arm/include/asm/{arch-tegra20 => arch-tegra}/usb.h (100%) diff --git a/arch/arm/cpu/armv7/tegra20/Makefile b/arch/arm/cpu/armv7/tegra20/Makefile index 54ed8c48b4..c8a8504e16 100644 --- a/arch/arm/cpu/armv7/tegra20/Makefile +++ b/arch/arm/cpu/armv7/tegra20/Makefile @@ -27,7 +27,6 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o -COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o COBJS-$(CONFIG_PWM_TEGRA) += pwm.o COBJS-$(CONFIG_VIDEO_TEGRA) += display.o diff --git a/arch/arm/cpu/armv7/tegra20/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c deleted file mode 100644 index 3fdd5df066..0000000000 --- a/arch/arm/cpu/armv7/tegra20/usb.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2010,2011 NVIDIA Corporation - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_USB_ULPI - #ifndef CONFIG_USB_ULPI_VIEWPORT - #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ - define CONFIG_USB_ULPI_VIEWPORT" - #endif -#endif - -enum { - USB_PORTS_MAX = 3, /* Maximum ports we allow */ -}; - -/* Parameters we need for USB */ -enum { - PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ - PARAM_DIVM, /* PLL INPUT DIVIDER */ - PARAM_DIVP, /* POST DIVIDER (2^N) */ - PARAM_CPCON, /* BASE PLLC CHARGE Pump setup ctrl */ - PARAM_LFCON, /* BASE PLLC LOOP FILter setup ctrl */ - PARAM_ENABLE_DELAY_COUNT, /* PLL-U Enable Delay Count */ - PARAM_STABLE_COUNT, /* PLL-U STABLE count */ - PARAM_ACTIVE_DELAY_COUNT, /* PLL-U Active delay count */ - PARAM_XTAL_FREQ_COUNT, /* PLL-U XTAL frequency count */ - PARAM_DEBOUNCE_A_TIME, /* 10MS DELAY for BIAS_DEBOUNCE_A */ - PARAM_BIAS_TIME, /* 20US DELAY AFter bias cell op */ - - PARAM_COUNT -}; - -/* Possible port types (dual role mode) */ -enum dr_mode { - DR_MODE_NONE = 0, - DR_MODE_HOST, /* supports host operation */ - DR_MODE_DEVICE, /* supports device operation */ - DR_MODE_OTG, /* supports both */ -}; - -/* Information about a USB port */ -struct fdt_usb { - struct usb_ctlr *reg; /* address of registers in physical memory */ - unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ - unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ - unsigned enabled:1; /* 1 to enable, 0 to disable */ - unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ - unsigned initialized:1; /* has this port already been initialized? */ - enum dr_mode dr_mode; /* dual role mode */ - enum periph_id periph_id;/* peripheral id */ - struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ - struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */ -}; - -static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ -static unsigned port_count; /* Number of available ports */ - -/* - * This table has USB timing parameters for each Oscillator frequency we - * support. There are four sets of values: - * - * 1. PLLU configuration information (reference clock is osc/clk_m and - * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). - * - * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz - * ---------------------------------------------------------------------- - * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) - * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) - * Filter frequency (MHz) 1 4.8 6 2 - * CPCON 1100b 0011b 1100b 1100b - * LFCON0 0 0 0 0 - * - * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: - * - * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz - * --------------------------------------------------------------------------- - * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) - * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) - * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) - * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) - * - * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and - * SessEnd. Each of these signals have their own debouncer and for each of - * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or - * BIAS_DEBOUNCE_B). - * - * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: - * 0xffff -> No debouncing at all - * ms = *1000 / (1/19.2MHz) / 4 - * - * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: - * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 - * - * We need to use only DebounceA for BOOTROM. We don't need the DebounceB - * values, so we can keep those to default. - * - * 4. The 20 microsecond delay after bias cell operation. - */ -static const unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { - /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ - { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, - { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, - { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, - { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } -}; - -/* UTMIP Idle Wait Delay */ -static const u8 utmip_idle_wait_delay = 17; - -/* UTMIP Elastic limit */ -static const u8 utmip_elastic_limit = 16; - -/* UTMIP High Speed Sync Start Delay */ -static const u8 utmip_hs_sync_start_delay = 9; - -/* Put the port into host mode */ -static void set_host_mode(struct fdt_usb *config) -{ - /* - * If we are an OTG port, check if remote host is driving VBus and - * bail out in this case. - */ - if (config->dr_mode == DR_MODE_OTG && - (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) - return; - - /* - * If not driving, we set the GPIO to enable VBUS. We assume - * that the pinmux is set up correctly for this. - */ - if (fdt_gpio_isvalid(&config->vbus_gpio)) { - fdtdec_setup_gpio(&config->vbus_gpio); - gpio_direction_output(config->vbus_gpio.gpio, - (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? - 0 : 1); - debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio, - (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? - "low" : "high"); - } -} - -void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) -{ - /* Reset the USB controller with 2us delay */ - reset_periph(config->periph_id, 2); - - /* - * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under - * base address - */ - if (config->has_legacy_mode) - setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE); - - /* Put UTMIP1/3 in reset */ - setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); - - /* Enable the UTMIP PHY */ - if (config->utmi) - setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); -} - -/* set up the UTMI USB controller with the parameters provided */ -static int init_utmi_usb_controller(struct fdt_usb *config) -{ - u32 val; - int loop_count; - const unsigned *timing; - struct usb_ctlr *usbctlr = config->reg; - - clock_enable(config->periph_id); - - /* Reset the usb controller */ - usbf_reset_controller(config, usbctlr); - - /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ - clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); - - /* Follow the crystal clock disable by >100ns delay */ - udelay(1); - - /* - * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP - * mux must be switched to actually use a_sess_vld threshold. - */ - if (fdt_gpio_isvalid(&config->vbus_gpio)) { - clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, - VBUS_SENSE_CTL_MASK, - VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); - } - - /* - * PLL Delay CONFIGURATION settings. The following parameters control - * the bring up of the plls. - */ - timing = usb_pll[clock_get_osc_freq()]; - - val = readl(&usbctlr->utmip_misc_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, - timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, - timing[PARAM_ACTIVE_DELAY_COUNT] << - UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); - writel(val, &usbctlr->utmip_misc_cfg1); - - /* Set PLL enable delay count and crystal frequency count */ - val = readl(&usbctlr->utmip_pll_cfg1); - clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, - timing[PARAM_ENABLE_DELAY_COUNT] << - UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); - clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, - timing[PARAM_XTAL_FREQ_COUNT] << - UTMIP_XTAL_FREQ_COUNT_SHIFT); - writel(val, &usbctlr->utmip_pll_cfg1); - - /* Setting the tracking length time */ - clrsetbits_le32(&usbctlr->utmip_bias_cfg1, - UTMIP_BIAS_PDTRK_COUNT_MASK, - timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); - - /* Program debounce time for VBUS to become valid */ - clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, - UTMIP_DEBOUNCE_CFG0_MASK, - timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); - - setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); - - /* Disable battery charge enabling bit */ - setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG); - - clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE); - setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL); - - /* - * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT - * Setting these fields, together with default values of the - * other fields, results in programming the registers below as - * follows: - * UTMIP_HSRX_CFG0 = 0x9168c000 - * UTMIP_HSRX_CFG1 = 0x13 - */ - - /* Set PLL enable delay count and Crystal frequency count */ - val = readl(&usbctlr->utmip_hsrx_cfg0); - clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, - utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); - clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, - utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); - writel(val, &usbctlr->utmip_hsrx_cfg0); - - /* Configure the UTMIP_HS_SYNC_START_DLY */ - clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, - UTMIP_HS_SYNC_START_DLY_MASK, - utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); - - /* Preceed the crystal clock disable by >100ns delay. */ - udelay(1); - - /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ - setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); - - /* Finished the per-controller init. */ - - /* De-assert UTMIP_RESET to bring out of reset. */ - clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); - - /* Wait for the phy clock to become valid in 100 ms */ - for (loop_count = 100000; loop_count != 0; loop_count--) { - if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) - break; - udelay(1); - } - if (!loop_count) - return -1; - - /* Disable ICUSB FS/LS transceiver */ - clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); - - /* Select UTMI parallel interface */ - clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, - PTS_UTMI << PTS_SHIFT); - clrbits_le32(&usbctlr->port_sc1, STS); - - /* Deassert power down state */ - clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | - UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); - clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | - UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); - - return 0; -} - -#ifdef CONFIG_USB_ULPI -/* if board file does not set a ULPI reference frequency we default to 24MHz */ -#ifndef CONFIG_ULPI_REF_CLK -#define CONFIG_ULPI_REF_CLK 24000000 -#endif - -/* set up the ULPI USB controller with the parameters provided */ -static int init_ulpi_usb_controller(struct fdt_usb *config) -{ - u32 val; - int loop_count; - struct ulpi_viewport ulpi_vp; - struct usb_ctlr *usbctlr = config->reg; - - /* set up ULPI reference clock on pllp_out4 */ - clock_enable(PERIPH_ID_DEV2_OUT); - clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); - - /* reset ULPI phy */ - if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { - fdtdec_setup_gpio(&config->phy_reset_gpio); - gpio_direction_output(config->phy_reset_gpio.gpio, 0); - mdelay(5); - gpio_set_value(config->phy_reset_gpio.gpio, 1); - } - - /* Reset the usb controller */ - clock_enable(config->periph_id); - usbf_reset_controller(config, usbctlr); - - /* enable pinmux bypass */ - setbits_le32(&usbctlr->ulpi_timing_ctrl_0, - ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); - - /* Select ULPI parallel interface */ - clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, PTS_ULPI << PTS_SHIFT); - - /* enable ULPI transceiver */ - setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); - - /* configure ULPI transceiver timings */ - val = 0; - writel(val, &usbctlr->ulpi_timing_ctrl_1); - - val |= ULPI_DATA_TRIMMER_SEL(4); - val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); - val |= ULPI_DIR_TRIMMER_SEL(4); - writel(val, &usbctlr->ulpi_timing_ctrl_1); - udelay(10); - - val |= ULPI_DATA_TRIMMER_LOAD; - val |= ULPI_STPDIRNXT_TRIMMER_LOAD; - val |= ULPI_DIR_TRIMMER_LOAD; - writel(val, &usbctlr->ulpi_timing_ctrl_1); - - /* set up phy for host operation with external vbus supply */ - ulpi_vp.port_num = 0; - ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; - - if (ulpi_init(&ulpi_vp)) { - printf("Tegra ULPI viewport init failed\n"); - return -1; - } - - ulpi_set_vbus(&ulpi_vp, 1, 1); - ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); - - /* enable wakeup events */ - setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); - - /* Enable and wait for the phy clock to become valid in 100 ms */ - setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); - for (loop_count = 100000; loop_count != 0; loop_count--) { - if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) - break; - udelay(1); - } - if (!loop_count) - return -1; - clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); - - return 0; -} -#else -static int init_ulpi_usb_controller(struct fdt_usb *config) -{ - printf("No code to set up ULPI controller, please enable" - "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT"); - return -1; -} -#endif - -static void config_clock(const u32 timing[]) -{ - clock_start_pll(CLOCK_ID_USB, - timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], - timing[PARAM_CPCON], timing[PARAM_LFCON]); -} - -int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor) -{ - struct fdt_usb *config; - struct usb_ctlr *usbctlr; - - if (portnum >= port_count) - return -1; - - config = &port[portnum]; - - /* skip init, if the port is already initialized */ - if (config->initialized) - goto success; - - if (config->utmi && init_utmi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", portnum); - return -1; - } - - if (config->ulpi && init_ulpi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", portnum); - return -1; - } - - set_host_mode(config); - - config->initialized = 1; - -success: - usbctlr = config->reg; - *hccr = (u32)&usbctlr->cap_length; - *hcor = (u32)&usbctlr->usb_cmd; - return 0; -} - -int tegrausb_stop_port(int portnum) -{ - struct usb_ctlr *usbctlr; - - usbctlr = port[portnum].reg; - - /* Stop controller */ - writel(0, &usbctlr->usb_cmd); - udelay(1000); - - /* Initiate controller reset */ - writel(2, &usbctlr->usb_cmd); - udelay(1000); - - port[portnum].initialized = 0; - - return 0; -} - -int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) -{ - const char *phy, *mode; - - config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); - mode = fdt_getprop(blob, node, "dr_mode", NULL); - if (mode) { - if (0 == strcmp(mode, "host")) - config->dr_mode = DR_MODE_HOST; - else if (0 == strcmp(mode, "peripheral")) - config->dr_mode = DR_MODE_DEVICE; - else if (0 == strcmp(mode, "otg")) - config->dr_mode = DR_MODE_OTG; - else { - debug("%s: Cannot decode dr_mode '%s'\n", __func__, - mode); - return -FDT_ERR_NOTFOUND; - } - } else { - config->dr_mode = DR_MODE_HOST; - } - - phy = fdt_getprop(blob, node, "phy_type", NULL); - config->utmi = phy && 0 == strcmp("utmi", phy); - config->ulpi = phy && 0 == strcmp("ulpi", phy); - config->enabled = fdtdec_get_is_enabled(blob, node); - config->has_legacy_mode = fdtdec_get_bool(blob, node, - "nvidia,has-legacy-mode"); - config->periph_id = clock_decode_periph_id(blob, node); - if (config->periph_id == PERIPH_ID_NONE) { - debug("%s: Missing/invalid peripheral ID\n", __func__); - return -FDT_ERR_NOTFOUND; - } - fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio); - fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio", - &config->phy_reset_gpio); - debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, " - "vbus=%d, phy_reset=%d, dr_mode=%d\n", - config->enabled, config->has_legacy_mode, config->utmi, - config->ulpi, config->periph_id, config->vbus_gpio.gpio, - config->phy_reset_gpio.gpio, config->dr_mode); - - return 0; -} - -int board_usb_init(const void *blob) -{ - struct fdt_usb config; - enum clock_osc_freq freq; - int node_list[USB_PORTS_MAX]; - int node, count, i; - - /* Set up the USB clocks correctly based on our oscillator frequency */ - freq = clock_get_osc_freq(); - config_clock(usb_pll[freq]); - - /* count may return <0 on error */ - count = fdtdec_find_aliases_for_id(blob, "usb", - COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX); - for (i = 0; i < count; i++) { - if (port_count == USB_PORTS_MAX) { - printf("tegrausb: Cannot register more than %d ports\n", - USB_PORTS_MAX); - return -1; - } - - debug("USB %d: ", i); - node = node_list[i]; - if (!node) - continue; - if (fdt_decode_usb(blob, node, &config)) { - debug("Cannot decode USB node %s\n", - fdt_get_name(blob, node, NULL)); - return -1; - } - config.initialized = 0; - - /* add new USB port to the list of available ports */ - port[port_count++] = config; - } - - return 0; -} diff --git a/arch/arm/include/asm/arch-tegra20/usb.h b/arch/arm/include/asm/arch-tegra/usb.h similarity index 100% rename from arch/arm/include/asm/arch-tegra20/usb.h rename to arch/arm/include/asm/arch-tegra/usb.h diff --git a/arch/arm/include/asm/arch-tegra20/tegra.h b/arch/arm/include/asm/arch-tegra20/tegra.h index e1de0447ff..ad5c01d1f4 100644 --- a/arch/arm/include/asm/arch-tegra20/tegra.h +++ b/arch/arm/include/asm/arch-tegra20/tegra.h @@ -29,7 +29,6 @@ #include #define TEGRA_USB1_BASE 0xC5000000 -#define TEGRA_USB3_BASE 0xC5008000 #define BCT_ODMDATA_OFFSET 4068 /* 12 bytes from end of BCT */ diff --git a/arch/arm/include/asm/arch-tegra30/tegra.h b/arch/arm/include/asm/arch-tegra30/tegra.h index decf564d13..c02c5d8500 100644 --- a/arch/arm/include/asm/arch-tegra30/tegra.h +++ b/arch/arm/include/asm/arch-tegra30/tegra.h @@ -21,6 +21,8 @@ #include +#define TEGRA_USB1_BASE 0x7D000000 + #define BCT_ODMDATA_OFFSET 6116 /* 12 bytes from end of BCT */ #define MAX_NUM_CPU 4 diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index d1d8a29cba..665fa1c36c 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -46,7 +46,7 @@ #include #endif #ifdef CONFIG_USB_EHCI_TEGRA -#include +#include #endif #include #include diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index a1c43f8331..b77806f310 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -1,5 +1,7 @@ /* + * Copyright (c) 2011 The Chromium OS Authors. * Copyright (c) 2009-2012 NVIDIA Corporation + * Copyright (c) 2013 Lucas Stach * * See file CREDITS for list of people who contributed to this * project. @@ -21,12 +23,128 @@ */ #include +#include +#include +#include +#include +#include #include +#include +#include +#include #include "ehci.h" -#include -#include +#ifdef CONFIG_USB_ULPI + #ifndef CONFIG_USB_ULPI_VIEWPORT + #error "To use CONFIG_USB_ULPI on Tegra Boards you have to also \ + define CONFIG_USB_ULPI_VIEWPORT" + #endif +#endif + +enum { + USB_PORTS_MAX = 3, /* Maximum ports we allow */ +}; + +/* Parameters we need for USB */ +enum { + PARAM_DIVN, /* PLL FEEDBACK DIVIDer */ + PARAM_DIVM, /* PLL INPUT DIVIDER */ + PARAM_DIVP, /* POST DIVIDER (2^N) */ + PARAM_CPCON, /* BASE PLLC CHARGE Pump setup ctrl */ + PARAM_LFCON, /* BASE PLLC LOOP FILter setup ctrl */ + PARAM_ENABLE_DELAY_COUNT, /* PLL-U Enable Delay Count */ + PARAM_STABLE_COUNT, /* PLL-U STABLE count */ + PARAM_ACTIVE_DELAY_COUNT, /* PLL-U Active delay count */ + PARAM_XTAL_FREQ_COUNT, /* PLL-U XTAL frequency count */ + PARAM_DEBOUNCE_A_TIME, /* 10MS DELAY for BIAS_DEBOUNCE_A */ + PARAM_BIAS_TIME, /* 20US DELAY AFter bias cell op */ + + PARAM_COUNT +}; + +/* Possible port types (dual role mode) */ +enum dr_mode { + DR_MODE_NONE = 0, + DR_MODE_HOST, /* supports host operation */ + DR_MODE_DEVICE, /* supports device operation */ + DR_MODE_OTG, /* supports both */ +}; + +/* Information about a USB port */ +struct fdt_usb { + struct usb_ctlr *reg; /* address of registers in physical memory */ + unsigned utmi:1; /* 1 if port has external tranceiver, else 0 */ + unsigned ulpi:1; /* 1 if port has external ULPI transceiver */ + unsigned enabled:1; /* 1 to enable, 0 to disable */ + unsigned has_legacy_mode:1; /* 1 if this port has legacy mode */ + unsigned initialized:1; /* has this port already been initialized? */ + enum dr_mode dr_mode; /* dual role mode */ + enum periph_id periph_id;/* peripheral id */ + struct fdt_gpio_state vbus_gpio; /* GPIO for vbus enable */ + struct fdt_gpio_state phy_reset_gpio; /* GPIO to reset ULPI phy */ +}; + +static struct fdt_usb port[USB_PORTS_MAX]; /* List of valid USB ports */ +static unsigned port_count; /* Number of available ports */ + +/* + * This table has USB timing parameters for each Oscillator frequency we + * support. There are four sets of values: + * + * 1. PLLU configuration information (reference clock is osc/clk_m and + * PLLU-FOs are fixed at 12MHz/60MHz/480MHz). + * + * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz + * ---------------------------------------------------------------------- + * DIVN 960 (0x3c0) 200 (0c8) 960 (3c0h) 960 (3c0) + * DIVM 13 (0d) 4 (04) 12 (0c) 26 (1a) + * Filter frequency (MHz) 1 4.8 6 2 + * CPCON 1100b 0011b 1100b 1100b + * LFCON0 0 0 0 0 + * + * 2. PLL CONFIGURATION & PARAMETERS for different clock generators: + * + * Reference frequency 13.0MHz 19.2MHz 12.0MHz 26.0MHz + * --------------------------------------------------------------------------- + * PLLU_ENABLE_DLY_COUNT 02 (0x02) 03 (03) 02 (02) 04 (04) + * PLLU_STABLE_COUNT 51 (33) 75 (4B) 47 (2F) 102 (66) + * PLL_ACTIVE_DLY_COUNT 05 (05) 06 (06) 04 (04) 09 (09) + * XTAL_FREQ_COUNT 127 (7F) 187 (BB) 118 (76) 254 (FE) + * + * 3. Debounce values IdDig, Avalid, Bvalid, VbusValid, VbusWakeUp, and + * SessEnd. Each of these signals have their own debouncer and for each of + * those one out of two debouncing times can be chosen (BIAS_DEBOUNCE_A or + * BIAS_DEBOUNCE_B). + * + * The values of DEBOUNCE_A and DEBOUNCE_B are calculated as follows: + * 0xffff -> No debouncing at all + * ms = *1000 / (1/19.2MHz) / 4 + * + * So to program a 1 ms debounce for BIAS_DEBOUNCE_A, we have: + * BIAS_DEBOUNCE_A[15:0] = 1000 * 19.2 / 4 = 4800 = 0x12c0 + * + * We need to use only DebounceA for BOOTROM. We don't need the DebounceB + * values, so we can keep those to default. + * + * 4. The 20 microsecond delay after bias cell operation. + */ +static const unsigned usb_pll[CLOCK_OSC_FREQ_COUNT][PARAM_COUNT] = { + /* DivN, DivM, DivP, CPCON, LFCON, Delays Debounce, Bias */ + { 0x3C0, 0x0D, 0x00, 0xC, 0, 0x02, 0x33, 0x05, 0x7F, 0x7EF4, 5 }, + { 0x0C8, 0x04, 0x00, 0x3, 0, 0x03, 0x4B, 0x06, 0xBB, 0xBB80, 7 }, + { 0x3C0, 0x0C, 0x00, 0xC, 0, 0x02, 0x2F, 0x04, 0x76, 0x7530, 5 }, + { 0x3C0, 0x1A, 0x00, 0xC, 0, 0x04, 0x66, 0x09, 0xFE, 0xFDE8, 9 } +}; + +/* UTMIP Idle Wait Delay */ +static const u8 utmip_idle_wait_delay = 17; + +/* UTMIP Elastic limit */ +static const u8 utmip_elastic_limit = 16; + +/* UTMIP High Speed Sync Start Delay */ +static const u8 utmip_hs_sync_start_delay = 9; /* * A known hardware issue where Connect Status Change bit of PORTSC register @@ -45,6 +163,419 @@ void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) *reg |= EHCI_PS_CSC; } +/* Put the port into host mode */ +static void set_host_mode(struct fdt_usb *config) +{ + /* + * If we are an OTG port, check if remote host is driving VBus and + * bail out in this case. + */ + if (config->dr_mode == DR_MODE_OTG && + (readl(&config->reg->phy_vbus_sensors) & VBUS_VLD_STS)) + return; + + /* + * If not driving, we set the GPIO to enable VBUS. We assume + * that the pinmux is set up correctly for this. + */ + if (fdt_gpio_isvalid(&config->vbus_gpio)) { + fdtdec_setup_gpio(&config->vbus_gpio); + gpio_direction_output(config->vbus_gpio.gpio, + (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? + 0 : 1); + debug("set_host_mode: GPIO %d %s\n", config->vbus_gpio.gpio, + (config->vbus_gpio.flags & FDT_GPIO_ACTIVE_LOW) ? + "low" : "high"); + } +} + +void usbf_reset_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) +{ + /* Reset the USB controller with 2us delay */ + reset_periph(config->periph_id, 2); + + /* + * Set USB1_NO_LEGACY_MODE to 1, Registers are accessible under + * base address + */ + if (config->has_legacy_mode) + setbits_le32(&usbctlr->usb1_legacy_ctrl, USB1_NO_LEGACY_MODE); + + /* Put UTMIP1/3 in reset */ + setbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); + + /* Enable the UTMIP PHY */ + if (config->utmi) + setbits_le32(&usbctlr->susp_ctrl, UTMIP_PHY_ENB); +} + +/* set up the UTMI USB controller with the parameters provided */ +static int init_utmi_usb_controller(struct fdt_usb *config) +{ + u32 val; + int loop_count; + const unsigned *timing; + struct usb_ctlr *usbctlr = config->reg; + + clock_enable(config->periph_id); + + /* Reset the usb controller */ + usbf_reset_controller(config, usbctlr); + + /* Stop crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN low */ + clrbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); + + /* Follow the crystal clock disable by >100ns delay */ + udelay(1); + + /* + * To Use the A Session Valid for cable detection logic, VBUS_WAKEUP + * mux must be switched to actually use a_sess_vld threshold. + */ + if (fdt_gpio_isvalid(&config->vbus_gpio)) { + clrsetbits_le32(&usbctlr->usb1_legacy_ctrl, + VBUS_SENSE_CTL_MASK, + VBUS_SENSE_CTL_A_SESS_VLD << VBUS_SENSE_CTL_SHIFT); + } + + /* + * PLL Delay CONFIGURATION settings. The following parameters control + * the bring up of the plls. + */ + timing = usb_pll[clock_get_osc_freq()]; + + val = readl(&usbctlr->utmip_misc_cfg1); + clrsetbits_le32(&val, UTMIP_PLLU_STABLE_COUNT_MASK, + timing[PARAM_STABLE_COUNT] << UTMIP_PLLU_STABLE_COUNT_SHIFT); + clrsetbits_le32(&val, UTMIP_PLL_ACTIVE_DLY_COUNT_MASK, + timing[PARAM_ACTIVE_DELAY_COUNT] << + UTMIP_PLL_ACTIVE_DLY_COUNT_SHIFT); + writel(val, &usbctlr->utmip_misc_cfg1); + + /* Set PLL enable delay count and crystal frequency count */ + val = readl(&usbctlr->utmip_pll_cfg1); + clrsetbits_le32(&val, UTMIP_PLLU_ENABLE_DLY_COUNT_MASK, + timing[PARAM_ENABLE_DELAY_COUNT] << + UTMIP_PLLU_ENABLE_DLY_COUNT_SHIFT); + clrsetbits_le32(&val, UTMIP_XTAL_FREQ_COUNT_MASK, + timing[PARAM_XTAL_FREQ_COUNT] << + UTMIP_XTAL_FREQ_COUNT_SHIFT); + writel(val, &usbctlr->utmip_pll_cfg1); + + /* Setting the tracking length time */ + clrsetbits_le32(&usbctlr->utmip_bias_cfg1, + UTMIP_BIAS_PDTRK_COUNT_MASK, + timing[PARAM_BIAS_TIME] << UTMIP_BIAS_PDTRK_COUNT_SHIFT); + + /* Program debounce time for VBUS to become valid */ + clrsetbits_le32(&usbctlr->utmip_debounce_cfg0, + UTMIP_DEBOUNCE_CFG0_MASK, + timing[PARAM_DEBOUNCE_A_TIME] << UTMIP_DEBOUNCE_CFG0_SHIFT); + + setbits_le32(&usbctlr->utmip_tx_cfg0, UTMIP_FS_PREAMBLE_J); + + /* Disable battery charge enabling bit */ + setbits_le32(&usbctlr->utmip_bat_chrg_cfg0, UTMIP_PD_CHRG); + + clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_XCVR_LSBIAS_SE); + setbits_le32(&usbctlr->utmip_spare_cfg0, FUSE_SETUP_SEL); + + /* + * Configure the UTMIP_IDLE_WAIT and UTMIP_ELASTIC_LIMIT + * Setting these fields, together with default values of the + * other fields, results in programming the registers below as + * follows: + * UTMIP_HSRX_CFG0 = 0x9168c000 + * UTMIP_HSRX_CFG1 = 0x13 + */ + + /* Set PLL enable delay count and Crystal frequency count */ + val = readl(&usbctlr->utmip_hsrx_cfg0); + clrsetbits_le32(&val, UTMIP_IDLE_WAIT_MASK, + utmip_idle_wait_delay << UTMIP_IDLE_WAIT_SHIFT); + clrsetbits_le32(&val, UTMIP_ELASTIC_LIMIT_MASK, + utmip_elastic_limit << UTMIP_ELASTIC_LIMIT_SHIFT); + writel(val, &usbctlr->utmip_hsrx_cfg0); + + /* Configure the UTMIP_HS_SYNC_START_DLY */ + clrsetbits_le32(&usbctlr->utmip_hsrx_cfg1, + UTMIP_HS_SYNC_START_DLY_MASK, + utmip_hs_sync_start_delay << UTMIP_HS_SYNC_START_DLY_SHIFT); + + /* Preceed the crystal clock disable by >100ns delay. */ + udelay(1); + + /* Resuscitate crystal clock by setting UTMIP_PHY_XTAL_CLOCKEN */ + setbits_le32(&usbctlr->utmip_misc_cfg1, UTMIP_PHY_XTAL_CLOCKEN); + + /* Finished the per-controller init. */ + + /* De-assert UTMIP_RESET to bring out of reset. */ + clrbits_le32(&usbctlr->susp_ctrl, UTMIP_RESET); + + /* Wait for the phy clock to become valid in 100 ms */ + for (loop_count = 100000; loop_count != 0; loop_count--) { + if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) + break; + udelay(1); + } + if (!loop_count) + return -1; + + /* Disable ICUSB FS/LS transceiver */ + clrbits_le32(&usbctlr->icusb_ctrl, IC_ENB1); + + /* Select UTMI parallel interface */ + clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, + PTS_UTMI << PTS_SHIFT); + clrbits_le32(&usbctlr->port_sc1, STS); + + /* Deassert power down state */ + clrbits_le32(&usbctlr->utmip_xcvr_cfg0, UTMIP_FORCE_PD_POWERDOWN | + UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN); + clrbits_le32(&usbctlr->utmip_xcvr_cfg1, UTMIP_FORCE_PDDISC_POWERDOWN | + UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN); + + return 0; +} + +#ifdef CONFIG_USB_ULPI +/* if board file does not set a ULPI reference frequency we default to 24MHz */ +#ifndef CONFIG_ULPI_REF_CLK +#define CONFIG_ULPI_REF_CLK 24000000 +#endif + +/* set up the ULPI USB controller with the parameters provided */ +static int init_ulpi_usb_controller(struct fdt_usb *config) +{ + u32 val; + int loop_count; + struct ulpi_viewport ulpi_vp; + struct usb_ctlr *usbctlr = config->reg; + + /* set up ULPI reference clock on pllp_out4 */ + clock_enable(PERIPH_ID_DEV2_OUT); + clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); + + /* reset ULPI phy */ + if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { + fdtdec_setup_gpio(&config->phy_reset_gpio); + gpio_direction_output(config->phy_reset_gpio.gpio, 0); + mdelay(5); + gpio_set_value(config->phy_reset_gpio.gpio, 1); + } + + /* Reset the usb controller */ + clock_enable(config->periph_id); + usbf_reset_controller(config, usbctlr); + + /* enable pinmux bypass */ + setbits_le32(&usbctlr->ulpi_timing_ctrl_0, + ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); + + /* Select ULPI parallel interface */ + clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, PTS_ULPI << PTS_SHIFT); + + /* enable ULPI transceiver */ + setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); + + /* configure ULPI transceiver timings */ + val = 0; + writel(val, &usbctlr->ulpi_timing_ctrl_1); + + val |= ULPI_DATA_TRIMMER_SEL(4); + val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); + val |= ULPI_DIR_TRIMMER_SEL(4); + writel(val, &usbctlr->ulpi_timing_ctrl_1); + udelay(10); + + val |= ULPI_DATA_TRIMMER_LOAD; + val |= ULPI_STPDIRNXT_TRIMMER_LOAD; + val |= ULPI_DIR_TRIMMER_LOAD; + writel(val, &usbctlr->ulpi_timing_ctrl_1); + + /* set up phy for host operation with external vbus supply */ + ulpi_vp.port_num = 0; + ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; + + if (ulpi_init(&ulpi_vp)) { + printf("Tegra ULPI viewport init failed\n"); + return -1; + } + + ulpi_set_vbus(&ulpi_vp, 1, 1); + ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); + + /* enable wakeup events */ + setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); + + /* Enable and wait for the phy clock to become valid in 100 ms */ + setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); + for (loop_count = 100000; loop_count != 0; loop_count--) { + if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) + break; + udelay(1); + } + if (!loop_count) + return -1; + clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); + + return 0; +} +#else +static int init_ulpi_usb_controller(struct fdt_usb *config) +{ + printf("No code to set up ULPI controller, please enable" + "CONFIG_USB_ULPI and CONFIG_USB_ULPI_VIEWPORT"); + return -1; +} +#endif + +static void config_clock(const u32 timing[]) +{ + clock_start_pll(CLOCK_ID_USB, + timing[PARAM_DIVM], timing[PARAM_DIVN], timing[PARAM_DIVP], + timing[PARAM_CPCON], timing[PARAM_LFCON]); +} + +int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor) +{ + struct fdt_usb *config; + struct usb_ctlr *usbctlr; + + if (portnum >= port_count) + return -1; + + config = &port[portnum]; + + /* skip init, if the port is already initialized */ + if (config->initialized) + goto success; + + if (config->utmi && init_utmi_usb_controller(config)) { + printf("tegrausb: Cannot init port %d\n", portnum); + return -1; + } + + if (config->ulpi && init_ulpi_usb_controller(config)) { + printf("tegrausb: Cannot init port %d\n", portnum); + return -1; + } + + set_host_mode(config); + + config->initialized = 1; + +success: + usbctlr = config->reg; + *hccr = (u32)&usbctlr->cap_length; + *hcor = (u32)&usbctlr->usb_cmd; + return 0; +} + +int tegrausb_stop_port(int portnum) +{ + struct usb_ctlr *usbctlr; + + usbctlr = port[portnum].reg; + + /* Stop controller */ + writel(0, &usbctlr->usb_cmd); + udelay(1000); + + /* Initiate controller reset */ + writel(2, &usbctlr->usb_cmd); + udelay(1000); + + port[portnum].initialized = 0; + + return 0; +} + +int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) +{ + const char *phy, *mode; + + config->reg = (struct usb_ctlr *)fdtdec_get_addr(blob, node, "reg"); + mode = fdt_getprop(blob, node, "dr_mode", NULL); + if (mode) { + if (0 == strcmp(mode, "host")) + config->dr_mode = DR_MODE_HOST; + else if (0 == strcmp(mode, "peripheral")) + config->dr_mode = DR_MODE_DEVICE; + else if (0 == strcmp(mode, "otg")) + config->dr_mode = DR_MODE_OTG; + else { + debug("%s: Cannot decode dr_mode '%s'\n", __func__, + mode); + return -FDT_ERR_NOTFOUND; + } + } else { + config->dr_mode = DR_MODE_HOST; + } + + phy = fdt_getprop(blob, node, "phy_type", NULL); + config->utmi = phy && 0 == strcmp("utmi", phy); + config->ulpi = phy && 0 == strcmp("ulpi", phy); + config->enabled = fdtdec_get_is_enabled(blob, node); + config->has_legacy_mode = fdtdec_get_bool(blob, node, + "nvidia,has-legacy-mode"); + config->periph_id = clock_decode_periph_id(blob, node); + if (config->periph_id == PERIPH_ID_NONE) { + debug("%s: Missing/invalid peripheral ID\n", __func__); + return -FDT_ERR_NOTFOUND; + } + fdtdec_decode_gpio(blob, node, "nvidia,vbus-gpio", &config->vbus_gpio); + fdtdec_decode_gpio(blob, node, "nvidia,phy-reset-gpio", + &config->phy_reset_gpio); + debug("enabled=%d, legacy_mode=%d, utmi=%d, ulpi=%d, periph_id=%d, " + "vbus=%d, phy_reset=%d, dr_mode=%d\n", + config->enabled, config->has_legacy_mode, config->utmi, + config->ulpi, config->periph_id, config->vbus_gpio.gpio, + config->phy_reset_gpio.gpio, config->dr_mode); + + return 0; +} + +int board_usb_init(const void *blob) +{ + struct fdt_usb config; + enum clock_osc_freq freq; + int node_list[USB_PORTS_MAX]; + int node, count, i; + + /* Set up the USB clocks correctly based on our oscillator frequency */ + freq = clock_get_osc_freq(); + config_clock(usb_pll[freq]); + + /* count may return <0 on error */ + count = fdtdec_find_aliases_for_id(blob, "usb", + COMPAT_NVIDIA_TEGRA20_USB, node_list, USB_PORTS_MAX); + for (i = 0; i < count; i++) { + if (port_count == USB_PORTS_MAX) { + printf("tegrausb: Cannot register more than %d ports\n", + USB_PORTS_MAX); + return -1; + } + + debug("USB %d: ", i); + node = node_list[i]; + if (!node) + continue; + if (fdt_decode_usb(blob, node, &config)) { + debug("Cannot decode USB node %s\n", + fdt_get_name(blob, node, NULL)); + return -1; + } + config.initialized = 0; + + /* add new USB port to the list of available ports */ + port[port_count++] = config; + } + + return 0; +} + /* * Create the appropriate control structures to manage * a new EHCI host controller. From d7a55e1a4b702bffae3e8ed43a5be125a30ba8ab Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 7 Feb 2013 07:16:30 +0000 Subject: [PATCH 07/39] tegra: usb: move [start|stop]_port into ehci_hcd_[init|stop] The ehci_hcd entry points were just calling into the Tegra USB functions. Now that they are in the same file we can just move over the implementation. Signed-off-by: Lucas Stach Acked-by: Simon Glass Signed-off-by: Tom Warren --- arch/arm/include/asm/arch-tegra/usb.h | 19 ---- drivers/usb/host/ehci-tegra.c | 119 +++++++++++--------------- 2 files changed, 51 insertions(+), 87 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra/usb.h b/arch/arm/include/asm/arch-tegra/usb.h index b18c85080b..ef6c089be2 100644 --- a/arch/arm/include/asm/arch-tegra/usb.h +++ b/arch/arm/include/asm/arch-tegra/usb.h @@ -246,23 +246,4 @@ struct usb_ctlr { /* Setup USB on the board */ int board_usb_init(const void *blob); -/** - * Start up the given port number (ports are numbered from 0 on each board). - * This returns values for the appropriate hccr and hcor addresses to use for - * USB EHCI operations. - * - * @param portnum port number to start - * @param hccr returns start address of EHCI HCCR registers - * @param hcor returns start address of EHCI HCOR registers - * @return 0 if ok, -1 on error (generally invalid port number) - */ -int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor); - -/** - * Stop the current port - * - * @return 0 if ok, -1 if no port was active - */ -int tegrausb_stop_port(int portnum); - #endif /* _TEGRA_USB_H_ */ diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index b77806f310..554145a250 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -438,60 +438,6 @@ static void config_clock(const u32 timing[]) timing[PARAM_CPCON], timing[PARAM_LFCON]); } -int tegrausb_start_port(int portnum, u32 *hccr, u32 *hcor) -{ - struct fdt_usb *config; - struct usb_ctlr *usbctlr; - - if (portnum >= port_count) - return -1; - - config = &port[portnum]; - - /* skip init, if the port is already initialized */ - if (config->initialized) - goto success; - - if (config->utmi && init_utmi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", portnum); - return -1; - } - - if (config->ulpi && init_ulpi_usb_controller(config)) { - printf("tegrausb: Cannot init port %d\n", portnum); - return -1; - } - - set_host_mode(config); - - config->initialized = 1; - -success: - usbctlr = config->reg; - *hccr = (u32)&usbctlr->cap_length; - *hcor = (u32)&usbctlr->usb_cmd; - return 0; -} - -int tegrausb_stop_port(int portnum) -{ - struct usb_ctlr *usbctlr; - - usbctlr = port[portnum].reg; - - /* Stop controller */ - writel(0, &usbctlr->usb_cmd); - udelay(1000); - - /* Initiate controller reset */ - writel(2, &usbctlr->usb_cmd); - udelay(1000); - - port[portnum].initialized = 0; - - return 0; -} - int fdt_decode_usb(const void *blob, int node, struct fdt_usb *config) { const char *phy, *mode; @@ -576,32 +522,69 @@ int board_usb_init(const void *blob) return 0; } -/* - * Create the appropriate control structures to manage - * a new EHCI host controller. +/** + * Start up the given port number (ports are numbered from 0 on each board). + * This returns values for the appropriate hccr and hcor addresses to use for + * USB EHCI operations. + * + * @param index port number to start + * @param hccr returns start address of EHCI HCCR registers + * @param hcor returns start address of EHCI HCOR registers + * @return 0 if ok, -1 on error (generally invalid port number) */ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { - u32 our_hccr, our_hcor; + struct fdt_usb *config; + struct usb_ctlr *usbctlr; - /* - * Select the first port, as we don't have a way of selecting others - * yet - */ - if (tegrausb_start_port(index, &our_hccr, &our_hcor)) + if (index >= port_count) return -1; - *hccr = (struct ehci_hccr *)our_hccr; - *hcor = (struct ehci_hcor *)our_hcor; + config = &port[index]; + /* skip init, if the port is already initialized */ + if (config->initialized) + goto success; + + if (config->utmi && init_utmi_usb_controller(config)) { + printf("tegrausb: Cannot init port %d\n", index); + return -1; + } + + if (config->ulpi && init_ulpi_usb_controller(config)) { + printf("tegrausb: Cannot init port %d\n", index); + return -1; + } + + set_host_mode(config); + + config->initialized = 1; + +success: + usbctlr = config->reg; + *hccr = (struct ehci_hccr *)&usbctlr->cap_length; + *hcor = (struct ehci_hcor *)&usbctlr->usb_cmd; return 0; } /* - * Destroy the appropriate control structures corresponding - * the the EHCI host controller. + * Bring down the specified USB controller */ int ehci_hcd_stop(int index) { - return tegrausb_stop_port(index); + struct usb_ctlr *usbctlr; + + usbctlr = port[index].reg; + + /* Stop controller */ + writel(0, &usbctlr->usb_cmd); + udelay(1000); + + /* Initiate controller reset */ + writel(2, &usbctlr->usb_cmd); + udelay(1000); + + port[index].initialized = 0; + + return 0; } From 702b87289438cfc3165408f0eaf999b0b67c1e7e Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Wed, 27 Feb 2013 11:10:01 +0000 Subject: [PATCH 08/39] Tegra114: I2C: Take DVFS out of reset to allow I2C5 (PWR_I2C) to work I2C driver can now probe dev 0 (PWR_I2C, where the PMU, etc. lives). This is needed so that the SDIO slot power can be brought up for the MMC driver, so it has to precede those commits. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/cpu/arm720t/tegra114/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/cpu/arm720t/tegra114/cpu.c b/arch/arm/cpu/arm720t/tegra114/cpu.c index 5962e15b4f..0b2157a0df 100644 --- a/arch/arm/cpu/arm720t/tegra114/cpu.c +++ b/arch/arm/cpu/arm720t/tegra114/cpu.c @@ -201,6 +201,7 @@ void t114_init_clocks(void) reset_set_enable(PERIPH_ID_MSELECT, 0); reset_set_enable(PERIPH_ID_EMC1, 0); reset_set_enable(PERIPH_ID_MC1, 0); + reset_set_enable(PERIPH_ID_DVFS, 0); debug("t114_init_clocks exit\n"); } From e32624ef820f821b94333402788e79979681eb29 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Fri, 8 Feb 2013 07:25:30 +0000 Subject: [PATCH 09/39] Tegra: I2C: Add T114 clock support to tegra_i2c driver T114 has a slightly different I2C clock, with a new (extra) divisor in standard/fast mode and HS mode. Tested on my Dalmore, and the I2C clock is 100KHz +/- 3Hz on my Saleae Logic analyzer. Added a new entry in compat_names for T114 I2C since it differs from the previous Tegra SoCs. A flag is set when T114 I2C HW is found so new features like the extra clock divisor can be used. Signed-off-by: Tom Warren Acked-by: Laxman Dewangan --- arch/arm/include/asm/arch-tegra/tegra_i2c.h | 6 +++ drivers/i2c/tegra_i2c.c | 42 ++++++++++++++++++--- include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra/tegra_i2c.h b/arch/arm/include/asm/arch-tegra/tegra_i2c.h index 2650744718..853e59bb6e 100644 --- a/arch/arm/include/asm/arch-tegra/tegra_i2c.h +++ b/arch/arm/include/asm/arch-tegra/tegra_i2c.h @@ -105,6 +105,7 @@ struct i2c_ctlr { u32 sl_delay_count; /* 3C: I2C_I2C_SL_DELAY_COUNT */ u32 reserved_2[4]; /* 40: */ struct i2c_control control; /* 50 ~ 68 */ + u32 clk_div; /* 6C: I2C_I2C_CLOCK_DIVISOR */ }; /* bit fields definitions for IO Packet Header 1 format */ @@ -154,6 +155,11 @@ struct i2c_ctlr { #define I2C_INT_ARBITRATION_LOST_SHIFT 2 #define I2C_INT_ARBITRATION_LOST_MASK (1 << I2C_INT_ARBITRATION_LOST_SHIFT) +/* I2C_CLK_DIVISOR_REGISTER */ +#define CLK_DIV_STD_FAST_MODE 0x19 +#define CLK_DIV_HS_MODE 1 +#define CLK_MULT_STD_FAST_MODE 8 + /** * Returns the bus number of the DVC controller * diff --git a/drivers/i2c/tegra_i2c.c b/drivers/i2c/tegra_i2c.c index efc77fa910..ca71cd3ee4 100644 --- a/drivers/i2c/tegra_i2c.c +++ b/drivers/i2c/tegra_i2c.c @@ -46,6 +46,7 @@ struct i2c_bus { struct i2c_control *control; struct i2c_ctlr *regs; int is_dvc; /* DVC type, rather than I2C */ + int is_scs; /* single clock source (T114+) */ int inited; /* bus is inited */ }; @@ -88,7 +89,28 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus) * 16 to get the right frequency. */ clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH, - i2c_bus->speed * 2 * 8); + i2c_bus->speed * 2 * 8); + + if (i2c_bus->is_scs) { + /* + * T114 I2C went to a single clock source for standard/fast and + * HS clock speeds. The new clock rate setting calculation is: + * SCL = CLK_SOURCE.I2C / + * (CLK_MULT_STD_FAST_MODE * (I2C_CLK_DIV_STD_FAST_MODE+1) * + * I2C FREQUENCY DIVISOR) as per the T114 TRM (sec 30.3.1). + * + * NOTE: We do this here, after the initial clock/pll start, + * because if we read the clk_div reg before the controller + * is running, we hang, and we need it for the new calc. + */ + int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16; + debug("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__, + clk_div_stdfst_mode); + + clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH, + CLK_MULT_STD_FAST_MODE * (clk_div_stdfst_mode + 1) * + i2c_bus->speed * 2); + } /* Reset I2C controller. */ i2c_reset_controller(i2c_bus); @@ -352,10 +374,11 @@ static int i2c_get_config(const void *blob, int node, struct i2c_bus *i2c_bus) * @param node_list list of nodes to process (any <=0 are ignored) * @param count number of nodes to process * @param is_dvc 1 if these are DVC ports, 0 if standard I2C + * @param is_scs 1 if this HW uses a single clock source (T114+) * @return 0 if ok, -1 on error */ static int process_nodes(const void *blob, int node_list[], int count, - int is_dvc) + int is_dvc, int is_scs) { struct i2c_bus *i2c_bus; int i; @@ -375,6 +398,8 @@ static int process_nodes(const void *blob, int node_list[], int count, return -1; } + i2c_bus->is_scs = is_scs; + i2c_bus->is_dvc = is_dvc; if (is_dvc) { i2c_bus->control = @@ -403,18 +428,25 @@ void i2c_init_board(void) const void *blob = gd->fdt_blob; int count; - /* First get the normal i2c ports */ + /* First check for newer (T114+) I2C ports */ + count = fdtdec_find_aliases_for_id(blob, "i2c", + COMPAT_NVIDIA_TEGRA114_I2C, node_list, + TEGRA_I2C_NUM_CONTROLLERS); + if (process_nodes(blob, node_list, count, 0, 1)) + return; + + /* Now get the older (T20/T30) normal I2C ports */ count = fdtdec_find_aliases_for_id(blob, "i2c", COMPAT_NVIDIA_TEGRA20_I2C, node_list, TEGRA_I2C_NUM_CONTROLLERS); - if (process_nodes(blob, node_list, count, 0)) + if (process_nodes(blob, node_list, count, 0, 0)) return; /* Now look for dvc ports */ count = fdtdec_add_aliases_for_id(blob, "i2c", COMPAT_NVIDIA_TEGRA20_DVC, node_list, TEGRA_I2C_NUM_CONTROLLERS); - if (process_nodes(blob, node_list, count, 1)) + if (process_nodes(blob, node_list, count, 1, 0)) return; } diff --git a/include/fdtdec.h b/include/fdtdec.h index 77f244f417..c7a92d553e 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -62,6 +62,7 @@ struct fdt_memory { enum fdt_compat_id { COMPAT_UNKNOWN, COMPAT_NVIDIA_TEGRA20_USB, /* Tegra20 USB port */ + COMPAT_NVIDIA_TEGRA114_I2C, /* Tegra114 I2C w/single clock source */ COMPAT_NVIDIA_TEGRA20_I2C, /* Tegra20 i2c */ COMPAT_NVIDIA_TEGRA20_DVC, /* Tegra20 dvc (really just i2c) */ COMPAT_NVIDIA_TEGRA20_EMC, /* Tegra20 memory controller */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 3ae348dd30..7c7fc833a6 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -37,6 +37,7 @@ DECLARE_GLOBAL_DATA_PTR; static const char * const compat_names[COMPAT_COUNT] = { COMPAT(UNKNOWN, ""), COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"), + COMPAT(NVIDIA_TEGRA114_I2C, "nvidia,tegra114-i2c"), COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"), COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"), COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"), From b77c3547e867f7876b3f970125c45d556588d9cb Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Fri, 8 Feb 2013 07:25:31 +0000 Subject: [PATCH 10/39] Tegra114: fdt: Update DT files with I2C info for T114/Dalmore T114, like T30, does not have a separate/different DVC (power I2C) controller like T20 - all 5 I2C controllers are identical, but I2C5 is used to designate the controller intended for power control (PWR_I2C in the schematics). PWR_I2C is set to 400KHz. Signed-off-by: Tom Warren Acked-by: Laxman Dewangan Reviewed-by: Stephen Warren --- arch/arm/dts/tegra114.dtsi | 64 +++++++++++++++++++++++++++ board/nvidia/dts/tegra114-dalmore.dts | 25 +++++++++++ 2 files changed, 89 insertions(+) diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index d06cd126dd..0655b4d523 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -2,4 +2,68 @@ / { compatible = "nvidia,tegra114"; + + aliases { + i2c0 = "/i2c@7000d000"; + i2c1 = "/i2c@7000c000"; + i2c2 = "/i2c@7000c400"; + i2c3 = "/i2c@7000c500"; + i2c4 = "/i2c@7000c700"; + }; + + tegra_car: clock@60006000 { + compatible = "nvidia,tegra114-car"; + reg = <0x60006000 0x1000>; + #clock-cells = <1>; + }; + + i2c@7000c000 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c000 0x100>; + interrupts = <0 38 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 12>; + status = "disabled"; + }; + + i2c@7000c400 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c400 0x100>; + interrupts = <0 84 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 54>; + status = "disabled"; + }; + + i2c@7000c500 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c500 0x100>; + interrupts = <0 92 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 67>; + status = "disabled"; + }; + + i2c@7000c700 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000c700 0x100>; + interrupts = <0 120 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 103>; + status = "disabled"; + }; + + i2c@7000d000 { + compatible = "nvidia,tegra114-i2c"; + reg = <0x7000d000 0x100>; + interrupts = <0 53 0x04>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&tegra_car 47>; + status = "disabled"; + }; }; diff --git a/board/nvidia/dts/tegra114-dalmore.dts b/board/nvidia/dts/tegra114-dalmore.dts index 731557798e..ed3c2fde28 100644 --- a/board/nvidia/dts/tegra114-dalmore.dts +++ b/board/nvidia/dts/tegra114-dalmore.dts @@ -10,4 +10,29 @@ device_type = "memory"; reg = <0x80000000 0x80000000>; }; + + i2c@7000c000 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@7000c400 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@7000c500 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@7000c700 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + }; }; From a7f8b5e616e49a2bb819eeb96b5438039307e7b6 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Fri, 8 Feb 2013 07:25:32 +0000 Subject: [PATCH 11/39] Tegra114: I2C: Enable I2C driver on Dalmore E1611 eval board Tested all 5 'buses', i2c probe enumerates device addresses on bus 0, 1 and 2. Signed-off-by: Tom Warren Acked-by: Laxman Dewangan --- include/configs/dalmore.h | 9 +++++++++ include/configs/tegra114-common.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/include/configs/dalmore.h b/include/configs/dalmore.h index ce32c8030b..b1a6e34eba 100644 --- a/include/configs/dalmore.h +++ b/include/configs/dalmore.h @@ -41,6 +41,15 @@ #define CONFIG_MACH_TYPE MACH_TYPE_DALMORE #define CONFIG_BOARD_EARLY_INIT_F + +/* I2C */ +#define CONFIG_TEGRA_I2C +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_MAX_I2C_BUS TEGRA_I2C_NUM_CONTROLLERS +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_CMD_I2C + #define CONFIG_ENV_IS_NOWHERE #define MACH_TYPE_DALMORE 4304 /* not yet in mach-types.h */ diff --git a/include/configs/tegra114-common.h b/include/configs/tegra114-common.h index 003353040e..c2986d8309 100644 --- a/include/configs/tegra114-common.h +++ b/include/configs/tegra114-common.h @@ -76,4 +76,7 @@ #define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/tegra114/u-boot-spl.lds" +/* Total I2C ports on Tegra114 */ +#define TEGRA_I2C_NUM_CONTROLLERS 5 + #endif /* _TEGRA114_COMMON_H_ */ From 6c5be646b47e0dfea3df5a08948f50d1c5d37f68 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 21 Feb 2013 12:31:27 +0000 Subject: [PATCH 12/39] Tegra: fdt: Change /include/ to #include for C preprocessor dts Makefile has the arch & board include paths added to DTS_CPPFLAGS. This allows the use of '#include "xyz"' in the dts/dtsi file which helps the C preprocessor find common dtsi include files. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/dts/tegra114.dtsi | 2 +- arch/arm/dts/tegra20.dtsi | 2 +- arch/arm/dts/tegra30.dtsi | 2 +- board/avionic-design/dts/tegra20-medcom-wide.dts | 2 +- board/avionic-design/dts/tegra20-plutux.dts | 2 +- board/avionic-design/dts/tegra20-tec.dts | 2 +- board/compal/dts/tegra20-paz00.dts | 2 +- board/compulab/dts/tegra20-trimslice.dts | 2 +- board/nvidia/dts/tegra114-dalmore.dts | 2 +- board/nvidia/dts/tegra20-harmony.dts | 2 +- board/nvidia/dts/tegra20-seaboard.dts | 2 +- board/nvidia/dts/tegra20-ventana.dts | 2 +- board/nvidia/dts/tegra20-whistler.dts | 2 +- board/nvidia/dts/tegra30-cardhu.dts | 2 +- board/toradex/dts/tegra20-colibri_t20_iris.dts | 2 +- dts/Makefile | 3 ++- 16 files changed, 17 insertions(+), 16 deletions(-) diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index 0655b4d523..f0f82de012 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -1,4 +1,4 @@ -/include/ "skeleton.dtsi" +#include "skeleton.dtsi" / { compatible = "nvidia,tegra114"; diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi index 9a8968522e..d163ff8b27 100644 --- a/arch/arm/dts/tegra20.dtsi +++ b/arch/arm/dts/tegra20.dtsi @@ -1,4 +1,4 @@ -/include/ "skeleton.dtsi" +#include "skeleton.dtsi" / { compatible = "nvidia,tegra20"; diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index 7b8126f7cc..561c617f4d 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -1,4 +1,4 @@ -/include/ "skeleton.dtsi" +#include "skeleton.dtsi" / { compatible = "nvidia,tegra30"; diff --git a/board/avionic-design/dts/tegra20-medcom-wide.dts b/board/avionic-design/dts/tegra20-medcom-wide.dts index e46afbeab3..4afe5c26ef 100644 --- a/board/avionic-design/dts/tegra20-medcom-wide.dts +++ b/board/avionic-design/dts/tegra20-medcom-wide.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "Avionic Design Medcom-Wide"; diff --git a/board/avionic-design/dts/tegra20-plutux.dts b/board/avionic-design/dts/tegra20-plutux.dts index 3e6cce013e..ef83f29f2b 100644 --- a/board/avionic-design/dts/tegra20-plutux.dts +++ b/board/avionic-design/dts/tegra20-plutux.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "Avionic Design Plutux"; diff --git a/board/avionic-design/dts/tegra20-tec.dts b/board/avionic-design/dts/tegra20-tec.dts index bf3ff1d009..cf2fadc52f 100644 --- a/board/avionic-design/dts/tegra20-tec.dts +++ b/board/avionic-design/dts/tegra20-tec.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "Avionic Design Tamonten Evaluation Carrier"; diff --git a/board/compal/dts/tegra20-paz00.dts b/board/compal/dts/tegra20-paz00.dts index 31b064d418..e521c80784 100644 --- a/board/compal/dts/tegra20-paz00.dts +++ b/board/compal/dts/tegra20-paz00.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "Toshiba AC100 / Dynabook AZ"; diff --git a/board/compulab/dts/tegra20-trimslice.dts b/board/compulab/dts/tegra20-trimslice.dts index 7aeed670db..eefd1993de 100644 --- a/board/compulab/dts/tegra20-trimslice.dts +++ b/board/compulab/dts/tegra20-trimslice.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "Compulab TrimSlice board"; diff --git a/board/nvidia/dts/tegra114-dalmore.dts b/board/nvidia/dts/tegra114-dalmore.dts index ed3c2fde28..27a4a07206 100644 --- a/board/nvidia/dts/tegra114-dalmore.dts +++ b/board/nvidia/dts/tegra114-dalmore.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include ARCH_CPU_DTS / { model = "NVIDIA Dalmore"; diff --git a/board/nvidia/dts/tegra20-harmony.dts b/board/nvidia/dts/tegra20-harmony.dts index aeda3a1ffb..9fc7c0db90 100644 --- a/board/nvidia/dts/tegra20-harmony.dts +++ b/board/nvidia/dts/tegra20-harmony.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "NVIDIA Tegra20 Harmony evaluation board"; diff --git a/board/nvidia/dts/tegra20-seaboard.dts b/board/nvidia/dts/tegra20-seaboard.dts index 527a29689d..a73db36f1e 100644 --- a/board/nvidia/dts/tegra20-seaboard.dts +++ b/board/nvidia/dts/tegra20-seaboard.dts @@ -1,7 +1,7 @@ /dts-v1/; /memreserve/ 0x1c000000 0x04000000; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "NVIDIA Seaboard"; diff --git a/board/nvidia/dts/tegra20-ventana.dts b/board/nvidia/dts/tegra20-ventana.dts index 3e5e39da63..ffc71b2778 100644 --- a/board/nvidia/dts/tegra20-ventana.dts +++ b/board/nvidia/dts/tegra20-ventana.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "NVIDIA Tegra20 Ventana evaluation board"; diff --git a/board/nvidia/dts/tegra20-whistler.dts b/board/nvidia/dts/tegra20-whistler.dts index 4579557d6d..1f09e5e7dd 100644 --- a/board/nvidia/dts/tegra20-whistler.dts +++ b/board/nvidia/dts/tegra20-whistler.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "NVIDIA Tegra20 Whistler evaluation board"; diff --git a/board/nvidia/dts/tegra30-cardhu.dts b/board/nvidia/dts/tegra30-cardhu.dts index f9f80c5218..f7ea07af84 100644 --- a/board/nvidia/dts/tegra30-cardhu.dts +++ b/board/nvidia/dts/tegra30-cardhu.dts @@ -1,7 +1,7 @@ /dts-v1/; /memreserve/ 0x1c000000 0x04000000; -/include/ ARCH_CPU_DTS +#include ARCH_CPU_DTS / { model = "NVIDIA Cardhu"; diff --git a/board/toradex/dts/tegra20-colibri_t20_iris.dts b/board/toradex/dts/tegra20-colibri_t20_iris.dts index c29b43a0ef..53c0cdc9f2 100644 --- a/board/toradex/dts/tegra20-colibri_t20_iris.dts +++ b/board/toradex/dts/tegra20-colibri_t20_iris.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ ARCH_CPU_DTS +#include "tegra20.dtsi" / { model = "Toradex Colibri T20"; diff --git a/dts/Makefile b/dts/Makefile index 922c78c1ca..6f36153634 100644 --- a/dts/Makefile +++ b/dts/Makefile @@ -38,7 +38,8 @@ Please define CONFIG_ARCH_DEVICE_TREE)) # We preprocess the device tree file provide a useful define DTS_CPPFLAGS := -x assembler-with-cpp \ -DARCH_CPU_DTS=\"$(SRCTREE)/arch/$(ARCH)/dts/$(CONFIG_ARCH_DEVICE_TREE).dtsi\" \ - -DBOARD_DTS=\"$(SRCTREE)/board/$(VENDOR)/$(BOARD)/dts/$(DEVICE_TREE).dts\" + -DBOARD_DTS=\"$(SRCTREE)/board/$(VENDOR)/$(BOARD)/dts/$(DEVICE_TREE).dts\" \ + -I$(SRCTREE)/board/$(VENDOR)/dts -I$(SRCTREE)/arch/$(ARCH)/dts all: $(obj).depend $(LIB) From 90b079c8f989c0e949e2a275e77434aa4e16b8e0 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 21 Feb 2013 12:31:28 +0000 Subject: [PATCH 13/39] Tegra: fdt: tamonten: Add common tamonten.dtsi file from linux Tamonten boards (medcom-wide, plutux, and tec) use a different/new dtsi file w/common settings. Signed-off-by: Tom Warren Acked-by: Thierry Reding Reviewed-by: Stephen Warren --- .../dts/tegra20-medcom-wide.dts | 2 +- board/avionic-design/dts/tegra20-plutux.dts | 2 +- .../avionic-design/dts/tegra20-tamonten.dtsi | 489 ++++++++++++++++++ board/avionic-design/dts/tegra20-tec.dts | 2 +- 4 files changed, 492 insertions(+), 3 deletions(-) create mode 100644 board/avionic-design/dts/tegra20-tamonten.dtsi diff --git a/board/avionic-design/dts/tegra20-medcom-wide.dts b/board/avionic-design/dts/tegra20-medcom-wide.dts index 4afe5c26ef..2acfbc18ef 100644 --- a/board/avionic-design/dts/tegra20-medcom-wide.dts +++ b/board/avionic-design/dts/tegra20-medcom-wide.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include "tegra20.dtsi" +#include "tegra20-tamonten.dtsi" / { model = "Avionic Design Medcom-Wide"; diff --git a/board/avionic-design/dts/tegra20-plutux.dts b/board/avionic-design/dts/tegra20-plutux.dts index ef83f29f2b..dba200df41 100644 --- a/board/avionic-design/dts/tegra20-plutux.dts +++ b/board/avionic-design/dts/tegra20-plutux.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include "tegra20.dtsi" +#include "tegra20-tamonten.dtsi" / { model = "Avionic Design Plutux"; diff --git a/board/avionic-design/dts/tegra20-tamonten.dtsi b/board/avionic-design/dts/tegra20-tamonten.dtsi new file mode 100644 index 0000000000..86c7bab160 --- /dev/null +++ b/board/avionic-design/dts/tegra20-tamonten.dtsi @@ -0,0 +1,489 @@ +#include "tegra20.dtsi" + +/ { + model = "Avionic Design Tamonten SOM"; + compatible = "ad,tamonten", "nvidia,tegra20"; + + memory { + reg = <0x00000000 0x20000000>; + }; + + host1x { + hdmi { + vdd-supply = <&hdmi_vdd_reg>; + pll-supply = <&hdmi_pll_reg>; + + nvidia,ddc-i2c-bus = <&hdmi_ddc>; + nvidia,hpd-gpio = <&gpio 111 0>; /* PN7 */ + }; + }; + + pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + ata { + nvidia,pins = "ata"; + nvidia,function = "ide"; + }; + atb { + nvidia,pins = "atb", "gma", "gme"; + nvidia,function = "sdio4"; + }; + atc { + nvidia,pins = "atc"; + nvidia,function = "nand"; + }; + atd { + nvidia,pins = "atd", "ate", "gmb", "gmd", "gpu", + "spia", "spib", "spic"; + nvidia,function = "gmi"; + }; + cdev1 { + nvidia,pins = "cdev1"; + nvidia,function = "plla_out"; + }; + cdev2 { + nvidia,pins = "cdev2"; + nvidia,function = "pllp_out4"; + }; + crtp { + nvidia,pins = "crtp"; + nvidia,function = "crt"; + }; + csus { + nvidia,pins = "csus"; + nvidia,function = "vi_sensor_clk"; + }; + dap1 { + nvidia,pins = "dap1"; + nvidia,function = "dap1"; + }; + dap2 { + nvidia,pins = "dap2"; + nvidia,function = "dap2"; + }; + dap3 { + nvidia,pins = "dap3"; + nvidia,function = "dap3"; + }; + dap4 { + nvidia,pins = "dap4"; + nvidia,function = "dap4"; + }; + dta { + nvidia,pins = "dta", "dtd"; + nvidia,function = "sdio2"; + }; + dtb { + nvidia,pins = "dtb", "dtc", "dte"; + nvidia,function = "rsvd1"; + }; + dtf { + nvidia,pins = "dtf"; + nvidia,function = "i2c3"; + }; + gmc { + nvidia,pins = "gmc"; + nvidia,function = "uartd"; + }; + gpu7 { + nvidia,pins = "gpu7"; + nvidia,function = "rtck"; + }; + gpv { + nvidia,pins = "gpv", "slxa", "slxk"; + nvidia,function = "pcie"; + }; + hdint { + nvidia,pins = "hdint"; + nvidia,function = "hdmi"; + }; + i2cp { + nvidia,pins = "i2cp"; + nvidia,function = "i2cp"; + }; + irrx { + nvidia,pins = "irrx", "irtx"; + nvidia,function = "uarta"; + }; + kbca { + nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd", + "kbce", "kbcf"; + nvidia,function = "kbc"; + }; + lcsn { + nvidia,pins = "lcsn", "ld0", "ld1", "ld2", + "ld3", "ld4", "ld5", "ld6", "ld7", + "ld8", "ld9", "ld10", "ld11", "ld12", + "ld13", "ld14", "ld15", "ld16", "ld17", + "ldc", "ldi", "lhp0", "lhp1", "lhp2", + "lhs", "lm0", "lm1", "lpp", "lpw0", + "lpw1", "lpw2", "lsc0", "lsc1", "lsck", + "lsda", "lsdi", "lspi", "lvp0", "lvp1", + "lvs"; + nvidia,function = "displaya"; + }; + owc { + nvidia,pins = "owc", "spdi", "spdo", "uac"; + nvidia,function = "rsvd2"; + }; + pmc { + nvidia,pins = "pmc"; + nvidia,function = "pwr_on"; + }; + rm { + nvidia,pins = "rm"; + nvidia,function = "i2c1"; + }; + sdb { + nvidia,pins = "sdb", "sdc", "sdd"; + nvidia,function = "pwm"; + }; + sdio1 { + nvidia,pins = "sdio1"; + nvidia,function = "sdio1"; + }; + slxc { + nvidia,pins = "slxc", "slxd"; + nvidia,function = "spdif"; + }; + spid { + nvidia,pins = "spid", "spie", "spif"; + nvidia,function = "spi1"; + }; + spig { + nvidia,pins = "spig", "spih"; + nvidia,function = "spi2_alt"; + }; + uaa { + nvidia,pins = "uaa", "uab", "uda"; + nvidia,function = "ulpi"; + }; + uad { + nvidia,pins = "uad"; + nvidia,function = "irda"; + }; + uca { + nvidia,pins = "uca", "ucb"; + nvidia,function = "uartc"; + }; + conf_ata { + nvidia,pins = "ata", "atb", "atc", "atd", "ate", + "cdev1", "cdev2", "dap1", "dtb", "gma", + "gmb", "gmc", "gmd", "gme", "gpu7", + "gpv", "i2cp", "pta", "rm", "slxa", + "slxk", "spia", "spib", "uac"; + nvidia,pull = <0>; + nvidia,tristate = <0>; + }; + conf_ck32 { + nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", + "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; + nvidia,pull = <0>; + }; + conf_csus { + nvidia,pins = "csus", "spid", "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; + conf_crtp { + nvidia,pins = "crtp", "dap2", "dap3", "dap4", + "dtc", "dte", "dtf", "gpu", "sdio1", + "slxc", "slxd", "spdi", "spdo", "spig", + "uda"; + nvidia,pull = <0>; + nvidia,tristate = <1>; + }; + conf_ddc { + nvidia,pins = "ddc", "dta", "dtd", "kbca", + "kbcb", "kbcc", "kbcd", "kbce", "kbcf", + "sdc"; + nvidia,pull = <2>; + nvidia,tristate = <0>; + }; + conf_hdint { + nvidia,pins = "hdint", "lcsn", "ldc", "lm1", + "lpw1", "lsc1", "lsck", "lsda", "lsdi", + "lvp0", "owc", "sdb"; + nvidia,tristate = <1>; + }; + conf_irrx { + nvidia,pins = "irrx", "irtx", "sdd", "spic", + "spie", "spih", "uaa", "uab", "uad", + "uca", "ucb"; + nvidia,pull = <2>; + nvidia,tristate = <1>; + }; + conf_lc { + nvidia,pins = "lc", "ls"; + nvidia,pull = <2>; + }; + conf_ld0 { + nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4", + "ld5", "ld6", "ld7", "ld8", "ld9", + "ld10", "ld11", "ld12", "ld13", "ld14", + "ld15", "ld16", "ld17", "ldi", "lhp0", + "lhp1", "lhp2", "lhs", "lm0", "lpp", + "lpw0", "lpw2", "lsc0", "lspi", "lvp1", + "lvs", "pmc"; + nvidia,tristate = <0>; + }; + conf_ld17_0 { + nvidia,pins = "ld17_0", "ld19_18", "ld21_20", + "ld23_22"; + nvidia,pull = <1>; + }; + }; + + state_i2cmux_ddc: pinmux_i2cmux_ddc { + ddc { + nvidia,pins = "ddc"; + nvidia,function = "i2c2"; + }; + pta { + nvidia,pins = "pta"; + nvidia,function = "rsvd4"; + }; + }; + + state_i2cmux_pta: pinmux_i2cmux_pta { + ddc { + nvidia,pins = "ddc"; + nvidia,function = "rsvd4"; + }; + pta { + nvidia,pins = "pta"; + nvidia,function = "i2c2"; + }; + }; + + state_i2cmux_idle: pinmux_i2cmux_idle { + ddc { + nvidia,pins = "ddc"; + nvidia,function = "rsvd4"; + }; + pta { + nvidia,pins = "pta"; + nvidia,function = "rsvd4"; + }; + }; + }; + + i2s@70002800 { + status = "okay"; + }; + + serial@70006300 { + status = "okay"; + }; + + i2c@7000c000 { + clock-frequency = <400000>; + status = "okay"; + }; + + i2c@7000c400 { + clock-frequency = <100000>; + status = "okay"; + }; + + i2cmux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <1>; + #size-cells = <0>; + + i2c-parent = <&{/i2c@7000c400}>; + + pinctrl-names = "ddc", "pta", "idle"; + pinctrl-0 = <&state_i2cmux_ddc>; + pinctrl-1 = <&state_i2cmux_pta>; + pinctrl-2 = <&state_i2cmux_idle>; + + hdmi_ddc: i2c@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + i2c@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + i2c@7000d000 { + clock-frequency = <400000>; + status = "okay"; + + pmic: tps6586x@34 { + compatible = "ti,tps6586x"; + reg = <0x34>; + interrupts = <0 86 0x4>; + + ti,system-power-controller; + + #gpio-cells = <2>; + gpio-controller; + + sys-supply = <&vdd_5v0_reg>; + vin-sm0-supply = <&sys_reg>; + vin-sm1-supply = <&sys_reg>; + vin-sm2-supply = <&sys_reg>; + vinldo01-supply = <&sm2_reg>; + vinldo23-supply = <&sm2_reg>; + vinldo4-supply = <&sm2_reg>; + vinldo678-supply = <&sm2_reg>; + vinldo9-supply = <&sm2_reg>; + + regulators { + sys_reg: sys { + regulator-name = "vdd_sys"; + regulator-always-on; + }; + + sm0 { + regulator-name = "vdd_sys_sm0,vdd_core"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + sm1 { + regulator-name = "vdd_sys_sm1,vdd_cpu"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + sm2_reg: sm2 { + regulator-name = "vdd_sys_sm2,vin_ldo*"; + regulator-min-microvolt = <3700000>; + regulator-max-microvolt = <3700000>; + regulator-always-on; + }; + + ldo0 { + regulator-name = "vdd_ldo0,vddio_pex_clk"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo1 { + regulator-name = "vdd_ldo1,avdd_pll*"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + }; + + ldo2 { + regulator-name = "vdd_ldo2,vdd_rtc"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + }; + + ldo3 { + regulator-name = "vdd_ldo3,avdd_usb*"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + ldo4 { + regulator-name = "vdd_ldo4,avdd_osc,vddio_sys"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo5 { + regulator-name = "vdd_ldo5,vcore_mmc"; + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; + + ldo6 { + regulator-name = "vdd_ldo6,avdd_vdac"; + /* + * According to the Tegra 2 Automotive + * DataSheet, a typical value for this + * would be 2.8V, but the PMIC only + * supports 2.85V. + */ + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + }; + + hdmi_vdd_reg: ldo7 { + regulator-name = "vdd_ldo7,avdd_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + hdmi_pll_reg: ldo8 { + regulator-name = "vdd_ldo8,avdd_hdmi_pll"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo9 { + regulator-name = "vdd_ldo9,vdd_ddr_rx,avdd_cam"; + /* + * According to the Tegra 2 Automotive + * DataSheet, a typical value for this + * would be 2.8V, but the PMIC only + * supports 2.85V. + */ + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + regulator-always-on; + }; + + ldo_rtc { + regulator-name = "vdd_rtc_out"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + }; + + temperature-sensor@4c { + compatible = "onnn,nct1008"; + reg = <0x4c>; + }; + }; + + pmc { + nvidia,invert-interrupt; + }; + + usb@c5008000 { + status = "okay"; + }; + + sdhci@c8000600 { + cd-gpios = <&gpio 58 1>; /* gpio PH2 */ + wp-gpios = <&gpio 59 0>; /* gpio PH3 */ + bus-width = <4>; + status = "okay"; + }; + + regulators { + compatible = "simple-bus"; + + #address-cells = <1>; + #size-cells = <0>; + + vdd_5v0_reg: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "vdd_5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + }; +}; diff --git a/board/avionic-design/dts/tegra20-tec.dts b/board/avionic-design/dts/tegra20-tec.dts index cf2fadc52f..04e6730047 100644 --- a/board/avionic-design/dts/tegra20-tec.dts +++ b/board/avionic-design/dts/tegra20-tec.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include "tegra20.dtsi" +#include "tegra20-tamonten.dtsi" / { model = "Avionic Design Tamonten Evaluation Carrier"; From 126685ad44ad39895567884458b3a4581acf8902 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 21 Feb 2013 12:31:29 +0000 Subject: [PATCH 14/39] Tegra: fdt: Add/enhance sdhci (mmc) nodes for all T20 DT files Linux dts files were used for those boards that didn't already have sdhci info populated. Tamonten has their own dtsi file with common sdhci nodes (sourced from Linux). Signed-off-by: Tom Warren Tested-by: Thierry Reding Reviewed-by: Stephen Warren --- arch/arm/dts/tegra20.dtsi | 16 ++++++++++++---- .../dts/tegra20-medcom-wide.dts | 1 + board/avionic-design/dts/tegra20-plutux.dts | 1 + board/avionic-design/dts/tegra20-tec.dts | 1 + board/compal/dts/tegra20-paz00.dts | 19 +++++++++++++++++-- board/compulab/dts/tegra20-trimslice.dts | 14 ++++++++++++++ board/nvidia/dts/tegra114-dalmore.dts | 2 +- board/nvidia/dts/tegra20-harmony.dts | 18 ++++++++++++++++++ board/nvidia/dts/tegra20-seaboard.dts | 12 ++++++++---- board/nvidia/dts/tegra20-ventana.dts | 15 +++++++++++++++ board/nvidia/dts/tegra20-whistler.dts | 13 +++++++++++++ board/nvidia/dts/tegra30-cardhu.dts | 2 +- .../toradex/dts/tegra20-colibri_t20_iris.dts | 7 +++++++ 13 files changed, 109 insertions(+), 12 deletions(-) diff --git a/arch/arm/dts/tegra20.dtsi b/arch/arm/dts/tegra20.dtsi index d163ff8b27..3805750581 100644 --- a/arch/arm/dts/tegra20.dtsi +++ b/arch/arm/dts/tegra20.dtsi @@ -318,24 +318,32 @@ sdhci@c8000000 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000000 0x200>; - interrupts = < 46 >; + interrupts = <0 14 0x04>; + clocks = <&tegra_car 14>; + status = "disabled"; }; sdhci@c8000200 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000200 0x200>; - interrupts = < 47 >; + interrupts = <0 15 0x04>; + clocks = <&tegra_car 9>; + status = "disabled"; }; sdhci@c8000400 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000400 0x200>; - interrupts = < 51 >; + interrupts = <0 19 0x04>; + clocks = <&tegra_car 69>; + status = "disabled"; }; sdhci@c8000600 { compatible = "nvidia,tegra20-sdhci"; reg = <0xc8000600 0x200>; - interrupts = < 63 >; + interrupts = <0 31 0x04>; + clocks = <&tegra_car 15>; + status = "disabled"; }; }; diff --git a/board/avionic-design/dts/tegra20-medcom-wide.dts b/board/avionic-design/dts/tegra20-medcom-wide.dts index 2acfbc18ef..a9a07f9bcd 100644 --- a/board/avionic-design/dts/tegra20-medcom-wide.dts +++ b/board/avionic-design/dts/tegra20-medcom-wide.dts @@ -8,6 +8,7 @@ aliases { usb0 = "/usb@c5008000"; + sdhci0 = "/sdhci@c8000600"; }; memory { diff --git a/board/avionic-design/dts/tegra20-plutux.dts b/board/avionic-design/dts/tegra20-plutux.dts index dba200df41..20016f29bb 100644 --- a/board/avionic-design/dts/tegra20-plutux.dts +++ b/board/avionic-design/dts/tegra20-plutux.dts @@ -8,6 +8,7 @@ aliases { usb0 = "/usb@c5008000"; + sdhci0 = "/sdhci@c8000600"; }; memory { diff --git a/board/avionic-design/dts/tegra20-tec.dts b/board/avionic-design/dts/tegra20-tec.dts index 04e6730047..1d7cf89eb6 100644 --- a/board/avionic-design/dts/tegra20-tec.dts +++ b/board/avionic-design/dts/tegra20-tec.dts @@ -8,6 +8,7 @@ aliases { usb0 = "/usb@c5008000"; + sdhci0 = "/sdhci@c8000600"; }; memory { diff --git a/board/compal/dts/tegra20-paz00.dts b/board/compal/dts/tegra20-paz00.dts index e521c80784..780203cfb3 100644 --- a/board/compal/dts/tegra20-paz00.dts +++ b/board/compal/dts/tegra20-paz00.dts @@ -3,11 +3,13 @@ #include "tegra20.dtsi" / { - model = "Toshiba AC100 / Dynabook AZ"; - compatible = "compal,paz00", "nvidia,tegra20"; + model = "Toshiba AC100 / Dynabook AZ"; + compatible = "compal,paz00", "nvidia,tegra20"; aliases { usb0 = "/usb@c5008000"; + sdhci0 = "/sdhci@c8000600"; + sdhci1 = "/sdhci@c8000000"; }; memory { @@ -53,6 +55,19 @@ status = "disabled"; }; + sdhci@c8000000 { + status = "okay"; + cd-gpios = <&gpio 173 1>; /* gpio PV5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 169 0>; /* gpio PV1 */ + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + bus-width = <8>; + }; + lcd_panel: panel { /* PAZ00 has 1024x600 */ clock = <54030000>; diff --git a/board/compulab/dts/tegra20-trimslice.dts b/board/compulab/dts/tegra20-trimslice.dts index eefd1993de..ee31476c1e 100644 --- a/board/compulab/dts/tegra20-trimslice.dts +++ b/board/compulab/dts/tegra20-trimslice.dts @@ -9,6 +9,8 @@ aliases { usb0 = "/usb@c5008000"; usb1 = "/usb@c5000000"; + sdhci0 = "/sdhci@c8000600"; + sdhci1 = "/sdhci@c8000000"; }; memory { @@ -47,4 +49,16 @@ usb@c5004000 { status = "disabled"; }; + + sdhci@c8000000 { + status = "okay"; + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + cd-gpios = <&gpio 121 1>; /* gpio PP1 */ + wp-gpios = <&gpio 122 0>; /* gpio PP2 */ + bus-width = <4>; + }; }; diff --git a/board/nvidia/dts/tegra114-dalmore.dts b/board/nvidia/dts/tegra114-dalmore.dts index 27a4a07206..3e1e1eaff8 100644 --- a/board/nvidia/dts/tegra114-dalmore.dts +++ b/board/nvidia/dts/tegra114-dalmore.dts @@ -1,6 +1,6 @@ /dts-v1/; -#include ARCH_CPU_DTS +#include "tegra114.dtsi" / { model = "NVIDIA Dalmore"; diff --git a/board/nvidia/dts/tegra20-harmony.dts b/board/nvidia/dts/tegra20-harmony.dts index 9fc7c0db90..7934e4a897 100644 --- a/board/nvidia/dts/tegra20-harmony.dts +++ b/board/nvidia/dts/tegra20-harmony.dts @@ -9,6 +9,8 @@ aliases { usb0 = "/usb@c5008000"; usb1 = "/usb@c5004000"; + sdhci0 = "/sdhci@c8000600"; + sdhci1 = "/sdhci@c8000200"; }; memory { @@ -52,4 +54,20 @@ usb@c5004000 { nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ }; + + sdhci@c8000200 { + status = "okay"; + cd-gpios = <&gpio 69 1>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 155 0>; /* gpio PT3 */ + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + cd-gpios = <&gpio 58 1>; /* gpio PH2 */ + wp-gpios = <&gpio 59 0>; /* gpio PH3 */ + power-gpios = <&gpio 70 0>; /* gpio PI6 */ + bus-width = <8>; + }; }; diff --git a/board/nvidia/dts/tegra20-seaboard.dts b/board/nvidia/dts/tegra20-seaboard.dts index a73db36f1e..12cb0bc780 100644 --- a/board/nvidia/dts/tegra20-seaboard.dts +++ b/board/nvidia/dts/tegra20-seaboard.dts @@ -12,14 +12,15 @@ }; aliases { - /* This defines the order of our USB ports */ + /* This defines the order of our ports */ usb0 = "/usb@c5008000"; usb1 = "/usb@c5000000"; - i2c0 = "/i2c@7000d000"; i2c1 = "/i2c@7000c000"; i2c2 = "/i2c@7000c400"; i2c3 = "/i2c@7000c500"; + sdhci0 = "/sdhci@c8000600"; + sdhci1 = "/sdhci@c8000400"; }; memory { @@ -156,13 +157,16 @@ }; sdhci@c8000400 { - cd-gpios = <&gpio 69 0>; /* gpio PI5 */ + status = "okay"; + cd-gpios = <&gpio 69 1>; /* gpio PI5 */ wp-gpios = <&gpio 57 0>; /* gpio PH1 */ power-gpios = <&gpio 70 0>; /* gpio PI6 */ + bus-width = <4>; }; sdhci@c8000600 { - support-8bit; + status = "okay"; + bus-width = <8>; }; lcd_panel: panel { diff --git a/board/nvidia/dts/tegra20-ventana.dts b/board/nvidia/dts/tegra20-ventana.dts index ffc71b2778..e1a3d1ec91 100644 --- a/board/nvidia/dts/tegra20-ventana.dts +++ b/board/nvidia/dts/tegra20-ventana.dts @@ -8,6 +8,8 @@ aliases { usb0 = "/usb@c5008000"; + sdhci0 = "/sdhci@c8000600"; + sdhci1 = "/sdhci@c8000400"; }; memory { @@ -41,4 +43,17 @@ usb@c5004000 { status = "disabled"; }; + + sdhci@c8000400 { + status = "okay"; + cd-gpios = <&gpio 69 1>; /* gpio PI5 */ + wp-gpios = <&gpio 57 0>; /* gpio PH1 */ + power-gpios = <&gpio 70 0>; /* gpio PI6 */ + bus-width = <4>; + }; + + sdhci@c8000600 { + status = "okay"; + bus-width = <8>; + }; }; diff --git a/board/nvidia/dts/tegra20-whistler.dts b/board/nvidia/dts/tegra20-whistler.dts index 1f09e5e7dd..eb92264f9d 100644 --- a/board/nvidia/dts/tegra20-whistler.dts +++ b/board/nvidia/dts/tegra20-whistler.dts @@ -9,6 +9,8 @@ aliases { i2c0 = "/i2c@7000d000"; usb0 = "/usb@c5008000"; + sdhci0 = "/sdhci@c8000600"; + sdhci1 = "/sdhci@c8000400"; }; memory { @@ -57,4 +59,15 @@ usb@c5004000 { status = "disabled"; }; + + sdhci@c8000400 { + status = "okay"; + wp-gpios = <&gpio 173 0>; /* gpio PV5 */ + bus-width = <8>; + }; + + sdhci@c8000600 { + status = "okay"; + bus-width = <8>; + }; }; diff --git a/board/nvidia/dts/tegra30-cardhu.dts b/board/nvidia/dts/tegra30-cardhu.dts index f7ea07af84..8ad1fb70ef 100644 --- a/board/nvidia/dts/tegra30-cardhu.dts +++ b/board/nvidia/dts/tegra30-cardhu.dts @@ -1,7 +1,7 @@ /dts-v1/; /memreserve/ 0x1c000000 0x04000000; -#include ARCH_CPU_DTS +#include "tegra30.dtsi" / { model = "NVIDIA Cardhu"; diff --git a/board/toradex/dts/tegra20-colibri_t20_iris.dts b/board/toradex/dts/tegra20-colibri_t20_iris.dts index 53c0cdc9f2..c0e54af886 100644 --- a/board/toradex/dts/tegra20-colibri_t20_iris.dts +++ b/board/toradex/dts/tegra20-colibri_t20_iris.dts @@ -10,6 +10,7 @@ usb0 = "/usb@c5008000"; usb1 = "/usb@c5000000"; usb2 = "/usb@c5004000"; + sdhci0 = "/sdhci@c8000600"; }; usb@c5000000 { @@ -35,4 +36,10 @@ compatible = "nand-flash"; }; }; + + sdhci@c8000600 { + status = "okay"; + cd-gpios = <&gpio 23 1>; /* gpio PC7 */ + bus-width = <4>; + }; }; From c9aa831ee26f629fbd2df67cab8bb357777e2256 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 21 Feb 2013 12:31:30 +0000 Subject: [PATCH 15/39] Tegra: MMC: Add DT support to MMC driver for all T20 boards tegra_mmc_init() now parses the DT info for bus width, WP/CD GPIOs, etc. Tested on Seaboard, fully functional. Tamonten boards (medcom-wide, plutux, and tec) use a different/new dtsi file w/common settings. Signed-off-by: Tom Warren Signed-off-by: Thierry Reding Reviewed-by: Stephen Warren --- arch/arm/include/asm/arch-tegra/mmc.h | 2 +- arch/arm/include/asm/arch-tegra/tegra_mmc.h | 13 +- board/avionic-design/common/tamonten.c | 19 +- board/compal/paz00/paz00.c | 26 +-- board/compulab/trimslice/trimslice.c | 23 +-- board/nvidia/common/board.c | 25 +++ board/nvidia/harmony/harmony.c | 26 +-- board/nvidia/seaboard/seaboard.c | 25 +-- board/nvidia/whistler/whistler.c | 30 +-- .../colibri_t20_iris/colibri_t20_iris.c | 11 +- drivers/mmc/tegra_mmc.c | 179 ++++++++++++------ include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 13 files changed, 173 insertions(+), 208 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra/mmc.h b/arch/arm/include/asm/arch-tegra/mmc.h index 5c95047998..71ad407511 100644 --- a/arch/arm/include/asm/arch-tegra/mmc.h +++ b/arch/arm/include/asm/arch-tegra/mmc.h @@ -22,6 +22,6 @@ #ifndef _TEGRA_MMC_H_ #define _TEGRA_MMC_H_ -int tegra_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio); +void tegra_mmc_init(void); #endif /* _TEGRA_MMC_H_ */ diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h index dd746cae0d..bd18f5f75b 100644 --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h @@ -27,6 +27,8 @@ #define TEGRA_SDMMC3_BASE 0xC8000400 #define TEGRA_SDMMC4_BASE 0xC8000600 +#define MAX_HOSTS 4 /* Max number of 'hosts'/controllers */ + #ifndef __ASSEMBLY__ struct tegra_mmc { unsigned int sysad; /* _SYSTEM_ADDRESS_0 */ @@ -119,12 +121,15 @@ struct tegra_mmc { struct mmc_host { struct tegra_mmc *reg; + int id; /* device id/number, 0-3 */ + int enabled; /* 1 to enable, 0 to disable */ + int width; /* Bus Width, 1, 4 or 8 */ + enum periph_id mmc_id; /* Peripheral ID: PERIPH_ID_... */ + struct fdt_gpio_state cd_gpio; /* Change Detect GPIO */ + struct fdt_gpio_state pwr_gpio; /* Power GPIO */ + struct fdt_gpio_state wp_gpio; /* Write Protect GPIO */ unsigned int version; /* SDHCI spec. version */ unsigned int clock; /* Current clock (MHz) */ - unsigned int base; /* Base address, SDMMC1/2/3/4 */ - enum periph_id mmc_id; /* Peripheral ID: PERIPH_ID_... */ - int pwr_gpio; /* Power GPIO */ - int cd_gpio; /* Change Detect GPIO */ }; #endif /* __ASSEMBLY__ */ diff --git a/board/avionic-design/common/tamonten.c b/board/avionic-design/common/tamonten.c index e6a932ec3c..ea95e43286 100644 --- a/board/avionic-design/common/tamonten.c +++ b/board/avionic-design/common/tamonten.c @@ -33,13 +33,8 @@ #include #include #include -#include #include #include -#ifdef CONFIG_TEGRA_MMC -#include -#endif - #ifdef CONFIG_BOARD_EARLY_INIT_F void gpio_early_init(void) @@ -54,7 +49,7 @@ void gpio_early_init(void) * Routine: pin_mux_mmc * Description: setup the pin muxes/tristate values for the SDMMC(s) */ -static void pin_mux_mmc(void) +void pin_mux_mmc(void) { funcmux_select(PERIPH_ID_SDMMC4, FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT); /* for write-protect GPIO PI6 */ @@ -62,16 +57,4 @@ static void pin_mux_mmc(void) /* for CD GPIO PH2 */ pinmux_tristate_disable(PINGRP_ATD); } - -/* this is a weak define that we are overriding */ -int board_mmc_init(bd_t *bd) -{ - /* Enable muxes, etc. for SDMMC controllers */ - pin_mux_mmc(); - - /* init dev 0, SD slot, with 4-bit bus */ - tegra_mmc_init(0, 4, GPIO_PI6, GPIO_PH2); - - return 0; -} #endif diff --git a/board/compal/paz00/paz00.c b/board/compal/paz00/paz00.c index 1447f47605..d6e5c3740e 100644 --- a/board/compal/paz00/paz00.c +++ b/board/compal/paz00/paz00.c @@ -18,19 +18,14 @@ #include #include #include -#include #include -#ifdef CONFIG_TEGRA_MMC -#include -#endif - #ifdef CONFIG_TEGRA_MMC /* * Routine: pin_mux_mmc * Description: setup the pin muxes/tristate values for the SDMMC(s) */ -static void pin_mux_mmc(void) +void pin_mux_mmc(void) { /* SDMMC4: config 3, x8 on 2nd set of pins */ pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4); @@ -51,25 +46,6 @@ static void pin_mux_mmc(void) /* For CD GPIO PV5 */ pinmux_tristate_disable(PINGRP_GPV); } - -/* this is a weak define that we are overriding */ -int board_mmc_init(bd_t *bd) -{ - debug("board_mmc_init called\n"); - - /* Enable muxes, etc. for SDMMC controllers */ - pin_mux_mmc(); - - debug("board_mmc_init: init eMMC\n"); - /* init dev 0, eMMC chip, with 8-bit bus */ - tegra_mmc_init(0, 8, -1, -1); - - debug("board_mmc_init: init SD slot\n"); - /* init dev 3, SD slot, with 4-bit bus */ - tegra_mmc_init(3, 4, GPIO_PV1, GPIO_PV5); - - return 0; -} #endif #ifdef CONFIG_LCD diff --git a/board/compulab/trimslice/trimslice.c b/board/compulab/trimslice/trimslice.c index 8f4dd09faa..8401100b18 100644 --- a/board/compulab/trimslice/trimslice.c +++ b/board/compulab/trimslice/trimslice.c @@ -27,12 +27,8 @@ #include #include #include -#include #include #include -#ifdef CONFIG_TEGRA_MMC -#include -#endif void pin_mux_usb(void) { @@ -52,7 +48,7 @@ void pin_mux_spi(void) * Routine: pin_mux_mmc * Description: setup the pin muxes/tristate values for the SDMMC(s) */ -static void pin_mux_mmc(void) +void pin_mux_mmc(void) { funcmux_select(PERIPH_ID_SDMMC1, FUNCMUX_SDMMC1_SDIO1_4BIT); funcmux_select(PERIPH_ID_SDMMC4, FUNCMUX_SDMMC4_ATB_GMA_4_BIT); @@ -60,20 +56,3 @@ static void pin_mux_mmc(void) /* For CD GPIO PP1 */ pinmux_tristate_disable(PINGRP_DAP3); } - -/* this is a weak define that we are overriding */ -int board_mmc_init(bd_t *bd) -{ - debug("board_mmc_init called\n"); - - /* Enable muxes, etc. for SDMMC controllers */ - pin_mux_mmc(); - - /* init dev 0 (SDMMC4), (micro-SD slot) with 4-bit bus */ - tegra_mmc_init(0, 4, -1, GPIO_PP1); - - /* init dev 3 (SDMMC1), (SD slot) with 4-bit bus */ - tegra_mmc_init(3, 4, -1, -1); - - return 0; -} diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index 665fa1c36c..babbe08e06 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -48,6 +48,9 @@ #ifdef CONFIG_USB_EHCI_TEGRA #include #endif +#ifdef CONFIG_TEGRA_MMC +#include +#endif #include #include #include "emc.h" @@ -221,3 +224,25 @@ int board_late_init(void) #endif return 0; } + +#if defined(CONFIG_TEGRA_MMC) +void __pin_mux_mmc(void) +{ +} + +void pin_mux_mmc(void) __attribute__((weak, alias("__pin_mux_mmc"))); + +/* this is a weak define that we are overriding */ +int board_mmc_init(bd_t *bd) +{ + debug("%s called\n", __func__); + + /* Enable muxes, etc. for SDMMC controllers */ + pin_mux_mmc(); + + debug("%s: init MMC\n", __func__); + tegra_mmc_init(); + + return 0; +} +#endif diff --git a/board/nvidia/harmony/harmony.c b/board/nvidia/harmony/harmony.c index 93430edd3b..312244139c 100644 --- a/board/nvidia/harmony/harmony.c +++ b/board/nvidia/harmony/harmony.c @@ -27,19 +27,14 @@ #include #include #include -#include #include -#ifdef CONFIG_TEGRA_MMC -#include -#endif - #ifdef CONFIG_TEGRA_MMC /* * Routine: pin_mux_mmc * Description: setup the pin muxes/tristate values for the SDMMC(s) */ -static void pin_mux_mmc(void) +void pin_mux_mmc(void) { funcmux_select(PERIPH_ID_SDMMC4, FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT); funcmux_select(PERIPH_ID_SDMMC2, FUNCMUX_SDMMC2_DTA_DTD_8BIT); @@ -54,25 +49,6 @@ static void pin_mux_mmc(void) /* For CD GPIO PI5 */ pinmux_tristate_disable(PINGRP_ATC); } - -/* this is a weak define that we are overriding */ -int board_mmc_init(bd_t *bd) -{ - debug("board_mmc_init called\n"); - - /* Enable muxes, etc. for SDMMC controllers */ - pin_mux_mmc(); - - debug("board_mmc_init: init SD slot J26\n"); - /* init dev 0, SD slot J26, with 8-bit bus */ - tegra_mmc_init(0, 8, GPIO_PI6, GPIO_PH2); - - debug("board_mmc_init: init SD slot J5\n"); - /* init dev 2, SD slot J5, with 4-bit bus */ - tegra_mmc_init(2, 4, GPIO_PT3, GPIO_PI5); - - return 0; -} #endif void pin_mux_usb(void) diff --git a/board/nvidia/seaboard/seaboard.c b/board/nvidia/seaboard/seaboard.c index 3e33da0afc..e581fddf43 100644 --- a/board/nvidia/seaboard/seaboard.c +++ b/board/nvidia/seaboard/seaboard.c @@ -28,11 +28,7 @@ #include #include #include -#include #include -#ifdef CONFIG_TEGRA_MMC -#include -#endif /* TODO: Remove this code when the SPI switch is working */ #if !defined(CONFIG_SPI_UART_SWITCH) && (CONFIG_MACH_TYPE != MACH_TYPE_VENTANA) @@ -51,7 +47,7 @@ void gpio_early_init_uart(void) * Routine: pin_mux_mmc * Description: setup the pin muxes/tristate values for the SDMMC(s) */ -static void pin_mux_mmc(void) +void pin_mux_mmc(void) { funcmux_select(PERIPH_ID_SDMMC4, FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT); funcmux_select(PERIPH_ID_SDMMC3, FUNCMUX_SDMMC3_SDB_4BIT); @@ -61,25 +57,6 @@ static void pin_mux_mmc(void) /* For CD GPIO PI5 */ pinmux_tristate_disable(PINGRP_ATC); } - -/* this is a weak define that we are overriding */ -int board_mmc_init(bd_t *bd) -{ - debug("board_mmc_init called\n"); - - /* Enable muxes, etc. for SDMMC controllers */ - pin_mux_mmc(); - - debug("board_mmc_init: init eMMC\n"); - /* init dev 0, eMMC chip, with 8-bit bus */ - tegra_mmc_init(0, 8, -1, -1); - - debug("board_mmc_init: init SD slot\n"); - /* init dev 1, SD slot, with 4-bit bus */ - tegra_mmc_init(1, 4, GPIO_PI6, GPIO_PI5); - - return 0; -} #endif void pin_mux_usb(void) diff --git a/board/nvidia/whistler/whistler.c b/board/nvidia/whistler/whistler.c index 592cd6b496..f18aa277b3 100644 --- a/board/nvidia/whistler/whistler.c +++ b/board/nvidia/whistler/whistler.c @@ -27,32 +27,19 @@ #include #include #include -#include #include #include + #ifdef CONFIG_TEGRA_MMC -#include -#endif - - /* * Routine: pin_mux_mmc * Description: setup the pin muxes/tristate values for the SDMMC(s) */ -static void pin_mux_mmc(void) -{ - funcmux_select(PERIPH_ID_SDMMC3, FUNCMUX_SDMMC3_SDB_SLXA_8BIT); - funcmux_select(PERIPH_ID_SDMMC4, FUNCMUX_SDMMC4_ATC_ATD_8BIT); -} - -/* this is a weak define that we are overriding */ -int board_mmc_init(bd_t *bd) +void pin_mux_mmc(void) { uchar val; int ret; - debug("board_mmc_init called\n"); - /* Turn on MAX8907B LDO12 to 2.8V for J40 power */ ret = i2c_set_bus_num(0); if (ret) @@ -70,17 +57,10 @@ int board_mmc_init(bd_t *bd) if (ret) printf("i2c_write 0 0x3c 0x44 failed: %d\n", ret); - /* Enable muxes, etc. for SDMMC controllers */ - pin_mux_mmc(); - - /* init dev 0 (SDMMC4), (J29 "HSMMC") with 8-bit bus */ - tegra_mmc_init(0, 8, -1, -1); - - /* init dev 1 (SDMMC3), (J40 "SDIO3") with 8-bit bus */ - tegra_mmc_init(1, 8, -1, -1); - - return 0; + funcmux_select(PERIPH_ID_SDMMC3, FUNCMUX_SDMMC3_SDB_SLXA_8BIT); + funcmux_select(PERIPH_ID_SDMMC4, FUNCMUX_SDMMC4_ATC_ATD_8BIT); } +#endif /* this is a weak define that we are overriding */ void pin_mux_usb(void) diff --git a/board/toradex/colibri_t20_iris/colibri_t20_iris.c b/board/toradex/colibri_t20_iris/colibri_t20_iris.c index e40a98609f..aa76f65fde 100644 --- a/board/toradex/colibri_t20_iris/colibri_t20_iris.c +++ b/board/toradex/colibri_t20_iris/colibri_t20_iris.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "../colibri_t20-common/colibri_t20-common.h" @@ -34,13 +33,13 @@ void pin_mux_usb(void) #endif #ifdef CONFIG_TEGRA_MMC -int board_mmc_init(bd_t *bd) +/* + * Routine: pin_mux_mmc + * Description: setup the pin muxes/tristate values for the SDMMC(s) + */ +void pin_mux_mmc(void) { funcmux_select(PERIPH_ID_SDMMC4, FUNCMUX_SDMMC4_ATB_GMA_4_BIT); pinmux_tristate_disable(PINGRP_GMB); - - tegra_mmc_init(0, 4, -1, GPIO_PC7); - - return 0; } #endif diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 72586193ca..455a690b7e 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -2,7 +2,7 @@ * (C) Copyright 2009 SAMSUNG Electronics * Minkyu Kang * Jaehoon Chung - * Portions Copyright 2011-2012 NVIDIA Corporation + * Portions Copyright 2011-2013 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,44 +29,14 @@ #include #include -/* support 4 mmc hosts */ -struct mmc mmc_dev[4]; -struct mmc_host mmc_host[4]; +DECLARE_GLOBAL_DATA_PTR; +struct mmc mmc_dev[MAX_HOSTS]; +struct mmc_host mmc_host[MAX_HOSTS]; -/** - * Get the host address and peripheral ID for a device. Devices are numbered - * from 0 to 3. - * - * @param host Structure to fill in (base, reg, mmc_id) - * @param dev_index Device index (0-3) - */ -static void tegra_get_setup(struct mmc_host *host, int dev_index) -{ - debug("tegra_get_setup: dev_index = %d\n", dev_index); - - switch (dev_index) { - case 1: - host->base = TEGRA_SDMMC3_BASE; - host->mmc_id = PERIPH_ID_SDMMC3; - break; - case 2: - host->base = TEGRA_SDMMC2_BASE; - host->mmc_id = PERIPH_ID_SDMMC2; - break; - case 3: - host->base = TEGRA_SDMMC1_BASE; - host->mmc_id = PERIPH_ID_SDMMC1; - break; - case 0: - default: - host->base = TEGRA_SDMMC4_BASE; - host->mmc_id = PERIPH_ID_SDMMC4; - break; - } - - host->reg = (struct tegra_mmc *)host->base; -} +#ifndef CONFIG_OF_CONTROL +#error "Please enable device tree support to use this driver" +#endif static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data, struct bounce_buffer *bbstate) @@ -518,41 +489,43 @@ int tegra_mmc_getcd(struct mmc *mmc) debug("tegra_mmc_getcd called\n"); - if (host->cd_gpio >= 0) - return !gpio_get_value(host->cd_gpio); + if (fdt_gpio_isvalid(&host->cd_gpio)) + return fdtdec_get_gpio(&host->cd_gpio); return 1; } -int tegra_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio) +static int do_mmc_init(int dev_index) { struct mmc_host *host; char gpusage[12]; /* "SD/MMCn PWR" or "SD/MMCn CD" */ struct mmc *mmc; - debug(" tegra_mmc_init: index %d, bus width %d " - "pwr_gpio %d cd_gpio %d\n", - dev_index, bus_width, pwr_gpio, cd_gpio); - + /* DT should have been read & host config filled in */ host = &mmc_host[dev_index]; + if (!host->enabled) + return -1; + + debug(" do_mmc_init: index %d, bus width %d " + "pwr_gpio %d cd_gpio %d\n", + dev_index, host->width, + host->pwr_gpio.gpio, host->cd_gpio.gpio); host->clock = 0; - host->pwr_gpio = pwr_gpio; - host->cd_gpio = cd_gpio; - tegra_get_setup(host, dev_index); - clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000); - if (host->pwr_gpio >= 0) { + if (fdt_gpio_isvalid(&host->pwr_gpio)) { sprintf(gpusage, "SD/MMC%d PWR", dev_index); - gpio_request(host->pwr_gpio, gpusage); - gpio_direction_output(host->pwr_gpio, 1); + gpio_request(host->pwr_gpio.gpio, gpusage); + gpio_direction_output(host->pwr_gpio.gpio, 1); + debug(" Power GPIO name = %s\n", host->pwr_gpio.name); } - if (host->cd_gpio >= 0) { + if (fdt_gpio_isvalid(&host->cd_gpio)) { sprintf(gpusage, "SD/MMC%d CD", dev_index); - gpio_request(host->cd_gpio, gpusage); - gpio_direction_input(host->cd_gpio); + gpio_request(host->cd_gpio.gpio, gpusage); + gpio_direction_input(host->cd_gpio.gpio); + debug(" CD GPIO name = %s\n", host->cd_gpio.name); } mmc = &mmc_dev[dev_index]; @@ -567,9 +540,9 @@ int tegra_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio) mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; mmc->host_caps = 0; - if (bus_width == 8) + if (host->width == 8) mmc->host_caps |= MMC_MODE_8BIT; - if (bus_width >= 4) + if (host->width >= 4) mmc->host_caps |= MMC_MODE_4BIT; mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; @@ -578,8 +551,6 @@ int tegra_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio) * low-speed SDIO card frequency (actually 400KHz) * max freq is highest HS eMMC clock as per the SD/MMC spec * (actually 52MHz) - * Both of these are the closest equivalents w/216MHz source - * clock and Tegra SDMMC divisors. */ mmc->f_min = 375000; mmc->f_max = 48000000; @@ -588,3 +559,95 @@ int tegra_mmc_init(int dev_index, int bus_width, int pwr_gpio, int cd_gpio) return 0; } + +/** + * Get the host address and peripheral ID for a node. + * + * @param blob fdt blob + * @param node Device index (0-3) + * @param host Structure to fill in (reg, width, mmc_id) + */ +static int mmc_get_config(const void *blob, int node, struct mmc_host *host) +{ + debug("%s: node = %d\n", __func__, node); + + host->enabled = fdtdec_get_is_enabled(blob, node); + + host->reg = (struct tegra_mmc *)fdtdec_get_addr(blob, node, "reg"); + if ((fdt_addr_t)host->reg == FDT_ADDR_T_NONE) { + debug("%s: no sdmmc base reg info found\n", __func__); + return -FDT_ERR_NOTFOUND; + } + + host->mmc_id = clock_decode_periph_id(blob, node); + if (host->mmc_id == PERIPH_ID_NONE) { + debug("%s: could not decode periph id\n", __func__); + return -FDT_ERR_NOTFOUND; + } + + /* + * NOTE: mmc->bus_width is determined by mmc.c dynamically. + * TBD: Override it with this value? + */ + host->width = fdtdec_get_int(blob, node, "bus-width", 0); + if (!host->width) + debug("%s: no sdmmc width found\n", __func__); + + /* These GPIOs are optional */ + fdtdec_decode_gpio(blob, node, "cd-gpios", &host->cd_gpio); + fdtdec_decode_gpio(blob, node, "wp-gpios", &host->wp_gpio); + fdtdec_decode_gpio(blob, node, "power-gpios", &host->pwr_gpio); + + debug("%s: found controller at %p, width = %d, periph_id = %d\n", + __func__, host->reg, host->width, host->mmc_id); + return 0; +} + +/* + * Process a list of nodes, adding them to our list of SDMMC ports. + * + * @param blob fdt blob + * @param node_list list of nodes to process (any <=0 are ignored) + * @param count number of nodes to process + * @return 0 if ok, -1 on error + */ +static int process_nodes(const void *blob, int node_list[], int count) +{ + struct mmc_host *host; + int i, node; + + debug("%s: count = %d\n", __func__, count); + + /* build mmc_host[] for each controller */ + for (i = 0; i < count; i++) { + node = node_list[i]; + if (node <= 0) + continue; + + host = &mmc_host[i]; + host->id = i; + + if (mmc_get_config(blob, node, host)) { + printf("%s: failed to decode dev %d\n", __func__, i); + return -1; + } + do_mmc_init(i); + } + return 0; +} + +void tegra_mmc_init(void) +{ + int node_list[MAX_HOSTS], count; + const void *blob = gd->fdt_blob; + debug("%s entry\n", __func__); + + count = fdtdec_find_aliases_for_id(blob, "sdhci", + COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, MAX_HOSTS); + debug("%s: count of sdhci nodes is %d\n", __func__, count); + + if (process_nodes(blob, node_list, count)) { + printf("%s: Error processing mmc node(s)!\n", __func__); + return; + } +} diff --git a/include/fdtdec.h b/include/fdtdec.h index c7a92d553e..32730d2063 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -71,6 +71,7 @@ enum fdt_compat_id { COMPAT_NVIDIA_TEGRA20_NAND, /* Tegra2 NAND controller */ COMPAT_NVIDIA_TEGRA20_PWM, /* Tegra 2 PWM controller */ COMPAT_NVIDIA_TEGRA20_DC, /* Tegra 2 Display controller */ + COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra SDMMC controller */ COMPAT_NVIDIA_TEGRA20_SFLASH, /* Tegra 2 SPI flash controller */ COMPAT_NVIDIA_TEGRA20_SLINK, /* Tegra 2 SPI SLINK controller */ COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 7c7fc833a6..000130f932 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -46,6 +46,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"), COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"), COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"), + COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"), COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"), COMPAT(SMSC_LAN9215, "smsc,lan9215"), From 73bb24439441d4a52e031c81f32a460ceab15421 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 21 Feb 2013 12:40:29 +0000 Subject: [PATCH 16/39] Tegra: fdt: Remove memreserve line from Cardhu/Seaboard DT files Not used, and wrong in Cardhu's case Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- board/nvidia/dts/tegra20-seaboard.dts | 1 - board/nvidia/dts/tegra30-cardhu.dts | 1 - 2 files changed, 2 deletions(-) diff --git a/board/nvidia/dts/tegra20-seaboard.dts b/board/nvidia/dts/tegra20-seaboard.dts index 12cb0bc780..c0e2e1e5fd 100644 --- a/board/nvidia/dts/tegra20-seaboard.dts +++ b/board/nvidia/dts/tegra20-seaboard.dts @@ -1,6 +1,5 @@ /dts-v1/; -/memreserve/ 0x1c000000 0x04000000; #include "tegra20.dtsi" / { diff --git a/board/nvidia/dts/tegra30-cardhu.dts b/board/nvidia/dts/tegra30-cardhu.dts index 8ad1fb70ef..778e513f8e 100644 --- a/board/nvidia/dts/tegra30-cardhu.dts +++ b/board/nvidia/dts/tegra30-cardhu.dts @@ -1,6 +1,5 @@ /dts-v1/; -/memreserve/ 0x1c000000 0x04000000; #include "tegra30.dtsi" / { From 527519ae69cdde6386754015f986f99604f2c9a7 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 21 Feb 2013 13:33:23 +0000 Subject: [PATCH 17/39] Tegra30: fdt: Sync DT nodes with kernel DT files (I2C, SPI, GPIO, clock) Minor edits to clock, apbdma and SPI, make I2C match kernel DT, and add gpio Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/dts/tegra30.dtsi | 90 ++++++++++++++++++----------- board/nvidia/dts/tegra30-cardhu.dts | 5 ++ 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index 561c617f4d..9483e801f6 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -3,8 +3,8 @@ / { compatible = "nvidia,tegra30"; - tegra_car: clock@60006000 { - compatible = "nvidia,tegra30-car", "nvidia,tegra20-car"; + tegra_car: clock { + compatible = "nvidia,tegra30-car"; reg = <0x60006000 0x1000>; #clock-cells = <1>; }; @@ -44,51 +44,79 @@ 0 141 0x04 0 142 0x04 0 143 0x04>; + clocks = <&tegra_car 34>; + }; + + gpio: gpio { + compatible = "nvidia,tegra30-gpio"; + reg = <0x6000d000 0x1000>; + interrupts = <0 32 0x04 + 0 33 0x04 + 0 34 0x04 + 0 35 0x04 + 0 55 0x04 + 0 87 0x04 + 0 89 0x04 + 0 125 0x04>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; }; i2c@7000c000 { + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000c000 0x100>; + interrupts = <0 38 0x04>; #address-cells = <1>; #size-cells = <0>; - compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; - reg = <0x7000C000 0x100>; - /* PERIPH_ID_I2C1, CLK_M */ - clocks = <&tegra_car 12>; + clocks = <&tegra_car 12>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; + status = "disabled"; }; i2c@7000c400 { + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000c400 0x100>; + interrupts = <0 84 0x04>; #address-cells = <1>; #size-cells = <0>; - compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; - reg = <0x7000C400 0x100>; - /* PERIPH_ID_I2C2, CLK_M */ - clocks = <&tegra_car 54>; + clocks = <&tegra_car 54>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; + status = "disabled"; }; i2c@7000c500 { + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000c500 0x100>; + interrupts = <0 92 0x04>; #address-cells = <1>; #size-cells = <0>; - compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; - reg = <0x7000C500 0x100>; - /* PERIPH_ID_I2C3, CLK_M */ - clocks = <&tegra_car 67>; + clocks = <&tegra_car 67>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; + status = "disabled"; }; i2c@7000c700 { + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000c700 0x100>; + interrupts = <0 120 0x04>; #address-cells = <1>; #size-cells = <0>; - compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; - reg = <0x7000C700 0x100>; - /* PERIPH_ID_I2C4, CLK_M */ - clocks = <&tegra_car 103>; + clocks = <&tegra_car 103>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; + status = "disabled"; }; i2c@7000d000 { + compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; + reg = <0x7000d000 0x100>; + interrupts = <0 53 0x04>; #address-cells = <1>; #size-cells = <0>; - compatible = "nvidia,tegra30-i2c", "nvidia,tegra20-i2c"; - reg = <0x7000D000 0x100>; - /* PERIPH_ID_I2C_DVC, CLK_M */ - clocks = <&tegra_car 47>; + clocks = <&tegra_car 47>, <&tegra_car 182>; + clock-names = "div-clk", "fast-clk"; + status = "disabled"; }; spi@7000d400 { @@ -98,9 +126,8 @@ nvidia,dma-request-selector = <&apbdma 15>; #address-cells = <1>; #size-cells = <0>; - status = "disabled"; - /* PERIPH_ID_SBC1, PLLP_OUT0 */ clocks = <&tegra_car 41>; + status = "disabled"; }; spi@7000d600 { @@ -110,9 +137,8 @@ nvidia,dma-request-selector = <&apbdma 16>; #address-cells = <1>; #size-cells = <0>; - status = "disabled"; - /* PERIPH_ID_SBC2, PLLP_OUT0 */ clocks = <&tegra_car 44>; + status = "disabled"; }; spi@7000d800 { @@ -122,9 +148,8 @@ nvidia,dma-request-selector = <&apbdma 17>; #address-cells = <1>; #size-cells = <0>; - status = "disabled"; - /* PERIPH_ID_SBC3, PLLP_OUT0 */ clocks = <&tegra_car 46>; + status = "disabled"; }; spi@7000da00 { @@ -134,9 +159,8 @@ nvidia,dma-request-selector = <&apbdma 18>; #address-cells = <1>; #size-cells = <0>; - status = "disabled"; - /* PERIPH_ID_SBC4, PLLP_OUT0 */ clocks = <&tegra_car 68>; + status = "disabled"; }; spi@7000dc00 { @@ -146,9 +170,8 @@ nvidia,dma-request-selector = <&apbdma 27>; #address-cells = <1>; #size-cells = <0>; - status = "disabled"; - /* PERIPH_ID_SBC5, PLLP_OUT0 */ clocks = <&tegra_car 104>; + status = "disabled"; }; spi@7000de00 { @@ -158,8 +181,7 @@ nvidia,dma-request-selector = <&apbdma 28>; #address-cells = <1>; #size-cells = <0>; - status = "disabled"; - /* PERIPH_ID_SBC6, PLLP_OUT0 */ clocks = <&tegra_car 105>; + status = "disabled"; }; }; diff --git a/board/nvidia/dts/tegra30-cardhu.dts b/board/nvidia/dts/tegra30-cardhu.dts index 778e513f8e..48039c9b30 100644 --- a/board/nvidia/dts/tegra30-cardhu.dts +++ b/board/nvidia/dts/tegra30-cardhu.dts @@ -20,22 +20,27 @@ }; i2c@7000c000 { + status = "okay"; clock-frequency = <100000>; }; i2c@7000c400 { + status = "okay"; clock-frequency = <100000>; }; i2c@7000c500 { + status = "okay"; clock-frequency = <100000>; }; i2c@7000c700 { + status = "okay"; clock-frequency = <100000>; }; i2c@7000d000 { + status = "okay"; clock-frequency = <100000>; }; From 16bb08d19a5ecb9c3e90ab2394d7c5c40955ee60 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 28 Feb 2013 12:40:09 +0000 Subject: [PATCH 18/39] ARM: tegra: implement WAR for Tegra114 CPU reset vector A Tegra114 HW bug prevents the main CPU vector from being modified under certain circumstances. Tegra114 A01P and later with a patched boot ROM set the CPU reset vector to 0x4003fffc (end of IRAM). This allows placing an arbitrary jump instruction at that location, in order to redirect to the desired reset vector location. Modify Tegra114's start_cpu() to make use of this feature. This allows CPUs with the patched boot ROM to boot. Based-on-work-by: Jimmy Zhang . Signed-off-by: Stephen Warren Signed-off-by: Tom Warren --- arch/arm/cpu/arm720t/tegra114/cpu.c | 36 +++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/arch/arm/cpu/arm720t/tegra114/cpu.c b/arch/arm/cpu/arm720t/tegra114/cpu.c index 0b2157a0df..6a94179d4a 100644 --- a/arch/arm/cpu/arm720t/tegra114/cpu.c +++ b/arch/arm/cpu/arm720t/tegra114/cpu.c @@ -270,6 +270,8 @@ void powerup_cpus(void) void start_cpu(u32 reset_vector) { + u32 imme, inst; + debug("start_cpu entry, reset_vector = %x\n", reset_vector); t114_init_clocks(); @@ -286,12 +288,38 @@ void start_cpu(u32 reset_vector) /* Take CPU(s) out of reset */ remove_cpu_resets(); + /* Set the entry point for CPU execution from reset */ + /* - * Set the entry point for CPU execution from reset, - * if it's a non-zero value. + * A01P with patched boot ROM; vector hard-coded to 0x4003fffc. + * See nvbug 1193357 for details. */ - if (reset_vector) - writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); + + /* mov r0, #lsb(reset_vector) */ + imme = reset_vector & 0xffff; + inst = imme & 0xfff; + inst |= ((imme >> 12) << 16); + inst |= 0xe3000000; + writel(inst, 0x4003fff0); + + /* movt r0, #msb(reset_vector) */ + imme = (reset_vector >> 16) & 0xffff; + inst = imme & 0xfff; + inst |= ((imme >> 12) << 16); + inst |= 0xe3400000; + writel(inst, 0x4003fff4); + + /* bx r0 */ + writel(0xe12fff10, 0x4003fff8); + + /* b -12 */ + imme = (u32)-20; + inst = (imme >> 2) & 0xffffff; + inst |= 0xea000000; + writel(inst, 0x4003fffc); + + /* Write to orignal location for compatibility */ + writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); /* If the CPU(s) don't already have power, power 'em up */ powerup_cpus(); From 7ea9c506d9390c03c61b21b222a18ede44b16f0a Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Tue, 26 Feb 2013 07:59:30 +0000 Subject: [PATCH 19/39] Tegra: Add twarren as maintainer for Tegra30 and Tegra114 SoCs Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index e792a8b4f6..059b4879b3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -976,6 +976,8 @@ Tom Warren harmony Tegra20 (ARM7 & A9 Dual Core) seaboard Tegra20 (ARM7 & A9 Dual Core) + cardhu Tegra30 (ARM7 & A9 Quad Core) + dalmore Tegra114 (ARM7 & A15 Quad Core) Tom Warren Stephen Warren From bfcf46db6340f202ecfd200252f9e3295a392696 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Tue, 26 Feb 2013 12:18:48 +0000 Subject: [PATCH 20/39] Tegra: Remove unused CONFIG_SYS_CPU_OSC_FREQUENCY define This wasn't used anywhere in any Tegra build. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- include/configs/tegra-common.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h index 4a656bb51b..80c846ce9d 100644 --- a/include/configs/tegra-common.h +++ b/include/configs/tegra-common.h @@ -21,8 +21,8 @@ * MA 02111-1307 USA */ -#ifndef __TEGRA_COMMON_H -#define __TEGRA_COMMON_H +#ifndef _TEGRA_COMMON_H_ +#define _TEGRA_COMMON_H_ #include #include @@ -56,10 +56,8 @@ #define CONFIG_SYS_MALLOC_LEN (4 << 20) /* 4MB */ /* - * PllX Configuration + * NS16550 Configuration */ -#define CONFIG_SYS_CPU_OSC_FREQUENCY 1000000 /* Set CPU clock to 1GHz */ - #define CONFIG_SYS_NS16550 #define CONFIG_SYS_NS16550_SERIAL #define CONFIG_SYS_NS16550_REG_SIZE (-4) From 19a970af28b7835ebabd61f1e09d623690b6feef Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Wed, 27 Feb 2013 05:52:52 +0000 Subject: [PATCH 21/39] Tegra114: fdt: Sync DT nodes with kernel DT files (GPIO, tegra_car) Minor edit to tegra_car node, add gpio node. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/dts/tegra114.dtsi | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index f0f82de012..dfeac53f72 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -11,12 +11,29 @@ i2c4 = "/i2c@7000c700"; }; - tegra_car: clock@60006000 { + tegra_car: clock { compatible = "nvidia,tegra114-car"; reg = <0x60006000 0x1000>; #clock-cells = <1>; }; + gpio: gpio { + compatible = "nvidia,tegra114-gpio", "nvidia,tegra30-gpio"; + reg = <0x6000d000 0x1000>; + interrupts = <0 32 0x04 + 0 33 0x04 + 0 34 0x04 + 0 35 0x04 + 0 55 0x04 + 0 87 0x04 + 0 89 0x04 + 0 125 0x04>; + #gpio-cells = <2>; + gpio-controller; + #interrupt-cells = <2>; + interrupt-controller; + }; + i2c@7000c000 { compatible = "nvidia,tegra114-i2c"; reg = <0x7000c000 0x100>; From bb638bb756b91a781d056d3b89cbd6dd562eabca Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Thu, 28 Feb 2013 06:30:03 +0000 Subject: [PATCH 22/39] Tegra30: Cardhu: Remove unneeded cardhu.c.mmc file This was an older debug/developmental file that got added accidentally. Not needed/used in any Cardhu build. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- board/nvidia/cardhu/cardhu.c.mmc | 151 ------------------------------- 1 file changed, 151 deletions(-) delete mode 100644 board/nvidia/cardhu/cardhu.c.mmc diff --git a/board/nvidia/cardhu/cardhu.c.mmc b/board/nvidia/cardhu/cardhu.c.mmc deleted file mode 100644 index 9e83b6fc00..0000000000 --- a/board/nvidia/cardhu/cardhu.c.mmc +++ /dev/null @@ -1,151 +0,0 @@ -/* - * (C) Copyright 2010-2012 - * NVIDIA Corporation - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include "pinmux-config-cardhu.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Routine: pinmux_init - * Description: Do individual peripheral pinmux configs - */ -void pinmux_init(void) -{ - pinmux_config_table(tegra3_pinmux_common, - ARRAY_SIZE(tegra3_pinmux_common)); - - pinmux_config_table(unused_pins_lowpower, - ARRAY_SIZE(unused_pins_lowpower)); -} - -#if defined(CONFIG_MMC) -/* - * Routine: pin_mux_mmc - * Description: setup the pin muxes/tristate values for the SDMMC(s) - */ -static void pin_mux_mmc(void) -{ -} - -/* Do I2C/PMU writes to bring up SD card bus power */ -static void board_sdmmc_voltage_init(void) -{ - uchar reg, data_buffer[1]; - int i; - - i2c_set_bus_num(0); /* PMU is on bus 0 */ - - data_buffer[0] = 0x65; - reg = 0x32; - - for (i = 0; i < MAX_I2C_RETRY; ++i) { - if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) - udelay(100); - } - - data_buffer[0] = 0x09; - reg = 0x67; - - for (i = 0; i < MAX_I2C_RETRY; ++i) { - if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) - udelay(100); - } -} - -static void pad_init_mmc(struct tegra_mmc *reg) -{ - struct apb_misc_gp_ctlr *const gpc = - (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; - struct sdmmc_ctlr *const sdmmc = (struct sdmmc_ctlr *)reg; - u32 val, offset = (unsigned int)reg; - u32 padcfg, padmask; - - debug("%s: sdmmc address = %08x\n", __func__, (unsigned int)sdmmc); - - /* Set the pad drive strength for SDMMC1 or 3 only */ - if (offset != TEGRA_SDMMC1_BASE && offset != TEGRA_SDMMC3_BASE) { - debug("%s: settings are only valid for SDMMC1/SDMMC3!\n", - __func__); - return; - } - - /* Set pads as per T30 TRM, section 24.6.1.2 */ - padcfg = (GP_SDIOCFG_DRVUP_SLWF | GP_SDIOCFG_DRVDN_SLWR | \ - GP_SDIOCFG_DRVUP | GP_SDIOCFG_DRVDN); - padmask = 0x00000FFF; - if (offset == TEGRA_SDMMC1_BASE) { - val = readl(&gpc->sdio1cfg); - val &= padmask; - val |= padcfg; - writel(val, &gpc->sdio1cfg); - } else { /* SDMMC3 */ - val = readl(&gpc->sdio3cfg); - val &= padmask; - val |= padcfg; - writel(val, &gpc->sdio3cfg); - } - - val = readl(&sdmmc->sdmmc_sdmemcomp_pad_ctrl); - val &= 0xFFFFFFF0; - val |= MEMCOMP_PADCTRL_VREF; - writel(val, &sdmmc->sdmmc_sdmemcomp_pad_ctrl); - - val = readl(&sdmmc->sdmmc_auto_cal_config); - val &= 0xFFFF0000; - val |= AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET | AUTO_CAL_ENABLED; - writel(val, &sdmmc->sdmmc_auto_cal_config); -} - -/* this is a weak define that we are overriding */ -int board_mmc_init(bd_t *bd) -{ - debug("board_mmc_init called\n"); - - /* Turn on SD-card bus power */ - board_sdmmc_voltage_init(); - - /* Set up the SDMMC pads as per the TRM */ - pad_init_mmc((struct tegra_mmc *)TEGRA_SDMMC1_BASE); - - /* Enable muxes, etc. for SDMMC controllers */ - pin_mux_mmc(); - - /* init dev 0 (SDMMC4), ("HSMMC") with 8-bit bus */ - tegra_mmc_init(0, 8, -1, -1); - - /* init dev 1 (SDMMC0), ("SDIO") with 8-bit bus */ - tegra_mmc_init(1, 8, -1, -1); - - return 0; -} -#endif /* MMC */ From 8b7776b9f95d542d0e81357c4f8aa32f7bf466e5 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Fri, 1 Mar 2013 14:38:20 -0700 Subject: [PATCH 23/39] Tegra114: pinmux: Update pinmux tables & code, fix a bug w/SDMMC3 init Use the latest tables & code from our internal U-Boot repo. The SDMMC3_CD, CLK_LB_IN and CLK_LB_OUT offsets in the pingroup table were off by a few indices, causing the pinmux init code to write bad data to the PINMUX_AUX_ regs. This also enabled the lock bit, which made it impossible to reconfig the pads correctly for SDMMC3 (SD card on Dalmore) operation. Also fixes SPI_CS2_N, USB_VBUS_EN0, HDMI_CEC and UART2_RXD/TXD muxes. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/cpu/tegra114-common/pinmux.c | 214 +++++---- arch/arm/include/asm/arch-tegra114/pinmux.h | 146 ++---- board/nvidia/dalmore/dalmore.c | 3 + board/nvidia/dalmore/pinmux-config-dalmore.h | 463 ++++++++++++------- 4 files changed, 449 insertions(+), 377 deletions(-) diff --git a/arch/arm/cpu/tegra114-common/pinmux.c b/arch/arm/cpu/tegra114-common/pinmux.c index 52b3ec47aa..27b5f694fa 100644 --- a/arch/arm/cpu/tegra114-common/pinmux.c +++ b/arch/arm/cpu/tegra114-common/pinmux.c @@ -37,6 +37,7 @@ struct tegra_pingroup_desc { #define PMUX_OD_SHIFT 6 #define PMUX_LOCK_SHIFT 7 #define PMUX_IO_RESET_SHIFT 8 +#define PMUX_RCV_SEL_SHIFT 9 /* Convenient macro for defining pin group properties */ #define PIN(pg_name, vdd, f0, f1, f2, f3, iod) \ @@ -58,6 +59,10 @@ struct tegra_pingroup_desc { #define PINO(pg_name, vdd, f0, f1, f2, f3) \ PIN(pg_name, vdd, f0, f1, f2, f3, OUTPUT) +/* A pin group number which is not used */ +#define PIN_RESERVED \ + PIN(NONE, NONE, INVALID, INVALID, INVALID, INVALID, NONE) + const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { /* NAME VDD f0 f1 f2 f3 */ PINI(ULPI_DATA0, BB, SPI3, HSI, UARTA, ULPI), @@ -84,71 +89,71 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { PINI(SDMMC1_DAT2, SDMMC1, SDMMC1, PWM0, SPI4, UARTA), PINI(SDMMC1_DAT1, SDMMC1, SDMMC1, PWM1, SPI4, UARTA), PINI(SDMMC1_DAT0, SDMMC1, SDMMC1, RSVD2, SPI4, UARTA), - PINI(GPIO_PV2, BB, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(GPIO_PV3, BB, RSVD1, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, /* Reserved by t114: 0x3060 - 0x3064 */ + PIN_RESERVED, PINI(CLK2_OUT, SDMMC1, EXTPERIPH2, RSVD2, RSVD3, RSVD4), PINI(CLK2_REQ, SDMMC1, DAP, RSVD2, RSVD3, RSVD4), - PINO(LCD_PWR1, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_PWR2, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_SDIN, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_SDOUT, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_WR_N, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_CS0_N, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_DC0, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_SCK, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_PWR0, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_PCLK, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_DE, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_HSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_VSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D0, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D1, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D2, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D3, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D4, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D5, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D6, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D7, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D8, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D9, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D10, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D11, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D12, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D13, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D14, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D15, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D16, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D17, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D18, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D19, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D20, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D21, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D22, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_D23, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_CS1_N, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_M1, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINO(LCD_DC1, LCD, RSVD1, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, /* Reserved by t114: 0x3070 - 0x310c */ + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, PINI(HDMI_INT, LCD, RSVD1, RSVD2, RSVD3, RSVD4), PINI(DDC_SCL, LCD, I2C4, RSVD2, RSVD3, RSVD4), PINI(DDC_SDA, LCD, I2C4, RSVD2, RSVD3, RSVD4), - PINI(CRT_HSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(CRT_VSYNC, LCD, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D0, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D1, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D2, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D3, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D4, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D5, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D6, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D7, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D8, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D9, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D10, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_D11, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_PCLK, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_MCLK, VI, RSVD1, RSVD3, RSVD3, RSVD4), - PINI(VI_VSYNC, VI, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(VI_HSYNC, VI, RSVD1, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, /* Reserved by t114: 0x311c - 0x3160 */ + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, PINI(UART2_RXD, UART, UARTB, SPDIF, UARTA, SPI4), PINI(UART2_TXD, UART, UARTB, SPDIF, UARTA, SPI4), PINI(UART2_RTS_N, UART, UARTA, UARTB, RSVD3, SPI4), @@ -220,7 +225,7 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { PINI(SDMMC4_DAT5, SDMMC4, SDMMC4, SPI3, GMI, RSVD4), PINI(SDMMC4_DAT6, SDMMC4, SDMMC4, SPI3, GMI, RSVD4), PINI(SDMMC4_DAT7, SDMMC4, SDMMC4, RSVD2, GMI, RSVD4), - PINI(SDMMC4_RST_N, SDMMC4, RSVD1, RSVD2, RSVD3, SDMMC4), + PIN_RESERVED, /* Reserved by t114: 0x3280 */ PINI(CAM_MCLK, CAM, VI, VI_ALT1, VI_ALT2, RSVD4), PINI(GPIO_PCC1, CAM, I2S4, RSVD2, RSVD3, RSVD4), PINI(GPIO_PBB0, CAM, I2S4, VI, VI_ALT1, VI_ALT3), @@ -246,11 +251,11 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { PINI(KB_ROW8, SYS, KBC, RSVD2, RSVD3, UARTA), PINI(KB_ROW9, SYS, KBC, RSVD2, RSVD3, UARTA), PINI(KB_ROW10, SYS, KBC, RSVD2, RSVD3, UARTA), - PINI(KB_ROW11, SYS, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(KB_ROW12, SYS, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(KB_ROW13, SYS, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(KB_ROW14, SYS, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(KB_ROW15, SYS, RSVD1, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, /* Reserved by t114: 0x32e8 - 0x32f8 */ + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, PINI(KB_COL0, SYS, KBC, USB, SPI2, EMC_DLL), PINI(KB_COL1, SYS, KBC, RSVD2, SPI2, EMC_DLL), PINI(KB_COL2, SYS, KBC, RSVD2, SPI2, RSVD4), @@ -278,36 +283,46 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { PINI(DAP2_DIN, AUDIO, I2S1, HDA, RSVD3, RSVD4), PINI(DAP2_DOUT, AUDIO, I2S1, HDA, RSVD3, RSVD4), PINI(DAP2_SCLK, AUDIO, I2S1, HDA, RSVD3, RSVD4), - PINI(SPI2_MOSI, AUDIO, SPI6, CLDVFS, RSVD3, RSVD4), - PINI(SPI2_MISO, AUDIO, SPI6, RSVD2, RSVD3, RSVD4), - PINI(SPI2_CS0_N, AUDIO, SPI6, SPI1, RSVD3, RSVD4), - PINI(SPI2_SCK, AUDIO, SPI6, CLDVFS, RSVD3, RSVD4), - PINI(SPI1_MOSI, AUDIO, RSVD1, SPI1, SPI2, DAP2), - PINI(SPI1_SCK, AUDIO, RSVD1, SPI1, SPI2, RSVD4), - PINI(SPI1_CS0_N, AUDIO, SPI6, SPI1, SPI2, RSVD4), - PINI(SPI1_MISO, AUDIO, RSVD1, SPI1, SPI2, RSVD4), - PINI(SPI2_CS1_N, AUDIO, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(SPI2_CS2_N, AUDIO, RSVD1, RSVD2, RSVD3, RSVD4), + PINI(DVFS_PWM, AUDIO, SPI6, CLDVFS, RSVD3, RSVD4), + PINI(GPIO_X1_AUD, AUDIO, SPI6, RSVD2, RSVD3, RSVD4), + PINI(GPIO_X3_AUD, AUDIO, SPI6, SPI1, RSVD3, RSVD4), + PINI(DVFS_CLK, AUDIO, SPI6, CLDVFS, RSVD3, RSVD4), + PINI(GPIO_X4_AUD, AUDIO, RSVD1, SPI1, SPI2, DAP2), + PINI(GPIO_X5_AUD, AUDIO, RSVD1, SPI1, SPI2, RSVD4), + PINI(GPIO_X6_AUD, AUDIO, SPI6, SPI1, SPI2, RSVD4), + PINI(GPIO_X7_AUD, AUDIO, RSVD1, SPI1, SPI2, RSVD4), + PIN_RESERVED, /* Reserved by t114: 0x3388 - 0x338c */ + PIN_RESERVED, PINI(SDMMC3_CLK, SDMMC3, SDMMC3, RSVD2, RSVD3, SPI3), PINI(SDMMC3_CMD, SDMMC3, SDMMC3, PWM3, UARTA, SPI3), PINI(SDMMC3_DAT0, SDMMC3, SDMMC3, RSVD2, RSVD3, SPI3), PINI(SDMMC3_DAT1, SDMMC3, SDMMC3, PWM2, UARTA, SPI3), PINI(SDMMC3_DAT2, SDMMC3, SDMMC3, PWM1, DISPA, SPI3), PINI(SDMMC3_DAT3, SDMMC3, SDMMC3, PWM0, DISPB, SPI3), - PINI(SDMMC3_DAT4, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(SDMMC3_DAT5, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(SDMMC3_DAT6, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4), - PINI(SDMMC3_DAT7, SDMMC3, RSVD1, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, /* Reserved by t114: 0x33a8 - 0x33dc */ + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, PINI(HDMI_CEC, SYS, CEC, SDMMC3, RSVD3, SOC), PINI(SDMMC1_WP_N, SDMMC1, SDMMC1, CLK12, SPI4, UARTA), - PINI(SDMMC3_CD_N, SDMMC3, SDMMC3, OWR, RSVD3, RSVD4), - PINI(SPI1_CS1_N, AUDIO, SPI6, RSVD2, SPI2, I2C1), - PINI(SPI1_CS2_N, AUDIO, SPI6, SPI1, SPI2, I2C1), - PINI(USB_VBUS_EN0, SYS, USB, RSVD2, RSVD3, RSVD4), - PINI(USB_VBUS_EN1, SYS, USB, RSVD2, RSVD3, RSVD4), + PINI(SDMMC3_CD_N, SYS, SDMMC3, OWR, RSVD3, RSVD4), + PINI(GPIO_W2_AUD, AUDIO, SPI6, RSVD2, SPI2, I2C1), + PINI(GPIO_W3_AUD, AUDIO, SPI6, SPI1, SPI2, I2C1), + PINI(USB_VBUS_EN0, LCD, USB, RSVD2, RSVD3, RSVD4), + PINI(USB_VBUS_EN1, LCD, USB, RSVD2, RSVD3, RSVD4), PINI(SDMMC3_CLK_LB_IN, SDMMC3, SDMMC3, RSVD2, RSVD3, RSVD4), - PINO(SDMMC3_CLK_LB_OUT, SDMMC3, SDMMC3, RSVD2, RSVD3, RSVD4), - PINO(NAND_GMI_CLK_LB, GMI, SDMMC2, NAND, GMI, RSVD4), + PINI(SDMMC3_CLK_LB_OUT, SDMMC3, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, /* Reserved by t114: 0x3404 */ PINO(RESET_OUT_N, SYS, RSVD1, RSVD2, RSVD3, RESET_OUT_N), }; @@ -484,6 +499,30 @@ static int pinmux_set_ioreset(enum pmux_pingrp pin, return 0; } +static int pinmux_set_rcv_sel(enum pmux_pingrp pin, + enum pmux_pin_rcv_sel rcv_sel) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pin_rcv_sel = &pmt->pmt_ctl[pin]; + u32 reg; + + /* Error check on pin and rcv_sel */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_rcv_sel_isvalid(rcv_sel)); + + if (rcv_sel == PMUX_PIN_RCV_SEL_DEFAULT) + return 0; + + reg = readl(pin_rcv_sel); + reg &= ~(0x1 << PMUX_RCV_SEL_SHIFT); + if (rcv_sel == PMUX_PIN_RCV_SEL_HIGH) + reg |= (0x1 << PMUX_RCV_SEL_SHIFT); + writel(reg, pin_rcv_sel); + + return 0; +} + void pinmux_config_pingroup(struct pingroup_config *config) { enum pmux_pingrp pin = config->pingroup; @@ -495,6 +534,7 @@ void pinmux_config_pingroup(struct pingroup_config *config) pinmux_set_lock(pin, config->lock); pinmux_set_od(pin, config->od); pinmux_set_ioreset(pin, config->ioreset); + pinmux_set_rcv_sel(pin, config->rcv_sel); } void pinmux_config_table(struct pingroup_config *config, int len) diff --git a/arch/arm/include/asm/arch-tegra114/pinmux.h b/arch/arm/include/asm/arch-tegra114/pinmux.h index fd2293039d..53905cb8e9 100644 --- a/arch/arm/include/asm/arch-tegra114/pinmux.h +++ b/arch/arm/include/asm/arch-tegra114/pinmux.h @@ -50,72 +50,12 @@ enum pmux_pingrp { PINGRP_SDMMC1_DAT2, PINGRP_SDMMC1_DAT1, PINGRP_SDMMC1_DAT0, - PINGRP_GPIO_PV2, - PINGRP_GPIO_PV3, - PINGRP_CLK2_OUT, + PINGRP_CLK2_OUT = PINGRP_SDMMC1_DAT0 + 3, PINGRP_CLK2_REQ, - PINGRP_LCD_PWR1, - PINGRP_LCD_PWR2, - PINGRP_LCD_SDIN, - PINGRP_LCD_SDOUT, - PINGRP_LCD_WR_N, - PINGRP_LCD_CS0_N, - PINGRP_LCD_DC0, - PINGRP_LCD_SCK, - PINGRP_LCD_PWR0, - PINGRP_LCD_PCLK, - PINGRP_LCD_DE, - PINGRP_LCD_HSYNC, - PINGRP_LCD_VSYNC, - PINGRP_LCD_D0, - PINGRP_LCD_D1, - PINGRP_LCD_D2, - PINGRP_LCD_D3, - PINGRP_LCD_D4, - PINGRP_LCD_D5, - PINGRP_LCD_D6, - PINGRP_LCD_D7, - PINGRP_LCD_D8, - PINGRP_LCD_D9, - PINGRP_LCD_D10, - PINGRP_LCD_D11, - PINGRP_LCD_D12, - PINGRP_LCD_D13, - PINGRP_LCD_D14, - PINGRP_LCD_D15, - PINGRP_LCD_D16, - PINGRP_LCD_D17, - PINGRP_LCD_D18, - PINGRP_LCD_D19, - PINGRP_LCD_D20, - PINGRP_LCD_D21, - PINGRP_LCD_D22, - PINGRP_LCD_D23, - PINGRP_LCD_CS1_N, - PINGRP_LCD_M1, - PINGRP_LCD_DC1, - PINGRP_HDMI_INT, + PINGRP_HDMI_INT = PINGRP_CLK2_REQ + 41, PINGRP_DDC_SCL, PINGRP_DDC_SDA, - PINGRP_CRT_HSYNC, - PINGRP_CRT_VSYNC, - PINGRP_VI_D0, - PINGRP_VI_D1, - PINGRP_VI_D2, - PINGRP_VI_D3, - PINGRP_VI_D4, - PINGRP_VI_D5, - PINGRP_VI_D6, - PINGRP_VI_D7, - PINGRP_VI_D8, - PINGRP_VI_D9, - PINGRP_VI_D10, - PINGRP_VI_D11, - PINGRP_VI_PCLK, - PINGRP_VI_MCLK, - PINGRP_VI_VSYNC, - PINGRP_VI_HSYNC, - PINGRP_UART2_RXD, + PINGRP_UART2_RXD = PINGRP_DDC_SDA + 19, PINGRP_UART2_TXD, PINGRP_UART2_RTS_N, PINGRP_UART2_CTS_N, @@ -186,8 +126,7 @@ enum pmux_pingrp { PINGRP_SDMMC4_DAT5, PINGRP_SDMMC4_DAT6, PINGRP_SDMMC4_DAT7, - PINGRP_SDMMC4_RST_N, - PINGRP_CAM_MCLK, + PINGRP_CAM_MCLK = PINGRP_SDMMC4_DAT7 + 2, PINGRP_GPIO_PCC1, PINGRP_GPIO_PBB0, PINGRP_CAM_I2C_SCL, @@ -212,12 +151,7 @@ enum pmux_pingrp { PINGRP_KB_ROW8, PINGRP_KB_ROW9, PINGRP_KB_ROW10, - PINGRP_KB_ROW11, - PINGRP_KB_ROW12, - PINGRP_KB_ROW13, - PINGRP_KB_ROW14, - PINGRP_KB_ROW15, - PINGRP_KB_COL0, + PINGRP_KB_COL0 = PINGRP_KB_ROW10 + 6, PINGRP_KB_COL1, PINGRP_KB_COL2, PINGRP_KB_COL3, @@ -244,47 +178,30 @@ enum pmux_pingrp { PINGRP_DAP2_DIN, PINGRP_DAP2_DOUT, PINGRP_DAP2_SCLK, - PINGRP_SPI2_MOSI, - PINGRP_SPI2_MISO, - PINGRP_SPI2_CS0_N, - PINGRP_SPI2_SCK, - PINGRP_SPI1_MOSI, - PINGRP_SPI1_SCK, - PINGRP_SPI1_CS0_N, - PINGRP_SPI1_MISO, - PINGRP_SPI2_CS1_N, - PINGRP_SPI2_CS2_N, - PINGRP_SDMMC3_CLK, + PINGRP_DVFS_PWM, + PINGRP_GPIO_X1_AUD, + PINGRP_GPIO_X3_AUD, + PINGRP_DVFS_CLK, + PINGRP_GPIO_X4_AUD, + PINGRP_GPIO_X5_AUD, + PINGRP_GPIO_X6_AUD, + PINGRP_GPIO_X7_AUD, + PINGRP_SDMMC3_CLK = PINGRP_GPIO_X7_AUD + 3, PINGRP_SDMMC3_CMD, PINGRP_SDMMC3_DAT0, PINGRP_SDMMC3_DAT1, PINGRP_SDMMC3_DAT2, PINGRP_SDMMC3_DAT3, - PINGRP_SDMMC3_DAT4, - PINGRP_SDMMC3_DAT5, - PINGRP_SDMMC3_DAT6, - PINGRP_SDMMC3_DAT7, - PINGRP_PEX_L0_PRSNT_N, - PINGRP_PEX_L0_RST_N, - PINGRP_PEX_L0_CLKREQ_N, - PINGRP_PEX_WAKE_N, - PINGRP_PEX_L1_PRSNT_N, - PINGRP_PEX_L1_RST_N, - PINGRP_PEX_L1_CLKREQ_N, - PINGRP_PEX_L2_PRSNT_N, - PINGRP_PEX_L2_RST_N, - PINGRP_PEX_L2_CLKREQ_N, - PINGRP_HDMI_CEC, /* offset 0x33e0 */ + PINGRP_HDMI_CEC = PINGRP_SDMMC3_DAT3 + 15, /* offset 0x33e0 */ PINGRP_SDMMC1_WP_N, PINGRP_SDMMC3_CD_N, - PINGRP_SPI1_CS1_N, - PINGRP_SPI1_CS2_N, - PINGRP_USB_VBUS_EN0, /* offset 0x33f4 */ + PINGRP_GPIO_W2_AUD, + PINGRP_GPIO_W3_AUD, + PINGRP_USB_VBUS_EN0, /* offset 0x33f4 */ PINGRP_USB_VBUS_EN1, PINGRP_SDMMC3_CLK_LB_IN, PINGRP_SDMMC3_CLK_LB_OUT, - PINGRP_NAND_GMI_CLK_LB, - PINGRP_RESET_OUT_N, + PINGRP_RESET_OUT_N = PINGRP_SDMMC3_CLK_LB_OUT + 2, PINGRP_COUNT, }; @@ -304,23 +221,16 @@ enum pdrive_pingrp { PDRIVE_PINGROUP_DAP3, PDRIVE_PINGROUP_DAP4, PDRIVE_PINGROUP_DBG, - PDRIVE_PINGROUP_LCD1, - PDRIVE_PINGROUP_LCD2, - PDRIVE_PINGROUP_SDIO2, PDRIVE_PINGROUP_SDIO3, PDRIVE_PINGROUP_SPI, PDRIVE_PINGROUP_UAA, PDRIVE_PINGROUP_UAB, PDRIVE_PINGROUP_UART2, PDRIVE_PINGROUP_UART3, - PDRIVE_PINGROUP_VI1 = 24, /* offset 0x8c8 */ PDRIVE_PINGROUP_SDIO1 = 33, /* offset 0x8ec */ PDRIVE_PINGROUP_CRT = 36, /* offset 0x8f8 */ PDRIVE_PINGROUP_DDC, PDRIVE_PINGROUP_GMA, - PDRIVE_PINGROUP_GMB, - PDRIVE_PINGROUP_GMC, - PDRIVE_PINGROUP_GMD, PDRIVE_PINGROUP_GME, PDRIVE_PINGROUP_GMF, PDRIVE_PINGROUP_GMG, @@ -401,6 +311,7 @@ enum pmux_func { PMUX_FUNC_VI, PMUX_FUNC_VI_SENSOR_CLK, PMUX_FUNC_XIO, + /* End of Tegra2 MUX selectors */ PMUX_FUNC_BLINK, PMUX_FUNC_CEC, PMUX_FUNC_CLK12, @@ -444,7 +355,7 @@ enum pmux_func { PMUX_FUNC_VGP4, PMUX_FUNC_VGP5, PMUX_FUNC_VGP6, - + /* End of Tegra3 MUX selectors */ PMUX_FUNC_USB, PMUX_FUNC_SOC, PMUX_FUNC_CPU, @@ -453,10 +364,12 @@ enum pmux_func { PMUX_FUNC_PMI, PMUX_FUNC_CLDVFS, PMUX_FUNC_RESET_OUT_N, + /* End of Tegra114 MUX selectors */ PMUX_FUNC_SAFE, PMUX_FUNC_MAX, + PMUX_FUNC_INVALID = 0x4000, PMUX_FUNC_RSVD1 = 0x8000, PMUX_FUNC_RSVD2 = 0x8001, PMUX_FUNC_RSVD3 = 0x8002, @@ -492,6 +405,7 @@ enum pmux_tristate { enum pmux_pin_io { PMUX_PIN_OUTPUT = 0, PMUX_PIN_INPUT = 1, + PMUX_PIN_NONE, }; /* return 1 if a pin_io_is in range */ #define pmux_pin_io_isvalid(io) (((io) >= PMUX_PIN_OUTPUT) && \ @@ -525,6 +439,16 @@ enum pmux_pin_ioreset { (((ioreset) >= PMUX_PIN_IO_RESET_DEFAULT) && \ ((ioreset) <= PMUX_PIN_IO_RESET_ENABLE)) +enum pmux_pin_rcv_sel { + PMUX_PIN_RCV_SEL_DEFAULT = 0, + PMUX_PIN_RCV_SEL_NORMAL, + PMUX_PIN_RCV_SEL_HIGH, +}; +/* return 1 if a pin_rcv_sel_is in range */ +#define pmux_pin_rcv_sel_isvalid(rcv_sel) \ + (((rcv_sel) >= PMUX_PIN_RCV_SEL_DEFAULT) && \ + ((rcv_sel) <= PMUX_PIN_RCV_SEL_HIGH)) + /* Available power domains used by pin groups */ enum pmux_vddio { PMUX_VDDIO_BB = 0, @@ -581,6 +505,8 @@ struct pingroup_config { enum pmux_pin_lock lock; /* lock enable/disable PMUX_PIN... */ enum pmux_pin_od od; /* open-drain or push-pull driver */ enum pmux_pin_ioreset ioreset; /* input/output reset PMUX_PIN... */ + enum pmux_pin_rcv_sel rcv_sel; /* select between High and Normal */ + /* VIL/VIH receivers */ }; /* Set a pin group to tristate */ diff --git a/board/nvidia/dalmore/dalmore.c b/board/nvidia/dalmore/dalmore.c index aca3c7d17b..2020a5f00d 100644 --- a/board/nvidia/dalmore/dalmore.c +++ b/board/nvidia/dalmore/dalmore.c @@ -24,6 +24,9 @@ */ void pinmux_init(void) { + pinmux_config_table(tegra114_pinmux_set_nontristate, + ARRAY_SIZE(tegra114_pinmux_set_nontristate)); + pinmux_config_table(tegra114_pinmux_common, ARRAY_SIZE(tegra114_pinmux_common)); diff --git a/board/nvidia/dalmore/pinmux-config-dalmore.h b/board/nvidia/dalmore/pinmux-config-dalmore.h index 3dd47da32d..d25881908d 100644 --- a/board/nvidia/dalmore/pinmux-config-dalmore.h +++ b/board/nvidia/dalmore/pinmux-config-dalmore.h @@ -17,7 +17,7 @@ #ifndef _PINMUX_CONFIG_DALMORE_H_ #define _PINMUX_CONFIG_DALMORE_H_ -#define DEFAULT_PINMUX(_pingroup, _mux, _pull, _tri, _io) \ +#define DEFAULT_PINMUX(_pingroup, _mux, _pull, _tri, _io) \ { \ .pingroup = PINGRP_##_pingroup, \ .func = PMUX_FUNC_##_mux, \ @@ -41,7 +41,19 @@ .ioreset = PMUX_PIN_IO_RESET_DEFAULT, \ } -#define LV_PINMUX(_pingroup, _mux, _pull, _tri, _io, _lock, _ioreset) \ +#define DDC_PINMUX(_pingroup, _mux, _pull, _tri, _io, _lock, _rcv_sel) \ + { \ + .pingroup = PINGRP_##_pingroup, \ + .func = PMUX_FUNC_##_mux, \ + .pull = PMUX_PULL_##_pull, \ + .tristate = PMUX_TRI_##_tri, \ + .io = PMUX_PIN_##_io, \ + .lock = PMUX_PIN_LOCK_##_lock, \ + .rcv_sel = PMUX_PIN_RCV_SEL_##_rcv_sel, \ + .ioreset = PMUX_PIN_IO_RESET_DEFAULT, \ + } + +#define VI_PINMUX(_pingroup, _mux, _pull, _tri, _io, _lock, _ioreset) \ { \ .pingroup = PINGRP_##_pingroup, \ .func = PMUX_FUNC_##_mux, \ @@ -50,200 +62,291 @@ .io = PMUX_PIN_##_io, \ .lock = PMUX_PIN_LOCK_##_lock, \ .od = PMUX_PIN_OD_DEFAULT, \ - .ioreset = PMUX_PIN_IO_RESET_##_ioreset \ + .ioreset = PMUX_PIN_IO_RESET_##_ioreset \ } +#define CEC_PINMUX(_pingroup, _mux, _pull, _tri, _io, _lock, _od) \ + { \ + .pingroup = PINGRP_##_pingroup, \ + .func = PMUX_FUNC_##_mux, \ + .pull = PMUX_PULL_##_pull, \ + .tristate = PMUX_TRI_##_tri, \ + .io = PMUX_PIN_##_io, \ + .lock = PMUX_PIN_LOCK_##_lock, \ + .od = PMUX_PIN_OD_##_od, \ + .ioreset = PMUX_PIN_IO_RESET_DEFAULT, \ + } + +#define USB_PINMUX CEC_PINMUX + static struct pingroup_config tegra114_pinmux_common[] = { - /* SDMMC1 pinmux */ - DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC1_CMD, SDMMC1, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC1_DAT3, SDMMC1, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC1_DAT2, SDMMC1, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC1_DAT1, SDMMC1, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC1_DAT0, SDMMC1, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC1_WP_N, SDMMC1, UP, NORMAL, INPUT), + /* EXTPERIPH1 pinmux */ + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT), - /* SDMMC3 pinmux */ - DEFAULT_PINMUX(SDMMC3_CLK, SDMMC3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_CLK_LB_IN, SDMMC3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_CLK_LB_OUT, SDMMC3, NORMAL, NORMAL, OUTPUT), + /* I2S0 pinmux */ + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_DAT0, SDMMC3, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_DAT1, SDMMC3, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_DAT2, SDMMC3, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_DAT3, SDMMC3, UP, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC3_CD_N, SDMMC3, UP, NORMAL, INPUT), + /* I2S1 pinmux */ + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), - /* SDMMC4 pinmux */ - LV_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_CMD, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT0, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT1, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT2, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT3, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT4, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT5, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT6, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_DAT7, SDMMC4, UP, NORMAL, INPUT, DISABLE, DISABLE), - LV_PINMUX(SDMMC4_RST_N, RSVD1, DOWN, NORMAL, INPUT, DISABLE, DISABLE), + /* I2S3 pinmux */ + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), - /* I2C1 pinmux */ - I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), - I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + /* CLDVFS pinmux */ + DEFAULT_PINMUX(DVFS_PWM, CLDVFS, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DVFS_CLK, CLDVFS, NORMAL, NORMAL, OUTPUT), - /* I2C2 pinmux */ - I2C_PINMUX(GEN2_I2C_SCL, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), - I2C_PINMUX(GEN2_I2C_SDA, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + /* ULPI pinmux */ + DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA0, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA1, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA2, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA3, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA4, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA5, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA6, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA7, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, OUTPUT), /* I2C3 pinmux */ - I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), - I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + + /* VI pinmux */ + VI_PINMUX(CAM_MCLK, VI_ALT3, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), + + /* VI_ALT1 pinmux */ + VI_PINMUX(GPIO_PBB0, VI_ALT3, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), + + /* VGP4 pinmux */ + VI_PINMUX(GPIO_PBB4, VGP4, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), + + /* I2C2 pinmux */ + I2C_PINMUX(GEN2_I2C_SCL, I2C2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(GEN2_I2C_SDA, I2C2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + + /* UARTD pinmux */ + DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), + + /* SPI4 pinmux */ + DEFAULT_PINMUX(GMI_AD5, SPI4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD6, SPI4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD7, SPI4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD12, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_CS6_N, SPI4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_WR_N, SPI4, NORMAL, NORMAL, INPUT), + + /* PWM1 pinmux */ + DEFAULT_PINMUX(GMI_AD9, PWM1, NORMAL, NORMAL, OUTPUT), + + /* SOC pinmux */ + DEFAULT_PINMUX(GMI_CS1_N, SOC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_OE_N, SOC, NORMAL, TRISTATE, INPUT), + + /* EXTPERIPH2 pinmux */ + DEFAULT_PINMUX(CLK2_OUT, EXTPERIPH2, NORMAL, NORMAL, OUTPUT), + + /* SDMMC1 pinmux */ + DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_CMD, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT0, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT1, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT2, SDMMC1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT3, SDMMC1, UP, NORMAL, INPUT), + + /* SDMMC3 pinmux */ + DEFAULT_PINMUX(SDMMC3_CLK, SDMMC3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT0, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT1, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT2, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT3, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_CLK_LB_IN, SDMMC3, UP, TRISTATE, INPUT), + DEFAULT_PINMUX(SDMMC3_CLK_LB_OUT, SDMMC3, DOWN, NORMAL, INPUT), + + /* SDMMC4 pinmux */ + DEFAULT_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT0, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT1, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT2, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT3, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT4, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT5, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT6, SDMMC4, UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT7, SDMMC4, UP, NORMAL, INPUT), + + /* BLINK pinmux */ + DEFAULT_PINMUX(CLK_32K_OUT, BLINK, NORMAL, NORMAL, OUTPUT), + + /* KBC pinmux */ + DEFAULT_PINMUX(KB_COL0, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL1, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL2, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW0, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW1, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW2, KBC, UP, NORMAL, INPUT), + + /*Audio Codec*/ + DEFAULT_PINMUX(DAP3_DIN, RSVD1, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(DAP3_SCLK, RSVD1, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD1, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW7, RSVD1, UP, NORMAL, INPUT), + + /* UARTA pinmux */ + DEFAULT_PINMUX(KB_ROW10, UARTA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(KB_ROW9, UARTA, NORMAL, NORMAL, OUTPUT), + + /* I2CPWR pinmux (I2C5) */ + I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + + /* SYSCLK pinmux */ + DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, OUTPUT), + + /* RTCK pinmux */ + DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, INPUT), + + /* CLK pinmux */ + DEFAULT_PINMUX(CLK_32K_IN, CLK, NORMAL, TRISTATE, INPUT), + + /* PWRON pinmux */ + DEFAULT_PINMUX(CORE_PWR_REQ, PWRON, NORMAL, NORMAL, OUTPUT), + + /* CPU pinmux */ + DEFAULT_PINMUX(CPU_PWR_REQ, CPU, NORMAL, NORMAL, OUTPUT), + + /* PMI pinmux */ + DEFAULT_PINMUX(PWR_INT_N, PMI, NORMAL, TRISTATE, INPUT), + + /* RESET_OUT_N pinmux */ + DEFAULT_PINMUX(RESET_OUT_N, RESET_OUT_N, NORMAL, NORMAL, OUTPUT), + + /* EXTPERIPH3 pinmux */ + DEFAULT_PINMUX(CLK3_OUT, EXTPERIPH3, NORMAL, NORMAL, OUTPUT), + + /* I2C1 pinmux */ + I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + + /* UARTB pinmux */ + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + + /* IRDA pinmux */ + DEFAULT_PINMUX(UART2_RXD, UARTB, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART2_TXD, UARTB, NORMAL, NORMAL, OUTPUT), + + /* UARTC pinmux */ + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), + + /* OWR pinmux */ + DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT), + + /* CEC pinmux */ + CEC_PINMUX(HDMI_CEC, CEC, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), /* I2C4 pinmux */ - I2C_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), - I2C_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + DDC_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DISABLE, HIGH), + DDC_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DISABLE, HIGH), - /* Power I2C pinmux */ - I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), - I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + /* USB pinmux */ + USB_PINMUX(USB_VBUS_EN0, USB, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), - DEFAULT_PINMUX(ULPI_DATA0, UARTA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(ULPI_DATA1, UARTA, UP, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_DATA2, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_DATA3, UARTA, NORMAL, NORMAL, INPUT), - - DEFAULT_PINMUX(ULPI_DATA4, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_DATA5, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_DATA6, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_DATA7, UARTA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(ULPI_CLK, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(ULPI_DIR, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_NXT, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_STP, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(CLK2_OUT, EXTPERIPH2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(CLK2_REQ, DAP, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART2_RXD, UARTB, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART2_TXD, UARTB, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU0, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU1, RSVD1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU2, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU3, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU6, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(CLK3_OUT, EXTPERIPH3, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(CLK3_REQ, DEV3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_WP_N, GMI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_CS2_N, RSVD1, UP, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_AD8, PWM0, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GMI_AD10, NAND, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, UP, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB5, VGP5, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB6, VGP6, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, OUTPUT), - - /* KBC keys */ - DEFAULT_PINMUX(KB_ROW0, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW1, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW2, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW3, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW4, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW5, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW6, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW7, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW8, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW9, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW10, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL0, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL1, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL2, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL3, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL4, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL5, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL6, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL7, KBC, UP, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PV0, RSVD1, UP, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PV1, RSVD1, UP, NORMAL, INPUT), - - DEFAULT_PINMUX(CLK_32K_OUT, BLINK, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(CLK1_REQ, DAP, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPDIF_OUT, SPDIF, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), - - DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_CS0_N, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_CS1_N, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_CS2_N, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(HDMI_CEC, CEC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(HDMI_INT, RSVD1, NORMAL, TRISTATE, INPUT), - - /* GPIOs */ - /* SDMMC1 CD gpio */ - DEFAULT_PINMUX(GMI_IORDY, RSVD1, UP, NORMAL, INPUT), - - /* Touch RESET */ - DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, NORMAL, OUTPUT), - - /* Power rails GPIO */ - DEFAULT_PINMUX(SPI2_SCK, GMI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB4, VGP4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW8, KBC, UP, NORMAL, INPUT), + /* nct */ + DEFAULT_PINMUX(GPIO_X6_AUD, SPI6, UP, TRISTATE, INPUT), }; static struct pingroup_config unused_pins_lowpower[] = { - DEFAULT_PINMUX(GMI_CS0_N, NAND, UP, TRISTATE, OUTPUT), - DEFAULT_PINMUX(GMI_CS3_N, NAND, UP, TRISTATE, OUTPUT), - DEFAULT_PINMUX(GMI_CS4_N, NAND, UP, TRISTATE, OUTPUT), - DEFAULT_PINMUX(GMI_CS7_N, NAND, UP, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_AD0, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD1, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD2, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD3, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD4, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD5, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD6, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD7, NAND, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(GMI_AD9, PWM1, NORMAL, TRISTATE, OUTPUT), - DEFAULT_PINMUX(GMI_AD11, NAND, NORMAL, TRISTATE, OUTPUT), - DEFAULT_PINMUX(GMI_AD13, NAND, UP, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_WR_N, NAND, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CLK1_REQ, RSVD3, DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(USB_VBUS_EN1, RSVD3, DOWN, TRISTATE, OUTPUT), }; -#endif /* _PINMUX_CONFIG_DALMORE_H_ */ +/* Initially setting all used GPIO's to non-TRISTATE */ +static struct pingroup_config tegra114_pinmux_set_nontristate[] = { + DEFAULT_PINMUX(GPIO_X4_AUD, RSVD1, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_X5_AUD, RSVD1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_X6_AUD, RSVD3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_X7_AUD, RSVD1, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_W2_AUD, RSVD1, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_W3_AUD, SPI6, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_X1_AUD, RSVD3, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_X3_AUD, RSVD3, UP, NORMAL, INPUT), + + DEFAULT_PINMUX(DAP3_FS, I2S2, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV1, RSVD1, NORMAL, NORMAL, INPUT), + + DEFAULT_PINMUX(GPIO_PBB3, RSVD3, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB5, RSVD3, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB6, RSVD3, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB7, RSVD3, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PCC1, RSVD3, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC2, RSVD3, DOWN, NORMAL, INPUT), + + DEFAULT_PINMUX(GMI_AD0, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_AD1, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_AD10, GMI, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_AD11, GMI, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_AD12, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD13, GMI, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_AD2, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD3, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD8, GMI, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_ADV_N, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CLK, GMI, DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_CS0_N, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CS2_N, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CS3_N, GMI, UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_CS4_N, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_CS7_N, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_DQS, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_IORDY, GMI, UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_WP_N, GMI, UP, NORMAL, INPUT), + + DEFAULT_PINMUX(SDMMC1_WP_N, SPI4, UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(CLK2_REQ, RSVD3, NORMAL, NORMAL, OUTPUT), + + DEFAULT_PINMUX(KB_COL3, KBC, UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(KB_COL4, SDMMC3, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL5, KBC, UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL6, KBC, UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(KB_COL7, KBC, UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(KB_ROW3, KBC, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW4, KBC, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW6, KBC, DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW8, KBC, UP, NORMAL, INPUT), + + DEFAULT_PINMUX(CLK3_REQ, RSVD3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU4, RSVD3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, RSVD3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU6, RSVD3, NORMAL, NORMAL, INPUT), + + DEFAULT_PINMUX(HDMI_INT, RSVD1, DOWN, NORMAL, INPUT), + + DEFAULT_PINMUX(GMI_AD9, PWM1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(SPDIF_IN, USB, NORMAL, NORMAL, INPUT), + + DEFAULT_PINMUX(SDMMC3_CD_N, SDMMC3, UP, NORMAL, INPUT), +}; +#endif /* PINMUX_CONFIG_COMMON_H */ From 8ca79b2ff467bda3bc1cfe7fe566f0c1189881dc Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Wed, 6 Mar 2013 16:16:22 -0700 Subject: [PATCH 24/39] Tegra30: Cardhu: Add pad config tables/code based on pinmux code Pad config registers exist in APB_MISC_GP space, and control slew rate, drive strengh, schmidt, high-speed, and low-power modes for all of the pingroups in Tegra30. This builds off of the pinmux way of constructing init tables to configure select pads (SDIOCFG, for instance) during pinmux_init(). Currently, only SDIO1CFG is changed as per the TRM to work with the SD-card slot on Cardhu. Thanks to StephenW for the suggestion/original idea. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/cpu/tegra30-common/pinmux.c | 190 +++++++++++++++++- .../arm/include/asm/arch-tegra30/gp_padctrl.h | 6 + arch/arm/include/asm/arch-tegra30/pinmux.h | 67 +++++- board/nvidia/cardhu/cardhu.c | 6 +- board/nvidia/cardhu/pinmux-config-cardhu.h | 21 +- 5 files changed, 285 insertions(+), 5 deletions(-) diff --git a/arch/arm/cpu/tegra30-common/pinmux.c b/arch/arm/cpu/tegra30-common/pinmux.c index 122665fd3c..eecf0580bc 100644 --- a/arch/arm/cpu/tegra30-common/pinmux.c +++ b/arch/arm/cpu/tegra30-common/pinmux.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -38,6 +38,19 @@ struct tegra_pingroup_desc { #define PMUX_LOCK_SHIFT 7 #define PMUX_IO_RESET_SHIFT 8 +#define PGRP_HSM_SHIFT 2 +#define PGRP_SCHMT_SHIFT 3 +#define PGRP_LPMD_SHIFT 4 +#define PGRP_LPMD_MASK (3 << PGRP_LPMD_SHIFT) +#define PGRP_DRVDN_SHIFT 12 +#define PGRP_DRVDN_MASK (0x7F << PGRP_DRVDN_SHIFT) +#define PGRP_DRVUP_SHIFT 20 +#define PGRP_DRVUP_MASK (0x7F << PGRP_DRVUP_SHIFT) +#define PGRP_SLWR_SHIFT 28 +#define PGRP_SLWR_MASK (3 << PGRP_SLWR_SHIFT) +#define PGRP_SLWF_SHIFT 30 +#define PGRP_SLWF_MASK (3 << PGRP_SLWF_SHIFT) + /* Convenient macro for defining pin group properties */ #define PIN(pg_name, vdd, f0, f1, f2, f3, iod) \ { \ @@ -504,3 +517,178 @@ void pinmux_config_table(struct pingroup_config *config, int len) for (i = 0; i < len; i++) pinmux_config_pingroup(&config[i]); } + +static int padgrp_set_drvup_slwf(enum pdrive_pingrp pad, + int slwf) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_slwf = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and slwf */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_slw_isvalid(slwf)); + + /* NONE means unspecified/do not change/use POR value */ + if (slwf == PGRP_SLWF_NONE) + return 0; + + reg = readl(pad_slwf); + reg &= ~PGRP_SLWF_MASK; + reg |= (slwf << PGRP_SLWF_SHIFT); + writel(reg, pad_slwf); + + return 0; +} + +static int padgrp_set_drvdn_slwr(enum pdrive_pingrp pad, int slwr) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_slwr = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and slwr */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_slw_isvalid(slwr)); + + /* NONE means unspecified/do not change/use POR value */ + if (slwr == PGRP_SLWR_NONE) + return 0; + + reg = readl(pad_slwr); + reg &= ~PGRP_SLWR_MASK; + reg |= (slwr << PGRP_SLWR_SHIFT); + writel(reg, pad_slwr); + + return 0; +} + +static int padgrp_set_drvup(enum pdrive_pingrp pad, int drvup) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_drvup = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and drvup */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_drv_isvalid(drvup)); + + /* NONE means unspecified/do not change/use POR value */ + if (drvup == PGRP_DRVUP_NONE) + return 0; + + reg = readl(pad_drvup); + reg &= ~PGRP_DRVUP_MASK; + reg |= (drvup << PGRP_DRVUP_SHIFT); + writel(reg, pad_drvup); + + return 0; +} + +static int padgrp_set_drvdn(enum pdrive_pingrp pad, int drvdn) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_drvdn = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and drvdn */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_drv_isvalid(drvdn)); + + /* NONE means unspecified/do not change/use POR value */ + if (drvdn == PGRP_DRVDN_NONE) + return 0; + + reg = readl(pad_drvdn); + reg &= ~PGRP_DRVDN_MASK; + reg |= (drvdn << PGRP_DRVDN_SHIFT); + writel(reg, pad_drvdn); + + return 0; +} + +static int padgrp_set_lpmd(enum pdrive_pingrp pad, enum pgrp_lpmd lpmd) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_lpmd = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check pad and lpmd value */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_lpmd_isvalid(lpmd)); + + /* NONE means unspecified/do not change/use POR value */ + if (lpmd == PGRP_LPMD_NONE) + return 0; + + reg = readl(pad_lpmd); + reg &= ~PGRP_LPMD_MASK; + reg |= (lpmd << PGRP_LPMD_SHIFT); + writel(reg, pad_lpmd); + + return 0; +} + +static int padgrp_set_schmt(enum pdrive_pingrp pad, enum pgrp_schmt schmt) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_schmt = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check pad */ + assert(pmux_padgrp_isvalid(pad)); + + reg = readl(pad_schmt); + reg &= ~(1 << PGRP_SCHMT_SHIFT); + if (schmt == PGRP_SCHMT_ENABLE) + reg |= (0x1 << PGRP_SCHMT_SHIFT); + writel(reg, pad_schmt); + + return 0; +} +static int padgrp_set_hsm(enum pdrive_pingrp pad, + enum pgrp_hsm hsm) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_hsm = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check pad */ + assert(pmux_padgrp_isvalid(pad)); + + reg = readl(pad_hsm); + reg &= ~(1 << PGRP_HSM_SHIFT); + if (hsm == PGRP_HSM_ENABLE) + reg |= (0x1 << PGRP_HSM_SHIFT); + writel(reg, pad_hsm); + + return 0; +} + +void padctrl_config_pingroup(struct padctrl_config *config) +{ + enum pdrive_pingrp pad = config->padgrp; + + padgrp_set_drvup_slwf(pad, config->slwf); + padgrp_set_drvdn_slwr(pad, config->slwr); + padgrp_set_drvup(pad, config->drvup); + padgrp_set_drvdn(pad, config->drvdn); + padgrp_set_lpmd(pad, config->lpmd); + padgrp_set_schmt(pad, config->schmt); + padgrp_set_hsm(pad, config->hsm); +} + +void padgrp_config_table(struct padctrl_config *config, int len) +{ + int i; + + for (i = 0; i < len; i++) + padctrl_config_pingroup(&config[i]); +} diff --git a/arch/arm/include/asm/arch-tegra30/gp_padctrl.h b/arch/arm/include/asm/arch-tegra30/gp_padctrl.h index 9b383d0e74..23d184f2dd 100644 --- a/arch/arm/include/asm/arch-tegra30/gp_padctrl.h +++ b/arch/arm/include/asm/arch-tegra30/gp_padctrl.h @@ -56,4 +56,10 @@ struct apb_misc_gp_ctlr { u32 sdio1cfg; /* 0xEC: APB_MISC_GP_SDIO1CFGPADCTRL */ }; +/* SDMMC1/3 settings from section 24.6 of T30 TRM */ +#define SDIOCFG_DRVUP_SLWF 1 +#define SDIOCFG_DRVDN_SLWR 1 +#define SDIOCFG_DRVUP 0x2E +#define SDIOCFG_DRVDN 0x2A + #endif /* _TEGRA30_GP_PADCTRL_H_ */ diff --git a/arch/arm/include/asm/arch-tegra30/pinmux.h b/arch/arm/include/asm/arch-tegra30/pinmux.h index 341951bfcb..a9e1b462c4 100644 --- a/arch/arm/include/asm/arch-tegra30/pinmux.h +++ b/arch/arm/include/asm/arch-tegra30/pinmux.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -531,6 +531,63 @@ enum pmux_vddio { PMUX_VDDIO_NONE }; +#define PGRP_SLWF_NONE -1 +#define PGRP_SLWF_MAX 3 +#define PGRP_SLWR_NONE PGRP_SLWF_NONE +#define PGRP_SLWR_MAX PGRP_SLWF_MAX + +#define PGRP_DRVUP_NONE -1 +#define PGRP_DRVUP_MAX 127 +#define PGRP_DRVDN_NONE PGRP_DRVUP_NONE +#define PGRP_DRVDN_MAX PGRP_DRVUP_MAX + +/* return 1 if a padgrp is in range */ +#define pmux_padgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PDRIVE_PINGROUP_COUNT)) + +/* return 1 if a slew-rate rising/falling edge value is in range */ +#define pmux_pad_slw_isvalid(slw) (((slw) >= 0) && ((slw) <= PGRP_SLWF_MAX)) + +/* return 1 if a driver output pull-up/down strength code value is in range */ +#define pmux_pad_drv_isvalid(drv) (((drv) >= 0) && ((drv) <= PGRP_DRVUP_MAX)) + +/* return 1 if a low-power mode value is in range */ +#define pmux_pad_lpmd_isvalid(lpm) (((lpm) >= 0) && ((lpm) <= PGRP_LPMD_X)) + +/* Defines a pin group cfg's low-power mode select */ +enum pgrp_lpmd { + PGRP_LPMD_X8 = 0, + PGRP_LPMD_X4, + PGRP_LPMD_X2, + PGRP_LPMD_X, + PGRP_LPMD_NONE = -1, +}; + +/* Defines whether a pin group cfg's schmidt is enabled or not */ +enum pgrp_schmt { + PGRP_SCHMT_DISABLE = 0, + PGRP_SCHMT_ENABLE = 1, +}; + +/* Defines whether a pin group cfg's high-speed mode is enabled or not */ +enum pgrp_hsm { + PGRP_HSM_DISABLE = 0, + PGRP_HSM_ENABLE = 1, +}; + +/* + * This defines the configuration for a pin group's pad control config + */ +struct padctrl_config { + enum pdrive_pingrp padgrp; /* pin group PDRIVE_PINGRP_x */ + int slwf; /* falling edge slew */ + int slwr; /* rising edge slew */ + int drvup; /* pull-up drive strength */ + int drvdn; /* pull-down drive strength */ + enum pgrp_lpmd lpmd; /* low-power mode selection */ + enum pgrp_schmt schmt; /* schmidt enable */ + enum pgrp_hsm hsm; /* high-speed mode enable */ +}; + /* t30 pin drive group and pin mux registers */ #define PDRIVE_PINGROUP_OFFSET (0x868 >> 2) #define PMUX_OFFSET ((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \ @@ -600,4 +657,12 @@ void pinmux_config_table(struct pingroup_config *config, int len); /* Set a group of pins from a table */ void pinmux_init(void); +/** + * Set the GP pad configs + * + * @param config List of config items + * @param len Number of config items in list + */ +void padgrp_config_table(struct padctrl_config *config, int len); + #endif /* _TEGRA30_PINMUX_H_ */ diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c index df4cb6b728..08e9b7bd5b 100644 --- a/board/nvidia/cardhu/cardhu.c +++ b/board/nvidia/cardhu/cardhu.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2010-2012 + * (C) Copyright 2010-2013 * NVIDIA Corporation * * See file CREDITS for list of people who contributed to this @@ -23,6 +23,7 @@ #include #include +#include #include "pinmux-config-cardhu.h" /* @@ -36,4 +37,7 @@ void pinmux_init(void) pinmux_config_table(unused_pins_lowpower, ARRAY_SIZE(unused_pins_lowpower)); + + /* Initialize any non-default pad configs (APB_MISC_GP regs) */ + padgrp_config_table(cardhu_padctrl, ARRAY_SIZE(cardhu_padctrl)); } diff --git a/board/nvidia/cardhu/pinmux-config-cardhu.h b/board/nvidia/cardhu/pinmux-config-cardhu.h index 8428bba783..51d2b9425c 100644 --- a/board/nvidia/cardhu/pinmux-config-cardhu.h +++ b/board/nvidia/cardhu/pinmux-config-cardhu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -53,6 +53,18 @@ .ioreset = PMUX_PIN_IO_RESET_##_ioreset \ } +#define DEFAULT_PADCFG(_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) \ + { \ + .padgrp = PDRIVE_PINGROUP_##_padgrp, \ + .slwf = _slwf, \ + .slwr = _slwr, \ + .drvup = _drvup, \ + .drvdn = _drvdn, \ + .lpmd = PGRP_LPMD_##_lpmd, \ + .schmt = PGRP_SCHMT_##_schmt, \ + .hsm = PGRP_HSM_##_hsm, \ + } + static struct pingroup_config tegra3_pinmux_common[] = { /* SDMMC1 pinmux */ DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT), @@ -326,4 +338,9 @@ static struct pingroup_config unused_pins_lowpower[] = { DEFAULT_PINMUX(GMI_DQS, NAND, NORMAL, TRISTATE, OUTPUT), }; -#endif /* _PINMUX_CONFIG_CARDHU_H_ */ +static struct padctrl_config cardhu_padctrl[] = { + /* (_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) */ + DEFAULT_PADCFG(SDIO1, SDIOCFG_DRVUP_SLWF, SDIOCFG_DRVDN_SLWR, \ + SDIOCFG_DRVUP, SDIOCFG_DRVDN, NONE, DISABLE, DISABLE), +}; +#endif /* _PINMUX_CONFIG_CARDHU_H_ */ From 1baa4e72c63f8038bb2f874827bebee0eef58fe7 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Tue, 26 Feb 2013 11:14:17 -0700 Subject: [PATCH 25/39] Tegra30: fdt: Add SDMMC (sdhci) nodes for T30 boards (Cardhu for now) Took these values directly from the kernel dts files. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/dts/tegra30.dtsi | 32 +++++++++++++++++++++++++++++ board/nvidia/dts/tegra30-cardhu.dts | 15 ++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi index 9483e801f6..ccf154f1e7 100644 --- a/arch/arm/dts/tegra30.dtsi +++ b/arch/arm/dts/tegra30.dtsi @@ -184,4 +184,36 @@ clocks = <&tegra_car 105>; status = "disabled"; }; + + sdhci@78000000 { + compatible = "nvidia,tegra30-sdhci"; + reg = <0x78000000 0x200>; + interrupts = <0 14 0x04>; + clocks = <&tegra_car 14>; + status = "disabled"; + }; + + sdhci@78000200 { + compatible = "nvidia,tegra30-sdhci"; + reg = <0x78000200 0x200>; + interrupts = <0 15 0x04>; + clocks = <&tegra_car 9>; + status = "disabled"; + }; + + sdhci@78000400 { + compatible = "nvidia,tegra30-sdhci"; + reg = <0x78000400 0x200>; + interrupts = <0 19 0x04>; + clocks = <&tegra_car 69>; + status = "disabled"; + }; + + sdhci@78000600 { + compatible = "nvidia,tegra30-sdhci"; + reg = <0x78000600 0x200>; + interrupts = <0 31 0x04>; + clocks = <&tegra_car 15>; + status = "disabled"; + }; }; diff --git a/board/nvidia/dts/tegra30-cardhu.dts b/board/nvidia/dts/tegra30-cardhu.dts index 48039c9b30..4d22b48ee9 100644 --- a/board/nvidia/dts/tegra30-cardhu.dts +++ b/board/nvidia/dts/tegra30-cardhu.dts @@ -12,6 +12,8 @@ i2c2 = "/i2c@7000c400"; i2c3 = "/i2c@7000c500"; i2c4 = "/i2c@7000c700"; + sdhci0 = "/sdhci@78000600"; + sdhci1 = "/sdhci@78000000"; }; memory { @@ -48,4 +50,17 @@ status = "okay"; spi-max-frequency = <25000000>; }; + + sdhci@78000000 { + status = "okay"; + cd-gpios = <&gpio 69 1>; /* gpio PI5 */ + wp-gpios = <&gpio 155 0>; /* gpio PT3 */ + power-gpios = <&gpio 31 0>; /* gpio PD7 */ + bus-width = <4>; + }; + + sdhci@78000600 { + status = "okay"; + bus-width = <8>; + }; }; From 38797bcb1f8306429409ca2831309342b77a2e37 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Tue, 26 Feb 2013 11:17:43 -0700 Subject: [PATCH 26/39] Tegra: MMC: Added/update SDMMC registers/base addresses for T20/T30 Removed SDMMC base addresses from tegra.h since they're no longer used. Added additional vendor-specific SD/MMC registers and bus power defines. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/include/asm/arch-tegra/tegra_mmc.h | 35 +++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h index bd18f5f75b..2a3f830cc5 100644 --- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h +++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h @@ -22,10 +22,7 @@ #ifndef __TEGRA_MMC_H_ #define __TEGRA_MMC_H_ -#define TEGRA_SDMMC1_BASE 0xC8000000 -#define TEGRA_SDMMC2_BASE 0xC8000200 -#define TEGRA_SDMMC3_BASE 0xC8000400 -#define TEGRA_SDMMC4_BASE 0xC8000600 +#include #define MAX_HOSTS 4 /* Max number of 'hosts'/controllers */ @@ -64,12 +61,30 @@ struct tegra_mmc { unsigned char admaerr; /* offset 54h */ unsigned char res4[3]; /* RESERVED, offset 55h-57h */ unsigned long admaaddr; /* offset 58h-5Fh */ - unsigned char res5[0x9c]; /* RESERVED, offset 60h-FBh */ + unsigned char res5[0xa0]; /* RESERVED, offset 60h-FBh */ unsigned short slotintstatus; /* offset FCh */ unsigned short hcver; /* HOST Version */ - unsigned char res6[0x100]; /* RESERVED, offset 100h-1FFh */ + unsigned int venclkctl; /* _VENDOR_CLOCK_CNTRL_0, 100h */ + unsigned int venspictl; /* _VENDOR_SPI_CNTRL_0, 104h */ + unsigned int venspiintsts; /* _VENDOR_SPI_INT_STATUS_0, 108h */ + unsigned int venceatactl; /* _VENDOR_CEATA_CNTRL_0, 10Ch */ + unsigned int venbootctl; /* _VENDOR_BOOT_CNTRL_0, 110h */ + unsigned int venbootacktout; /* _VENDOR_BOOT_ACK_TIMEOUT, 114h */ + unsigned int venbootdattout; /* _VENDOR_BOOT_DAT_TIMEOUT, 118h */ + unsigned int vendebouncecnt; /* _VENDOR_DEBOUNCE_COUNT_0, 11Ch */ + unsigned int venmiscctl; /* _VENDOR_MISC_CNTRL_0, 120h */ + unsigned int res6[47]; /* 0x124 ~ 0x1DC */ + unsigned int sdmemcmppadctl; /* _SDMEMCOMPPADCTRL_0, 1E0h */ + unsigned int autocalcfg; /* _AUTO_CAL_CONFIG_0, 1E4h */ + unsigned int autocalintval; /* _AUTO_CAL_INTERVAL_0, 1E8h */ + unsigned int autocalsts; /* _AUTO_CAL_STATUS_0, 1ECh */ }; +#define TEGRA_MMC_PWRCTL_SD_BUS_POWER (1 << 0) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 (5 << 1) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 (6 << 1) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 (7 << 1) + #define TEGRA_MMC_HOSTCTL_DMASEL_MASK (3 << 3) #define TEGRA_MMC_HOSTCTL_DMASEL_SDMA (0 << 3) #define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_32BIT (2 << 3) @@ -119,6 +134,12 @@ struct tegra_mmc { #define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE (1 << 1) +/* SDMMC1/3 settings from section 24.6 of T30 TRM */ +#define MEMCOMP_PADCTRL_VREF 7 +#define AUTO_CAL_ENABLED (1 << 29) +#define AUTO_CAL_PD_OFFSET (0x70 << 8) +#define AUTO_CAL_PU_OFFSET (0x62 << 0) + struct mmc_host { struct tegra_mmc *reg; int id; /* device id/number, 0-3 */ @@ -132,5 +153,7 @@ struct mmc_host { unsigned int clock; /* Current clock (MHz) */ }; +void pad_init_mmc(struct mmc_host *host); + #endif /* __ASSEMBLY__ */ #endif /* __TEGRA_MMC_H_ */ From 190be1f9b74b0c8c2f1b2735774a6536758837af Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Tue, 26 Feb 2013 12:26:55 -0700 Subject: [PATCH 27/39] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines T30 requires specific SDMMC pad programming, and bus power-rail bringup. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- board/nvidia/cardhu/cardhu.c | 51 ++++++++++++++++++++++++++++++++++++ board/nvidia/common/board.c | 31 +++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c index 08e9b7bd5b..3544b41cd0 100644 --- a/board/nvidia/cardhu/cardhu.c +++ b/board/nvidia/cardhu/cardhu.c @@ -25,6 +25,10 @@ #include #include #include "pinmux-config-cardhu.h" +#include + +#define PMU_I2C_ADDRESS 0x2D +#define MAX_I2C_RETRY 3 /* * Routine: pinmux_init @@ -41,3 +45,50 @@ void pinmux_init(void) /* Initialize any non-default pad configs (APB_MISC_GP regs) */ padgrp_config_table(cardhu_padctrl, ARRAY_SIZE(cardhu_padctrl)); } + +#if defined(CONFIG_TEGRA_MMC) +/* + * Do I2C/PMU writes to bring up SD card bus power + * + */ +void board_sdmmc_voltage_init(void) +{ + uchar reg, data_buffer[1]; + int i; + + i2c_set_bus_num(0); /* PMU is on bus 0 */ + + /* TPS659110: LDO5_REG = 3.3v, ACTIVE to SDMMC1 */ + data_buffer[0] = 0x65; + reg = 0x32; + + for (i = 0; i < MAX_I2C_RETRY; ++i) { + if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) + udelay(100); + } + + /* TPS659110: GPIO7_REG = PDEN, output a 1 to EN_3V3_SYS */ + data_buffer[0] = 0x09; + reg = 0x67; + + for (i = 0; i < MAX_I2C_RETRY; ++i) { + if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1)) + udelay(100); + } +} + +/* + * Routine: pin_mux_mmc + * Description: setup the MMC muxes, power rails, etc. + */ +void pin_mux_mmc(void) +{ + /* + * NOTE: We don't do mmc-specific pin muxes here. + * They were done globally in pinmux_init(). + */ + + /* Bring up the SDIO1 power rail */ + board_sdmmc_voltage_init(); +} +#endif /* MMC */ diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index babbe08e06..7d9f361a8a 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -49,6 +49,7 @@ #include #endif #ifdef CONFIG_TEGRA_MMC +#include #include #endif #include @@ -245,4 +246,32 @@ int board_mmc_init(bd_t *bd) return 0; } -#endif + +void pad_init_mmc(struct mmc_host *host) +{ +#if defined(CONFIG_TEGRA30) + enum periph_id id = host->mmc_id; + u32 val; + + debug("%s: sdmmc address = %08x, id = %d\n", __func__, + (unsigned int)host->reg, id); + + /* Set the pad drive strength for SDMMC1 or 3 only */ + if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) { + debug("%s: settings are only valid for SDMMC1/SDMMC3!\n", + __func__); + return; + } + + val = readl(&host->reg->sdmemcmppadctl); + val &= 0xFFFFFFF0; + val |= MEMCOMP_PADCTRL_VREF; + writel(val, &host->reg->sdmemcmppadctl); + + val = readl(&host->reg->autocalcfg); + val &= 0xFFFF0000; + val |= AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET | AUTO_CAL_ENABLED; + writel(val, &host->reg->autocalcfg); +#endif /* T30 */ +} +#endif /* MMC */ From 2d348a1652f1d1211ab82cb0c7a57a3362830d71 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Tue, 26 Feb 2013 12:31:26 -0700 Subject: [PATCH 28/39] mmc: Tegra: Add SD bus power/voltage function and MMC pad init call. Tegra30 requires the SD Bus Voltage & Power bits be set in the SD Power Control register. Tegra20 works w/o them set, but do it anyway for those SoCs as it's part of the SD spec. Also call a common board pad init routine (pad_init_mmc) in mmc_reset(), used by Tegra30 only for now. Note that Tegra20 SD/MMC HW differs enough from Tegra20 that a new compatible entry is used in the fdt compat_names/id tables. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- drivers/mmc/tegra_mmc.c | 63 +++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index 455a690b7e..e86bc680ff 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include @@ -38,6 +37,38 @@ struct mmc_host mmc_host[MAX_HOSTS]; #error "Please enable device tree support to use this driver" #endif +static void mmc_set_power(struct mmc_host *host, unsigned short power) +{ + u8 pwr = 0; + debug("%s: power = %x\n", __func__, power); + + if (power != (unsigned short)-1) { + switch (1 << power) { + case MMC_VDD_165_195: + pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8; + break; + case MMC_VDD_29_30: + case MMC_VDD_30_31: + pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0; + break; + case MMC_VDD_32_33: + case MMC_VDD_33_34: + pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3; + break; + } + } + debug("%s: pwr = %X\n", __func__, pwr); + + /* Set the bus voltage first (if any) */ + writeb(pwr, &host->reg->pwrcon); + if (pwr == 0) + return; + + /* Now enable bus power */ + pwr |= TEGRA_MMC_PWRCTL_SD_BUS_POWER; + writeb(pwr, &host->reg->pwrcon); +} + static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data, struct bounce_buffer *bbstate) { @@ -334,8 +365,7 @@ static void mmc_change_clock(struct mmc_host *host, uint clock) debug(" mmc_change_clock called\n"); /* - * Change Tegra SDMMCx clock divisor here. Source is 216MHz, - * PLLP_OUT0 + * Change Tegra SDMMCx clock divisor here. Source is PLLP_OUT0 */ if (clock == 0) goto out; @@ -410,7 +440,7 @@ static void mmc_set_ios(struct mmc *mmc) debug("mmc_set_ios: hostctl = %08X\n", ctrl); } -static void mmc_reset(struct mmc_host *host) +static void mmc_reset(struct mmc_host *host, struct mmc *mmc) { unsigned int timeout; debug(" mmc_reset called\n"); @@ -436,6 +466,14 @@ static void mmc_reset(struct mmc_host *host) timeout--; udelay(1000); } + + /* Set SD bus voltage & enable bus power */ + mmc_set_power(host, fls(mmc->voltages) - 1); + debug("%s: power control = %02X, host control = %02X\n", __func__, + readb(&host->reg->pwrcon), readb(&host->reg->hostctl)); + + /* Make sure SDIO pads are set up */ + pad_init_mmc(host); } static int mmc_core_init(struct mmc *mmc) @@ -444,7 +482,7 @@ static int mmc_core_init(struct mmc *mmc) unsigned int mask; debug(" mmc_core_init called\n"); - mmc_reset(host); + mmc_reset(host, mmc); host->version = readw(&host->reg->hcver); debug("host version = %x\n", host->version); @@ -642,12 +680,21 @@ void tegra_mmc_init(void) const void *blob = gd->fdt_blob; debug("%s entry\n", __func__); + /* See if any Tegra30 MMC controllers are present */ + count = fdtdec_find_aliases_for_id(blob, "sdhci", + COMPAT_NVIDIA_TEGRA30_SDMMC, node_list, MAX_HOSTS); + debug("%s: count of T30 sdhci nodes is %d\n", __func__, count); + if (process_nodes(blob, node_list, count)) { + printf("%s: Error processing T30 mmc node(s)!\n", __func__); + return; + } + + /* Now look for any Tegra20 MMC controllers */ count = fdtdec_find_aliases_for_id(blob, "sdhci", COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, MAX_HOSTS); - debug("%s: count of sdhci nodes is %d\n", __func__, count); - + debug("%s: count of T20 sdhci nodes is %d\n", __func__, count); if (process_nodes(blob, node_list, count)) { - printf("%s: Error processing mmc node(s)!\n", __func__); + printf("%s: Error processing T20 mmc node(s)!\n", __func__); return; } } From f4e4e0b0e3405785a5a4b46913a9476175adc12d Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Mon, 4 Mar 2013 14:07:18 -0700 Subject: [PATCH 29/39] Tegra30: mmc: Add Tegra30 SDMMC compatible entry to fdtdec & driver Tegra30 SD/MMC controller differs enough from Tegra20 that it needs its own entry in the compat_names/compat_id tables and in the Tegra MMC driver. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- include/fdtdec.h | 3 ++- lib/fdtdec.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/fdtdec.h b/include/fdtdec.h index 32730d2063..21894835d1 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -71,7 +71,8 @@ enum fdt_compat_id { COMPAT_NVIDIA_TEGRA20_NAND, /* Tegra2 NAND controller */ COMPAT_NVIDIA_TEGRA20_PWM, /* Tegra 2 PWM controller */ COMPAT_NVIDIA_TEGRA20_DC, /* Tegra 2 Display controller */ - COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra SDMMC controller */ + COMPAT_NVIDIA_TEGRA30_SDMMC, /* Tegra30 SDMMC controller */ + COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra20 SDMMC controller */ COMPAT_NVIDIA_TEGRA20_SFLASH, /* Tegra 2 SPI flash controller */ COMPAT_NVIDIA_TEGRA20_SLINK, /* Tegra 2 SPI SLINK controller */ COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 000130f932..43f29f5c6b 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -46,6 +46,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"), COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"), COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"), + COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"), COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"), COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"), From ca557b386d957a853e085259b4c501b7a0ee1ee2 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Tue, 26 Feb 2013 12:36:22 -0700 Subject: [PATCH 30/39] Tegra30: MMC: Enable DT MMC driver support for Tegra30 Cardhu boards Tested on my Cardhu-A04 tablet, eMMC and SD-Card work fine, can load a kernel off of an SD card OK, card detect works, and the env is now stored in eMMC (end of the 2nd 'boot' sector, same as Tegra20). Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- include/configs/cardhu.h | 20 +++++++++++++++++++- include/configs/tegra30-common.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h index 1616b39778..18c7eb82dd 100644 --- a/include/configs/cardhu.h +++ b/include/configs/cardhu.h @@ -47,7 +47,25 @@ #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_CMD_I2C -#define CONFIG_ENV_IS_NOWHERE +/* SD/MMC */ +#define CONFIG_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_TEGRA_MMC +#define CONFIG_CMD_MMC + +#define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION +#define CONFIG_FS_EXT4 +#define CONFIG_FS_FAT +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_FAT +#define CONFIG_CMD_FS_GENERIC + +/* Environment in eMMC, at the end of 2nd "boot sector" */ +#define CONFIG_ENV_IS_IN_MMC +#define CONFIG_ENV_OFFSET ((512 * 1024) - CONFIG_ENV_SIZE) +#define CONFIG_SYS_MMC_ENV_DEV 0 +#define CONFIG_SYS_MMC_ENV_PART 2 /* SPI */ #define CONFIG_TEGRA_SLINK diff --git a/include/configs/tegra30-common.h b/include/configs/tegra30-common.h index 04517e1409..bd1dfe8df9 100644 --- a/include/configs/tegra30-common.h +++ b/include/configs/tegra30-common.h @@ -86,4 +86,7 @@ /* Total I2C ports on Tegra30 */ #define TEGRA_I2C_NUM_CONTROLLERS 5 +/* Misc utility code */ +#define CONFIG_BOUNCE_BUFFER + #endif /* _TEGRA30_COMMON_H_ */ From a885f85214dcd358b29a2ffe69ab4f9b515b95e9 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 28 Feb 2013 15:03:45 +0000 Subject: [PATCH 31/39] ARM: tegra: make bounce buffer option common All Tegra devices will need CONFIG_BOUNCE_BUFFER. Move it to tegra-common.h to ensure it's always set. Signed-off-by: Stephen Warren Acked-by: Simon Glass Signed-off-by: Tom Warren --- include/configs/tegra-common.h | 3 +++ include/configs/tegra20-common.h | 3 --- include/configs/tegra30-common.h | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h index 80c846ce9d..080feb01fe 100644 --- a/include/configs/tegra-common.h +++ b/include/configs/tegra-common.h @@ -155,4 +155,7 @@ #define CONFIG_SPL_SERIAL_SUPPORT #define CONFIG_SPL_GPIO_SUPPORT +/* Misc utility code */ +#define CONFIG_BOUNCE_BUFFER + #endif /* _TEGRA_COMMON_H_ */ diff --git a/include/configs/tegra20-common.h b/include/configs/tegra20-common.h index 33e5f524f1..dac8245864 100644 --- a/include/configs/tegra20-common.h +++ b/include/configs/tegra20-common.h @@ -114,7 +114,4 @@ #define CONFIG_SYS_NAND_SELF_INIT #define CONFIG_SYS_NAND_ONFI_DETECTION -/* Misc utility code */ -#define CONFIG_BOUNCE_BUFFER - #endif /* _TEGRA20_COMMON_H_ */ diff --git a/include/configs/tegra30-common.h b/include/configs/tegra30-common.h index bd1dfe8df9..04517e1409 100644 --- a/include/configs/tegra30-common.h +++ b/include/configs/tegra30-common.h @@ -86,7 +86,4 @@ /* Total I2C ports on Tegra30 */ #define TEGRA_I2C_NUM_CONTROLLERS 5 -/* Misc utility code */ -#define CONFIG_BOUNCE_BUFFER - #endif /* _TEGRA30_COMMON_H_ */ From 2c1af9dcdcf4ede8d153c0918beca9067ec0eb36 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 28 Feb 2013 15:03:46 +0000 Subject: [PATCH 32/39] disk: define HAVE_BLOCK_DEVICE in a common place This set of ifdefs is used in a number of places. Move its definition somewhere common so it doesn't have to be repeated. Signed-off-by: Stephen Warren Acked-by: Simon Glass Acked-by: Tom Rini Signed-off-by: Tom Warren --- disk/part.c | 10 ---------- disk/part_amiga.c | 6 +----- disk/part_dos.c | 7 +------ disk/part_efi.c | 8 +------- disk/part_iso.c | 7 +------ disk/part_mac.c | 7 +------ include/config_fallbacks.h | 10 ++++++++++ 7 files changed, 15 insertions(+), 40 deletions(-) diff --git a/disk/part.c b/disk/part.c index 58a45637aa..d73625c443 100644 --- a/disk/part.c +++ b/disk/part.c @@ -35,16 +35,6 @@ #define PRINTF(fmt,args...) #endif -/* Rather than repeat this expression each time, add a define for it */ -#if (defined(CONFIG_CMD_IDE) || \ - defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_SCSI) || \ - defined(CONFIG_CMD_USB) || \ - defined(CONFIG_MMC) || \ - defined(CONFIG_SYSTEMACE) ) -#define HAVE_BLOCK_DEVICE -#endif - struct block_drvr { char *name; block_dev_desc_t* (*get_dev)(int dev); diff --git a/disk/part_amiga.c b/disk/part_amiga.c index dc7d46256d..0e6d82dbae 100644 --- a/disk/part_amiga.c +++ b/disk/part_amiga.c @@ -26,11 +26,7 @@ #include #include "part_amiga.h" -#if defined(CONFIG_CMD_IDE) || \ - defined(CONFIG_CMD_SCSI) || \ - defined(CONFIG_CMD_USB) || \ - defined(CONFIG_MMC) || \ - defined(CONFIG_SYSTEMACE) +#ifdef HAVE_BLOCK_DEVICE #undef AMIGA_DEBUG diff --git a/disk/part_dos.c b/disk/part_dos.c index 3fe901ba1b..37087a6ac3 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -35,12 +35,7 @@ #include #include "part_dos.h" -#if defined(CONFIG_CMD_IDE) || \ - defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_SCSI) || \ - defined(CONFIG_CMD_USB) || \ - defined(CONFIG_MMC) || \ - defined(CONFIG_SYSTEMACE) +#ifdef HAVE_BLOCK_DEVICE /* Convert char[4] in little endian format to the host format integer */ diff --git a/disk/part_efi.c b/disk/part_efi.c index 7665017330..b3fd0e954d 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -39,13 +39,7 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined(CONFIG_CMD_IDE) || \ - defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_SCSI) || \ - defined(CONFIG_CMD_USB) || \ - defined(CONFIG_MMC) || \ - defined(CONFIG_SYSTEMACE) - +#ifdef HAVE_BLOCK_DEVICE /** * efi_crc32() - EFI version of crc32 function * @buf: buffer to calculate crc32 of diff --git a/disk/part_iso.c b/disk/part_iso.c index 4401790af2..49639af269 100644 --- a/disk/part_iso.c +++ b/disk/part_iso.c @@ -25,12 +25,7 @@ #include #include "part_iso.h" -#if defined(CONFIG_CMD_IDE) || \ - defined(CONFIG_CMD_SCSI) || \ - defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_USB) || \ - defined(CONFIG_MMC) || \ - defined(CONFIG_SYSTEMACE) +#ifdef HAVE_BLOCK_DEVICE /* #define ISO_PART_DEBUG */ diff --git a/disk/part_mac.c b/disk/part_mac.c index cb443ac532..74dc12fe58 100644 --- a/disk/part_mac.c +++ b/disk/part_mac.c @@ -34,12 +34,7 @@ #include #include "part_mac.h" -#if defined(CONFIG_CMD_IDE) || \ - defined(CONFIG_CMD_SCSI) || \ - defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_USB) || \ - defined(CONFIG_MMC) || \ - defined(CONFIG_SYSTEMACE) +#ifdef HAVE_BLOCK_DEVICE /* stdlib.h causes some compatibility problems; should fixe these! -- wd */ #ifndef __ldiv_t_defined diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h index bfb9680d68..653ff2b388 100644 --- a/include/config_fallbacks.h +++ b/include/config_fallbacks.h @@ -26,4 +26,14 @@ #define CONFIG_EXT4_WRITE #endif +/* Rather than repeat this expression each time, add a define for it */ +#if defined(CONFIG_CMD_IDE) || \ + defined(CONFIG_CMD_SATA) || \ + defined(CONFIG_CMD_SCSI) || \ + defined(CONFIG_CMD_USB) || \ + defined(CONFIG_MMC) || \ + defined(CONFIG_SYSTEMACE) +#define HAVE_BLOCK_DEVICE +#endif + #endif /* __CONFIG_FALLBACKS_H */ From 4123c4ea23cd8b9f3313bccb6c2add87b06412a3 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 28 Feb 2013 15:03:47 +0000 Subject: [PATCH 33/39] disk: define HAVE_BLOCK_DEVICE if CONFIG_CMD_PART Various code that is conditional upon HAVE_BLOCK_DEVICE is required by code conditional upon CONFIG_CMD_PART. So, enable HAVE_BLOCK_DEVICE if CONFIG_CMD_PART is enabled. Signed-off-by: Stephen Warren Acked-by: Simon Glass Acked-by: Tom Rini Signed-off-by: Tom Warren --- include/config_fallbacks.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h index 653ff2b388..9298d0ee97 100644 --- a/include/config_fallbacks.h +++ b/include/config_fallbacks.h @@ -31,6 +31,7 @@ defined(CONFIG_CMD_SATA) || \ defined(CONFIG_CMD_SCSI) || \ defined(CONFIG_CMD_USB) || \ + defined(CONFIG_CMD_PART) || \ defined(CONFIG_MMC) || \ defined(CONFIG_SYSTEMACE) #define HAVE_BLOCK_DEVICE From 11d9c0303949c2e9c2a176f81c0d7355c76bb546 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 28 Feb 2013 15:03:48 +0000 Subject: [PATCH 34/39] ARM: tegra: enable a common set of disk-related commands everywhere Enable a common set of partition types, filesystems, and related commands in tegra-common.h, so that they are available on all Tegra boards. This allows boot.scr (loaded and executed by the default built-in environment) on those boards to assume that certain features are always available. Do this in tegra-common.h, so that individual board files can undefine the features if they really don't want any of them. Signed-off-by: Stephen Warren Acked-by: Simon Glass Signed-off-by: Tom Warren --- include/configs/cardhu.h | 8 -------- include/configs/colibri_t20_iris.h | 6 ------ include/configs/harmony.h | 8 -------- include/configs/medcom-wide.h | 5 ----- include/configs/paz00.h | 8 -------- include/configs/plutux.h | 5 ----- include/configs/seaboard.h | 8 -------- include/configs/tec.h | 5 ----- include/configs/tegra-common.h | 12 ++++++++++++ include/configs/tegra20-common.h | 3 --- include/configs/trimslice.h | 8 -------- include/configs/ventana.h | 8 -------- include/configs/whistler.h | 8 -------- 13 files changed, 12 insertions(+), 80 deletions(-) diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h index 18c7eb82dd..55dc83da6a 100644 --- a/include/configs/cardhu.h +++ b/include/configs/cardhu.h @@ -53,14 +53,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_FS_EXT4 -#define CONFIG_FS_FAT -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT -#define CONFIG_CMD_FS_GENERIC - /* Environment in eMMC, at the end of 2nd "boot sector" */ #define CONFIG_ENV_IS_IN_MMC #define CONFIG_ENV_OFFSET ((512 * 1024) - CONFIG_ENV_SIZE) diff --git a/include/configs/colibri_t20_iris.h b/include/configs/colibri_t20_iris.h index 0e5f281b25..856c860cda 100644 --- a/include/configs/colibri_t20_iris.h +++ b/include/configs/colibri_t20_iris.h @@ -40,12 +40,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -/* File system support */ -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT - /* USB host support */ #define CONFIG_USB_EHCI #define CONFIG_USB_EHCI_TEGRA diff --git a/include/configs/harmony.h b/include/configs/harmony.h index 8d1fd47afe..0c73f86ec1 100644 --- a/include/configs/harmony.h +++ b/include/configs/harmony.h @@ -56,14 +56,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_FS_EXT4 -#define CONFIG_FS_FAT -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT -#define CONFIG_CMD_FS_GENERIC - /* NAND support */ #define CONFIG_CMD_NAND #define CONFIG_TEGRA_NAND diff --git a/include/configs/medcom-wide.h b/include/configs/medcom-wide.h index bae4ba0bb5..57a50d730c 100644 --- a/include/configs/medcom-wide.h +++ b/include/configs/medcom-wide.h @@ -66,11 +66,6 @@ #define CONFIG_CMD_NET #define CONFIG_CMD_DHCP -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT - #define CONFIG_FIT #define CONFIG_BOOTCOMMAND \ diff --git a/include/configs/paz00.h b/include/configs/paz00.h index 2edb4aaba9..eac1ef9e02 100644 --- a/include/configs/paz00.h +++ b/include/configs/paz00.h @@ -44,14 +44,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_FS_EXT4 -#define CONFIG_FS_FAT -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT -#define CONFIG_CMD_FS_GENERIC - /* Environment in eMMC, at the end of 2nd "boot sector" */ #define CONFIG_ENV_IS_IN_MMC #define CONFIG_ENV_OFFSET ((1024 * 1024) - CONFIG_ENV_SIZE) diff --git a/include/configs/plutux.h b/include/configs/plutux.h index deee237879..4cfe88a5e7 100644 --- a/include/configs/plutux.h +++ b/include/configs/plutux.h @@ -65,11 +65,6 @@ #define CONFIG_CMD_NET #define CONFIG_CMD_DHCP -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT - #define CONFIG_FIT #define CONFIG_BOOTCOMMAND \ diff --git a/include/configs/seaboard.h b/include/configs/seaboard.h index de0c777819..f66173e0f2 100644 --- a/include/configs/seaboard.h +++ b/include/configs/seaboard.h @@ -70,14 +70,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_FS_EXT4 -#define CONFIG_FS_FAT -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT -#define CONFIG_CMD_FS_GENERIC - /* Environment in eMMC, at the end of 2nd "boot sector" */ #define CONFIG_ENV_IS_IN_MMC #define CONFIG_ENV_OFFSET ((512 * 1024) - CONFIG_ENV_SIZE) diff --git a/include/configs/tec.h b/include/configs/tec.h index caeb9cd8a8..f90f5c7526 100644 --- a/include/configs/tec.h +++ b/include/configs/tec.h @@ -73,11 +73,6 @@ #define CONFIG_CMD_NET #define CONFIG_CMD_DHCP -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT - #define CONFIG_FIT #define CONFIG_BOOTCOMMAND \ diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h index 080feb01fe..4cc35e5a88 100644 --- a/include/configs/tegra-common.h +++ b/include/configs/tegra-common.h @@ -88,6 +88,18 @@ #define CONFIG_COMMAND_HISTORY #define CONFIG_AUTO_COMPLETE +/* turn on commonly used storage-related commands */ + +#define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION +#define CONFIG_PARTITION_UUIDS +#define CONFIG_FS_EXT4 +#define CONFIG_FS_FAT +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_FAT +#define CONFIG_CMD_FS_GENERIC +#define CONFIG_CMD_PART + #define CONFIG_SYS_NO_FLASH #define CONFIG_CONSOLE_MUX diff --git a/include/configs/tegra20-common.h b/include/configs/tegra20-common.h index dac8245864..311680e9e1 100644 --- a/include/configs/tegra20-common.h +++ b/include/configs/tegra20-common.h @@ -108,9 +108,6 @@ /* Total I2C ports on Tegra20 */ #define TEGRA_I2C_NUM_CONTROLLERS 4 -#define CONFIG_PARTITION_UUIDS -#define CONFIG_CMD_PART - #define CONFIG_SYS_NAND_SELF_INIT #define CONFIG_SYS_NAND_ONFI_DETECTION diff --git a/include/configs/trimslice.h b/include/configs/trimslice.h index 334d3a3b8b..0644f7a5b8 100644 --- a/include/configs/trimslice.h +++ b/include/configs/trimslice.h @@ -67,14 +67,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_FS_EXT4 -#define CONFIG_FS_FAT -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT -#define CONFIG_CMD_FS_GENERIC - /* Environment in SPI */ #define CONFIG_ENV_IS_IN_SPI_FLASH #define CONFIG_ENV_SPI_MAX_HZ 48000000 diff --git a/include/configs/ventana.h b/include/configs/ventana.h index b55ebc9bfc..5755f11714 100644 --- a/include/configs/ventana.h +++ b/include/configs/ventana.h @@ -50,14 +50,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_FS_EXT4 -#define CONFIG_FS_FAT -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT -#define CONFIG_CMD_FS_GENERIC - /* Environment in eMMC, at the end of 2nd "boot sector" */ #define CONFIG_ENV_IS_IN_MMC #define CONFIG_ENV_OFFSET ((1024 * 1024) - CONFIG_ENV_SIZE) diff --git a/include/configs/whistler.h b/include/configs/whistler.h index 1e554d8164..9542c7e213 100644 --- a/include/configs/whistler.h +++ b/include/configs/whistler.h @@ -59,14 +59,6 @@ #define CONFIG_TEGRA_MMC #define CONFIG_CMD_MMC -#define CONFIG_DOS_PARTITION -#define CONFIG_EFI_PARTITION -#define CONFIG_FS_EXT4 -#define CONFIG_FS_FAT -#define CONFIG_CMD_EXT2 -#define CONFIG_CMD_FAT -#define CONFIG_CMD_FS_GENERIC - /* * Environment in eMMC, at the end of 2nd "boot sector". Note: This assumes * the user plugged the standard 8MB MoviNAND card into J29/HSMMC/POP. If From b3b6ddff0bb6768af7532da4cee5362fbe41ec4b Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Wed, 13 Mar 2013 15:00:54 -0700 Subject: [PATCH 35/39] Tegra114: pinmux: Fix bad CAM_MCLK func 3 table entry This caused CAM_MCLK's pinmux reg to be locked out, since the table parsing code couldn't find a matching entry for VI_ALT3 and wrote garbage to the register. Signed-off-by: Tom Warren --- arch/arm/cpu/tegra114-common/pinmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/cpu/tegra114-common/pinmux.c b/arch/arm/cpu/tegra114-common/pinmux.c index 27b5f694fa..16368c5bc1 100644 --- a/arch/arm/cpu/tegra114-common/pinmux.c +++ b/arch/arm/cpu/tegra114-common/pinmux.c @@ -226,7 +226,7 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { PINI(SDMMC4_DAT6, SDMMC4, SDMMC4, SPI3, GMI, RSVD4), PINI(SDMMC4_DAT7, SDMMC4, SDMMC4, RSVD2, GMI, RSVD4), PIN_RESERVED, /* Reserved by t114: 0x3280 */ - PINI(CAM_MCLK, CAM, VI, VI_ALT1, VI_ALT2, RSVD4), + PINI(CAM_MCLK, CAM, VI, VI_ALT1, VI_ALT3, RSVD4), PINI(GPIO_PCC1, CAM, I2S4, RSVD2, RSVD3, RSVD4), PINI(GPIO_PBB0, CAM, I2S4, VI, VI_ALT1, VI_ALT3), PINI(CAM_I2C_SCL, CAM, VGP1, I2C3, RSVD3, RSVD4), From 36c48be1104664ab79e5655327f39812e979c6aa Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Wed, 13 Mar 2013 15:13:47 -0700 Subject: [PATCH 36/39] Tegra114: Fix/update GP padcfg register struct Differences in padcfg registers (some removed, some added) between Tegra30 and Tegra114 weren't picked up when I first ported this file. Signed-off-by: Tom Warren --- .../include/asm/arch-tegra114/gp_padctrl.h | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/arch/arm/include/asm/arch-tegra114/gp_padctrl.h b/arch/arm/include/asm/arch-tegra114/gp_padctrl.h index c538bdd052..1ef1a1484d 100644 --- a/arch/arm/include/asm/arch-tegra114/gp_padctrl.h +++ b/arch/arm/include/asm/arch-tegra114/gp_padctrl.h @@ -27,7 +27,7 @@ struct apb_misc_gp_ctlr { u32 emu_revid; /* 0x60: APB_MISC_GP_EMU_REVID */ u32 xactor_scratch; /* 0x64: APB_MISC_GP_XACTOR_SCRATCH */ u32 aocfg1; /* 0x68: APB_MISC_GP_AOCFG1PADCTRL */ - u32 aocfg2; /* 0x6c: APB_MISC_GP_AOCFG2PADCTRL */ + u32 aocfg2; /* 0x6C: APB_MISC_GP_AOCFG2PADCTRL */ u32 atcfg1; /* 0x70: APB_MISC_GP_ATCFG1PADCTRL */ u32 atcfg2; /* 0x74: APB_MISC_GP_ATCFG2PADCTRL */ u32 atcfg3; /* 0x78: APB_MISC_GP_ATCFG3PADCTRL */ @@ -35,25 +35,43 @@ struct apb_misc_gp_ctlr { u32 atcfg5; /* 0x80: APB_MISC_GP_ATCFG5PADCTRL */ u32 cdev1cfg; /* 0x84: APB_MISC_GP_CDEV1CFGPADCTRL */ u32 cdev2cfg; /* 0x88: APB_MISC_GP_CDEV2CFGPADCTRL */ - u32 csuscfg; /* 0x8C: APB_MISC_GP_CSUSCFGPADCTRL */ + u32 reserved1; /* 0x8C: */ u32 dap1cfg; /* 0x90: APB_MISC_GP_DAP1CFGPADCTRL */ u32 dap2cfg; /* 0x94: APB_MISC_GP_DAP2CFGPADCTRL */ u32 dap3cfg; /* 0x98: APB_MISC_GP_DAP3CFGPADCTRL */ u32 dap4cfg; /* 0x9C: APB_MISC_GP_DAP4CFGPADCTRL */ u32 dbgcfg; /* 0xA0: APB_MISC_GP_DBGCFGPADCTRL */ - u32 lcdcfg1; /* 0xA4: APB_MISC_GP_LCDCFG1PADCTRL */ - u32 lcdcfg2; /* 0xA8: APB_MISC_GP_LCDCFG2PADCTRL */ - u32 sdio2cfg; /* 0xAC: APB_MISC_GP_SDIO2CFGPADCTRL */ + u32 reserved2[3]; /* 0xA4 - 0xAC: */ u32 sdio3cfg; /* 0xB0: APB_MISC_GP_SDIO3CFGPADCTRL */ u32 spicfg; /* 0xB4: APB_MISC_GP_SPICFGPADCTRL */ u32 uaacfg; /* 0xB8: APB_MISC_GP_UAACFGPADCTRL */ u32 uabcfg; /* 0xBC: APB_MISC_GP_UABCFGPADCTRL */ u32 uart2cfg; /* 0xC0: APB_MISC_GP_UART2CFGPADCTRL */ u32 uart3cfg; /* 0xC4: APB_MISC_GP_UART3CFGPADCTRL */ - u32 vicfg1; /* 0xC8: APB_MISC_GP_VICFG1PADCTRL */ - u32 vivttgen; /* 0xCC: APB_MISC_GP_VIVTTGENPADCTRL */ - u32 reserved1[7]; /* 0xD0-0xE8: */ + u32 reserved3[9]; /* 0xC8-0xE8: */ u32 sdio1cfg; /* 0xEC: APB_MISC_GP_SDIO1CFGPADCTRL */ + u32 reserved4[3]; /* 0xF0-0xF8: */ + u32 ddccfg; /* 0xFC: APB_MISC_GP_DDCCFGPADCTRL */ + u32 gmacfg; /* 0x100: APB_MISC_GP_GMACFGPADCTRL */ + u32 reserved5[3]; /* 0x104-0x10C: */ + u32 gmecfg; /* 0x110: APB_MISC_GP_GMECFGPADCTRL */ + u32 gmfcfg; /* 0x114: APB_MISC_GP_GMFCFGPADCTRL */ + u32 gmgcfg; /* 0x118: APB_MISC_GP_GMGCFGPADCTRL */ + u32 gmhcfg; /* 0x11C: APB_MISC_GP_GMHCFGPADCTRL */ + u32 owrcfg; /* 0x120: APB_MISC_GP_OWRCFGPADCTRL */ + u32 uadcfg; /* 0x124: APB_MISC_GP_UADCFGPADCTRL */ + u32 reserved6; /* 0x128: */ + u32 dev3cfg; /* 0x12C: APB_MISC_GP_DEV3CFGPADCTRL */ + u32 reserved7[2]; /* 0x130 - 0x134: */ + u32 ceccfg; /* 0x138: APB_MISC_GP_CECCFGPADCTRL */ + u32 reserved8[22]; /* 0x13C - 0x190: */ + u32 atcfg6; /* 0x194: APB_MISC_GP_ATCFG6PADCTRL */ + u32 dap5cfg; /* 0x198: APB_MISC_GP_DAP5CFGPADCTRL */ + u32 vbuscfg; /* 0x19C: APB_MISC_GP_USBVBUSENCFGPADCTRL */ + u32 aocfg3; /* 0x1A0: APB_MISC_GP_AOCFG3PADCTRL */ + u32 hvccfg0; /* 0x1A4: APB_MISC_GP_HVCCFG0PADCTRL */ + u32 sdio4cfg; /* 0x1A8: APB_MISC_GP_SDIO4CFGPADCTRL */ + u32 aocfg0; /* 0x1AC: APB_MISC_GP_AOCFG0PADCTRL */ }; #endif /* _TEGRA114_GP_PADCTRL_H_ */ From f31a5443a8b52a613fcafc0330a303420eafcca4 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Wed, 13 Mar 2013 15:40:33 -0700 Subject: [PATCH 37/39] Tegra114: Dalmore: Always use DEFAULT instead of DISABLE for lock bits The pinmux code issues a warning if the caller attempts to disable the lock bit in a pinmux register, since this is impossible (once it's locked, the only way to unlock it is to reset the device/pmt controller). The I2C/DDC/CEC/USB macros expect a lock setting to be passed in, and the previous setting of DISABLE caused the pinmux table parsing code to issue the warning. Changing the lock bits in these table entries to DEFAULT (i.e. don't touch it) fixes this. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- board/nvidia/dalmore/pinmux-config-dalmore.h | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/board/nvidia/dalmore/pinmux-config-dalmore.h b/board/nvidia/dalmore/pinmux-config-dalmore.h index d25881908d..cb48b3ba1f 100644 --- a/board/nvidia/dalmore/pinmux-config-dalmore.h +++ b/board/nvidia/dalmore/pinmux-config-dalmore.h @@ -120,8 +120,8 @@ static struct pingroup_config tegra114_pinmux_common[] = { DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, OUTPUT), /* I2C3 pinmux */ - I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), + I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), /* VI pinmux */ VI_PINMUX(CAM_MCLK, VI_ALT3, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), @@ -133,8 +133,8 @@ static struct pingroup_config tegra114_pinmux_common[] = { VI_PINMUX(GPIO_PBB4, VGP4, NORMAL, NORMAL, OUTPUT, DEFAULT, DEFAULT), /* I2C2 pinmux */ - I2C_PINMUX(GEN2_I2C_SCL, I2C2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - I2C_PINMUX(GEN2_I2C_SDA, I2C2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(GEN2_I2C_SCL, I2C2, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), + I2C_PINMUX(GEN2_I2C_SDA, I2C2, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), /* UARTD pinmux */ DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), @@ -212,8 +212,8 @@ static struct pingroup_config tegra114_pinmux_common[] = { DEFAULT_PINMUX(KB_ROW9, UARTA, NORMAL, NORMAL, OUTPUT), /* I2CPWR pinmux (I2C5) */ - I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), + I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), /* SYSCLK pinmux */ DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, OUTPUT), @@ -240,8 +240,8 @@ static struct pingroup_config tegra114_pinmux_common[] = { DEFAULT_PINMUX(CLK3_OUT, EXTPERIPH3, NORMAL, NORMAL, OUTPUT), /* I2C1 pinmux */ - I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), + I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), /* UARTB pinmux */ DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, TRISTATE, INPUT), @@ -261,14 +261,14 @@ static struct pingroup_config tegra114_pinmux_common[] = { DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT), /* CEC pinmux */ - CEC_PINMUX(HDMI_CEC, CEC, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + CEC_PINMUX(HDMI_CEC, CEC, NORMAL, NORMAL, INPUT, DEFAULT, DISABLE), /* I2C4 pinmux */ - DDC_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DISABLE, HIGH), - DDC_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DISABLE, HIGH), + DDC_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DEFAULT, HIGH), + DDC_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DEFAULT, HIGH), /* USB pinmux */ - USB_PINMUX(USB_VBUS_EN0, USB, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + USB_PINMUX(USB_VBUS_EN0, USB, NORMAL, NORMAL, INPUT, DEFAULT, ENABLE), /* nct */ DEFAULT_PINMUX(GPIO_X6_AUD, SPI6, UP, TRISTATE, INPUT), From 5647c0343176d8ea257abf44211c493ef139d3e8 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Mon, 11 Mar 2013 17:07:21 -0700 Subject: [PATCH 38/39] Tegra114: fdt: Move aliases from dtsi to dts file as per other Tegras All other Tegra boards have their alias nodes in the .dts file Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/dts/tegra114.dtsi | 8 -------- board/nvidia/dts/tegra114-dalmore.dts | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/dts/tegra114.dtsi b/arch/arm/dts/tegra114.dtsi index dfeac53f72..701c0f9aff 100644 --- a/arch/arm/dts/tegra114.dtsi +++ b/arch/arm/dts/tegra114.dtsi @@ -3,14 +3,6 @@ / { compatible = "nvidia,tegra114"; - aliases { - i2c0 = "/i2c@7000d000"; - i2c1 = "/i2c@7000c000"; - i2c2 = "/i2c@7000c400"; - i2c3 = "/i2c@7000c500"; - i2c4 = "/i2c@7000c700"; - }; - tegra_car: clock { compatible = "nvidia,tegra114-car"; reg = <0x60006000 0x1000>; diff --git a/board/nvidia/dts/tegra114-dalmore.dts b/board/nvidia/dts/tegra114-dalmore.dts index 3e1e1eaff8..30cf1fb730 100644 --- a/board/nvidia/dts/tegra114-dalmore.dts +++ b/board/nvidia/dts/tegra114-dalmore.dts @@ -6,6 +6,14 @@ model = "NVIDIA Dalmore"; compatible = "nvidia,dalmore", "nvidia,tegra114"; + aliases { + i2c0 = "/i2c@7000d000"; + i2c1 = "/i2c@7000c000"; + i2c2 = "/i2c@7000c400"; + i2c3 = "/i2c@7000c500"; + i2c4 = "/i2c@7000c700"; + }; + memory { device_type = "memory"; reg = <0x80000000 0x80000000>; From 477393e7875cf4261f107fdfb8887309ea7fc3f7 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Mon, 11 Mar 2013 16:43:49 -0700 Subject: [PATCH 39/39] Tegra114: Dalmore: Add pad config tables/code based on pinmux code Pad config registers exist in APB_MISC_GP space, and control slew rate, drive strengh, schmidt, high-speed, and low-power modes for all of the pingroups in Tegra30. This builds off of the pinmux way of constructing init tables to configure select pads (SDIOCFG, for instance) during pinmux_init(). Currently, no padcfg entries exist. SDIO3CFG will be added when the MMC driver is added as per the TRM to work with the SD-card slot on Dalmore E1611. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/cpu/tegra114-common/pinmux.c | 194 +++++++++++++++++++ arch/arm/include/asm/arch-tegra114/pinmux.h | 100 ++++++++-- board/nvidia/dalmore/pinmux-config-dalmore.h | 12 ++ 3 files changed, 292 insertions(+), 14 deletions(-) diff --git a/arch/arm/cpu/tegra114-common/pinmux.c b/arch/arm/cpu/tegra114-common/pinmux.c index 16368c5bc1..4983a05090 100644 --- a/arch/arm/cpu/tegra114-common/pinmux.c +++ b/arch/arm/cpu/tegra114-common/pinmux.c @@ -39,6 +39,19 @@ struct tegra_pingroup_desc { #define PMUX_IO_RESET_SHIFT 8 #define PMUX_RCV_SEL_SHIFT 9 +#define PGRP_HSM_SHIFT 2 +#define PGRP_SCHMT_SHIFT 3 +#define PGRP_LPMD_SHIFT 4 +#define PGRP_LPMD_MASK (3 << PGRP_LPMD_SHIFT) +#define PGRP_DRVDN_SHIFT 12 +#define PGRP_DRVDN_MASK (0x7F << PGRP_DRVDN_SHIFT) +#define PGRP_DRVUP_SHIFT 20 +#define PGRP_DRVUP_MASK (0x7F << PGRP_DRVUP_SHIFT) +#define PGRP_SLWR_SHIFT 28 +#define PGRP_SLWR_MASK (3 << PGRP_SLWR_SHIFT) +#define PGRP_SLWF_SHIFT 30 +#define PGRP_SLWF_MASK (3 << PGRP_SLWF_SHIFT) + /* Convenient macro for defining pin group properties */ #define PIN(pg_name, vdd, f0, f1, f2, f3, iod) \ { \ @@ -544,3 +557,184 @@ void pinmux_config_table(struct pingroup_config *config, int len) for (i = 0; i < len; i++) pinmux_config_pingroup(&config[i]); } + +static int padgrp_set_drvup_slwf(enum pdrive_pingrp pad, int slwf) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_slwf = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and slwf */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_slw_isvalid(slwf)); + + /* NONE means unspecified/do not change/use POR value */ + if (slwf == PGRP_SLWF_NONE) + return 0; + + reg = readl(pad_slwf); + reg &= ~PGRP_SLWF_MASK; + reg |= (slwf << PGRP_SLWF_SHIFT); + writel(reg, pad_slwf); + + return 0; +} + +static int padgrp_set_drvdn_slwr(enum pdrive_pingrp pad, int slwr) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_slwr = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and slwr */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_slw_isvalid(slwr)); + + /* NONE means unspecified/do not change/use POR value */ + if (slwr == PGRP_SLWR_NONE) + return 0; + + reg = readl(pad_slwr); + reg &= ~PGRP_SLWR_MASK; + reg |= (slwr << PGRP_SLWR_SHIFT); + writel(reg, pad_slwr); + + return 0; +} + +static int padgrp_set_drvup(enum pdrive_pingrp pad, int drvup) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_drvup = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and drvup */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_drv_isvalid(drvup)); + + /* NONE means unspecified/do not change/use POR value */ + if (drvup == PGRP_DRVUP_NONE) + return 0; + + reg = readl(pad_drvup); + reg &= ~PGRP_DRVUP_MASK; + reg |= (drvup << PGRP_DRVUP_SHIFT); + writel(reg, pad_drvup); + + return 0; +} + +static int padgrp_set_drvdn(enum pdrive_pingrp pad, int drvdn) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_drvdn = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check on pad and drvdn */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_drv_isvalid(drvdn)); + + /* NONE means unspecified/do not change/use POR value */ + if (drvdn == PGRP_DRVDN_NONE) + return 0; + + reg = readl(pad_drvdn); + reg &= ~PGRP_DRVDN_MASK; + reg |= (drvdn << PGRP_DRVDN_SHIFT); + writel(reg, pad_drvdn); + + return 0; +} + +static int padgrp_set_lpmd(enum pdrive_pingrp pad, enum pgrp_lpmd lpmd) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_lpmd = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check pad and lpmd value */ + assert(pmux_padgrp_isvalid(pad)); + assert(pmux_pad_lpmd_isvalid(lpmd)); + + /* NONE means unspecified/do not change/use POR value */ + if (lpmd == PGRP_LPMD_NONE) + return 0; + + reg = readl(pad_lpmd); + reg &= ~PGRP_LPMD_MASK; + reg |= (lpmd << PGRP_LPMD_SHIFT); + writel(reg, pad_lpmd); + + return 0; +} + +static int padgrp_set_schmt(enum pdrive_pingrp pad, enum pgrp_schmt schmt) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_schmt = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check pad */ + assert(pmux_padgrp_isvalid(pad)); + + /* NONE means unspecified/do not change/use POR value */ + if (schmt == PGRP_SCHMT_NONE) + return 0; + + reg = readl(pad_schmt); + reg &= ~(1 << PGRP_SCHMT_SHIFT); + if (schmt == PGRP_SCHMT_ENABLE) + reg |= (0x1 << PGRP_SCHMT_SHIFT); + writel(reg, pad_schmt); + + return 0; +} +static int padgrp_set_hsm(enum pdrive_pingrp pad, enum pgrp_hsm hsm) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + u32 *pad_hsm = &pmt->pmt_drive[pad]; + u32 reg; + + /* Error check pad */ + assert(pmux_padgrp_isvalid(pad)); + + /* NONE means unspecified/do not change/use POR value */ + if (hsm == PGRP_HSM_NONE) + return 0; + + reg = readl(pad_hsm); + reg &= ~(1 << PGRP_HSM_SHIFT); + if (hsm == PGRP_HSM_ENABLE) + reg |= (0x1 << PGRP_HSM_SHIFT); + writel(reg, pad_hsm); + + return 0; +} + +void padctrl_config_pingroup(struct padctrl_config *config) +{ + enum pdrive_pingrp pad = config->padgrp; + + padgrp_set_drvup_slwf(pad, config->slwf); + padgrp_set_drvdn_slwr(pad, config->slwr); + padgrp_set_drvup(pad, config->drvup); + padgrp_set_drvdn(pad, config->drvdn); + padgrp_set_lpmd(pad, config->lpmd); + padgrp_set_schmt(pad, config->schmt); + padgrp_set_hsm(pad, config->hsm); +} + +void padgrp_config_table(struct padctrl_config *config, int len) +{ + int i; + + for (i = 0; i < len; i++) + padctrl_config_pingroup(&config[i]); +} diff --git a/arch/arm/include/asm/arch-tegra114/pinmux.h b/arch/arm/include/asm/arch-tegra114/pinmux.h index 53905cb8e9..9c22c08b6e 100644 --- a/arch/arm/include/asm/arch-tegra114/pinmux.h +++ b/arch/arm/include/asm/arch-tegra114/pinmux.h @@ -215,34 +215,35 @@ enum pdrive_pingrp { PDRIVE_PINGROUP_AT5, PDRIVE_PINGROUP_CDEV1, PDRIVE_PINGROUP_CDEV2, - PDRIVE_PINGROUP_CSUS, - PDRIVE_PINGROUP_DAP1, + PDRIVE_PINGROUP_DAP1 = 10, /* offset 0x890 */ PDRIVE_PINGROUP_DAP2, PDRIVE_PINGROUP_DAP3, PDRIVE_PINGROUP_DAP4, PDRIVE_PINGROUP_DBG, - PDRIVE_PINGROUP_SDIO3, + PDRIVE_PINGROUP_SDIO3 = 18, /* offset 0x8B0 */ PDRIVE_PINGROUP_SPI, PDRIVE_PINGROUP_UAA, PDRIVE_PINGROUP_UAB, PDRIVE_PINGROUP_UART2, PDRIVE_PINGROUP_UART3, - PDRIVE_PINGROUP_SDIO1 = 33, /* offset 0x8ec */ - PDRIVE_PINGROUP_CRT = 36, /* offset 0x8f8 */ - PDRIVE_PINGROUP_DDC, + PDRIVE_PINGROUP_SDIO1 = 33, /* offset 0x8EC */ + PDRIVE_PINGROUP_DDC = 37, /* offset 0x8FC */ PDRIVE_PINGROUP_GMA, - PDRIVE_PINGROUP_GME, + PDRIVE_PINGROUP_GME = 42, /* offset 0x910 */ PDRIVE_PINGROUP_GMF, PDRIVE_PINGROUP_GMG, PDRIVE_PINGROUP_GMH, PDRIVE_PINGROUP_OWR, PDRIVE_PINGROUP_UAD, - PDRIVE_PINGROUP_GPV, PDRIVE_PINGROUP_DEV3 = 49, /* offset 0x92c */ PDRIVE_PINGROUP_CEC = 52, /* offset 0x938 */ - PDRIVE_PINGROUP_AT6, + PDRIVE_PINGROUP_AT6 = 75, /* offset 0x994 */ PDRIVE_PINGROUP_DAP5, PDRIVE_PINGROUP_VBUS, + PDRIVE_PINGROUP_AO3, + PDRIVE_PINGROUP_HVC, + PDRIVE_PINGROUP_SDIO4, + PDRIVE_PINGROUP_AO0, PDRIVE_PINGROUP_COUNT, }; @@ -470,10 +471,73 @@ enum pmux_vddio { PMUX_VDDIO_NONE }; -/* T114 pin drive group and pin mux registers */ -#define PDRIVE_PINGROUP_OFFSET (0x868 >> 2) -#define PMUX_OFFSET ((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \ - PDRIVE_PINGROUP_COUNT) +#define PGRP_SLWF_NONE -1 +#define PGRP_SLWF_MAX 3 +#define PGRP_SLWR_NONE PGRP_SLWF_NONE +#define PGRP_SLWR_MAX PGRP_SLWF_MAX + +#define PGRP_DRVUP_NONE -1 +#define PGRP_DRVUP_MAX 127 +#define PGRP_DRVDN_NONE PGRP_DRVUP_NONE +#define PGRP_DRVDN_MAX PGRP_DRVUP_MAX + +#define PGRP_SCHMT_NONE -1 +#define PGRP_HSM_NONE PGRP_SCHMT_NONE + +/* return 1 if a padgrp is in range */ +#define pmux_padgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PDRIVE_PINGROUP_COUNT)) + +/* return 1 if a slew-rate rising/falling edge value is in range */ +#define pmux_pad_slw_isvalid(slw) (((slw) == PGRP_SLWF_NONE) || \ + (((slw) >= 0) && ((slw) <= PGRP_SLWF_MAX))) + +/* return 1 if a driver output pull-up/down strength code value is in range */ +#define pmux_pad_drv_isvalid(drv) (((drv) == PGRP_DRVUP_NONE) || \ + (((drv) >= 0) && ((drv) <= PGRP_DRVUP_MAX))) + +/* return 1 if a low-power mode value is in range */ +#define pmux_pad_lpmd_isvalid(lpm) (((lpm) == PGRP_LPMD_NONE) || \ + (((lpm) >= 0) && ((lpm) <= PGRP_LPMD_X))) + +/* Defines a pin group cfg's low-power mode select */ +enum pgrp_lpmd { + PGRP_LPMD_X8 = 0, + PGRP_LPMD_X4, + PGRP_LPMD_X2, + PGRP_LPMD_X, + PGRP_LPMD_NONE = -1, +}; + +/* Defines whether a pin group cfg's schmidt is enabled or not */ +enum pgrp_schmt { + PGRP_SCHMT_DISABLE = 0, + PGRP_SCHMT_ENABLE = 1, +}; + +/* Defines whether a pin group cfg's high-speed mode is enabled or not */ +enum pgrp_hsm { + PGRP_HSM_DISABLE = 0, + PGRP_HSM_ENABLE = 1, +}; + +/* + * This defines the configuration for a pin group's pad control config + */ +struct padctrl_config { + enum pdrive_pingrp padgrp; /* pin group PDRIVE_PINGRP_x */ + int slwf; /* falling edge slew */ + int slwr; /* rising edge slew */ + int drvup; /* pull-up drive strength */ + int drvdn; /* pull-down drive strength */ + enum pgrp_lpmd lpmd; /* low-power mode selection */ + enum pgrp_schmt schmt; /* schmidt enable */ + enum pgrp_hsm hsm; /* high-speed mode enable */ +}; + +/* t114 pin drive group and pin mux registers */ +#define PDRIVE_PINGROUP_OFFSET (0x868 >> 2) +#define PMUX_OFFSET ((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \ + PDRIVE_PINGROUP_COUNT) struct pmux_tri_ctlr { uint pmt_reserved0; /* ABP_MISC_PP_ reserved offset 00 */ uint pmt_reserved1; /* ABP_MISC_PP_ reserved offset 04 */ @@ -541,4 +605,12 @@ void pinmux_config_table(struct pingroup_config *config, int len); /* Set a group of pins from a table */ void pinmux_init(void); -#endif /* _TEGRA114_PINMUX_H_ */ +/** + * Set the GP pad configs + * + * @param config List of config items + * @param len Number of config items in list + */ +void padgrp_config_table(struct padctrl_config *config, int len); + +#endif /* _TEGRA114_PINMUX_H_ */ diff --git a/board/nvidia/dalmore/pinmux-config-dalmore.h b/board/nvidia/dalmore/pinmux-config-dalmore.h index cb48b3ba1f..3ef6f4eaf6 100644 --- a/board/nvidia/dalmore/pinmux-config-dalmore.h +++ b/board/nvidia/dalmore/pinmux-config-dalmore.h @@ -79,6 +79,18 @@ #define USB_PINMUX CEC_PINMUX +#define DEFAULT_PADCFG(_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) \ + { \ + .padgrp = PDRIVE_PINGROUP_##_padgrp, \ + .slwf = _slwf, \ + .slwr = _slwr, \ + .drvup = _drvup, \ + .drvdn = _drvdn, \ + .lpmd = PGRP_LPMD_##_lpmd, \ + .schmt = PGRP_SCHMT_##_schmt, \ + .hsm = PGRP_HSM_##_hsm, \ + } + static struct pingroup_config tegra114_pinmux_common[] = { /* EXTPERIPH1 pinmux */ DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT),