diff options
author | Gary King <gking@nvidia.com> | 2010-05-14 10:36:33 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-14 20:04:06 -0700 |
commit | 106de33bf7f410bade659e110a5a7b187b46b8b2 (patch) | |
tree | 4d8231dc38fb3c05b6ccb911ff1e3b840d1d444b /arch/arm/mach-tegra/odm_kit/adaptations | |
parent | e0426ba3077eae7e326c56487f34719f9638ddb5 (diff) |
[ARM/tegra] add NvRm, ODM services, ODM kit for harmony & whistler
add power rail support to GPIO driver
Change-Id: I45d4c1110a635047d68fb14f3e72a28f99acbe1b
Diffstat (limited to 'arch/arm/mach-tegra/odm_kit/adaptations')
95 files changed, 18446 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/Makefile new file mode 100644 index 000000000000..9b0d46744489 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/Makefile @@ -0,0 +1,4 @@ +obj-y += gpio_ext/ +obj-y += tmon/ +obj-y += pmu/ +obj-y += misc/ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/Makefile new file mode 100644 index 000000000000..8500f4a6779a --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/Makefile @@ -0,0 +1,12 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +obj-y += gpio_ext_hal.o +obj-y += gpio_ext_null.o +obj-y += gpio_pcf50626.o diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_hal.c b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_hal.c new file mode 100644 index 000000000000..c53fad2da1cd --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_hal.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvcommon.h" +#include "nvodm_query_discovery.h" +#include "nvodm_gpio_ext.h" +#include "nvodm_services.h" +#include "gpio_ext_hal.h" +#include "gpio_ext_null.h" +#include "gpio_pcf50626.h" + +void +NvOdmExternalGpioWritePins( + NvU32 Port, + NvU32 Pin, + NvU32 PinValue) +{ + static NvBool IsInit = NV_FALSE; + static NvOdmGpioExtDevice GpioExtDevice; + + if (!IsInit) + { + NvOdmOsMemset(&GpioExtDevice, 0, sizeof(GpioExtDevice)); + if (NvOdmPeripheralGetGuid(NV_ODM_GUID('p','c','f','_','p','m','u','0'))) + { + // fill in HAL function here. + GpioExtDevice.pfnWritePins = GPIO_PCF50626_NvOdmExternalGpioWritePins; + } + else + { + // NULL implementation + GpioExtDevice.pfnWritePins = null_NvOdmExternalGpioWritePins; + } + IsInit = NV_TRUE; + } + GpioExtDevice.pfnWritePins(Port, Pin, PinValue); +} + +NvU32 +NvOdmExternalGpioReadPins( + NvU32 Port, + NvU32 Pin) +{ + static NvBool IsInit = NV_FALSE; + static NvOdmGpioExtDevice GpioExtDevice; + + if (!IsInit) + { + NvOdmOsMemset(&GpioExtDevice, 0, sizeof(GpioExtDevice)); + if (NvOdmPeripheralGetGuid(NV_ODM_GUID('p','c','f','_','p','m','u','0'))) + { + // fill in HAL function here. + GpioExtDevice.pfnReadPins = GPIO_PCF50626_NvOdmExternalGpioReadPins; + } + else + { + // NULL implementation + GpioExtDevice.pfnReadPins = null_NvOdmExternalGpioReadPins; + } + IsInit = NV_TRUE; + } + return GpioExtDevice.pfnReadPins(Port, Pin); +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_hal.h b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_hal.h new file mode 100644 index 000000000000..e1ca2c1182f9 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_hal.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * <b>NVIDIA Tegra ODM Kit: + * Abstraction layer stub for external gpio + * adaptation</b> + */ + +#ifndef INCLUDED_NVODM_GPIO_EXT_ADAPTATION_HAL_H +#define INCLUDED_NVODM_GPIO_EXT_ADAPTATION_HAL_H + +#include "nvodm_gpio_ext.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +// A simple HAL for the External GPIO adaptations. +typedef void (*pfnExternalGpioWritePins)(NvU32, NvU32, NvU32); +typedef NvU32 (*pfnExternalGpioReadPins)(NvU32, NvU32); + +typedef struct NvOdmGpioExtDeviceRec +{ + pfnExternalGpioWritePins pfnWritePins; + pfnExternalGpioReadPins pfnReadPins; + +} NvOdmGpioExtDevice; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_null.c b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_null.c new file mode 100644 index 000000000000..4957b099484a --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_null.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_gpio_ext.h" +#include "gpio_ext_null.h" + +void +null_NvOdmExternalGpioWritePins( + NvU32 Port, + NvU32 Pin, + NvU32 PinValue) +{ + // NULL implementation that does nothing. + return; +} + +NvU32 +null_NvOdmExternalGpioReadPins( + NvU32 Port, + NvU32 Pin) +{ + // NULL implementation that does nothing. + return 0; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_null.h b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_null.h new file mode 100644 index 000000000000..6e38bb31f121 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_ext_null.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_GPIO_EXT_NULL_H +#define INCLUDED_GPIO_EXT_NULL_H + +#include "gpio_ext_hal.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +void null_NvOdmExternalGpioWritePins(NvU32, NvU32, NvU32); +NvU32 null_NvOdmExternalGpioReadPins(NvU32, NvU32); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_pcf50626.c b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_pcf50626.c new file mode 100644 index 000000000000..5f41b8aee053 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_pcf50626.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_services.h" +#include "nvassert.h" +#include "nvodm_gpio_ext.h" +#include "gpio_pcf50626.h" + +#if NV_DEBUG +#define ASSERT_SUCCESS( expr ) \ + do { \ + NvBool b = (expr); \ + NV_ASSERT( b == NV_TRUE ); \ + } while( 0 ) +#else +#define ASSERT_SUCCESS( expr ) \ + do { \ + (void)(expr); \ + } while( 0 ) +#endif + +static NvOdmServicesI2cHandle s_hOdmI2c = NULL; + +#define PCF50626_I2C_SPEED_KHZ 400 +#define PCF50626_DEVICE_ADDR 0xE0 +#define PCF50626_GPO2C1_ADDR 0x55 +#define PCF50626_PWM1S_ADDR 0x2D +#define PCF50626_PWM1D_ADDR 0x2E + +static NvBool GPIO_PCF50626_I2cWrite8(NvU8 Addr, NvU8 Data); + +void +GPIO_PCF50626_NvOdmExternalGpioWritePins( + NvU32 Port, + NvU32 Pin, + NvU32 PinValue) +{ + NvU8 val; + NvBool RetVal = NV_TRUE; + + switch (Port) + { + case NVODM_GPIO_EXT_PORT_2: + if (Pin != 1) // Only Pin 1 is implemented at this time + break; + + if (PinValue) // Enable + { + val = (1UL << 6) // invert polarity + | 0x3; // pwm1 output + RetVal = GPIO_PCF50626_I2cWrite8(PCF50626_GPO2C1_ADDR, val); + } + else // Disable + { + RetVal = GPIO_PCF50626_I2cWrite8(PCF50626_GPO2C1_ADDR, 0x0); + } + break; + } + + if (RetVal == NV_FALSE) + { + NvOdmOsDebugPrintf("ERROR: GPIO_PCF50626_I2cWrite8() failed.\n"); + } + + return; +} + +NvU32 +GPIO_PCF50626_NvOdmExternalGpioReadPins( + NvU32 Port, + NvU32 Pin) +{ + // Implement external GPIO port read routine here. + return 0; +} + +static NvBool GPIO_PCF50626_I2cWrite8( + NvU8 Addr, + NvU8 Data) +{ + NvBool RetVal = NV_TRUE; + NvU8 WriteBuffer[2]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + NvOdmI2cTransactionInfo TransactionInfo; + NvU32 DeviceAddr = (NvU32)PCF50626_DEVICE_ADDR; + + s_hOdmI2c = NvOdmI2cOpen(NvOdmIoModule_I2c_Pmu, 0); + if (!s_hOdmI2c) + { + RetVal = NV_FALSE; + goto GPIO_PCF50626_I2cWrite8_exit; + } + + WriteBuffer[0] = Addr & 0xFF; // PMU offset + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = DeviceAddr; + TransactionInfo.Buf = WriteBuffer; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(s_hOdmI2c, &TransactionInfo, 1, + PCF50626_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + RetVal = NV_TRUE; + else + RetVal = NV_FALSE; + +GPIO_PCF50626_I2cWrite8_exit: + NvOdmI2cClose(s_hOdmI2c); + s_hOdmI2c = NULL; + return RetVal; +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_pcf50626.h b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_pcf50626.h new file mode 100644 index 000000000000..4f78bff05e3f --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/gpio_ext/gpio_pcf50626.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_GPIO_PCF50626_H +#define INCLUDED_GPIO_PCF50626_H + +#include "gpio_ext_hal.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +void +GPIO_PCF50626_NvOdmExternalGpioWritePins( + NvU32 Port, + NvU32 Pin, + NvU32 PinValue); + +NvU32 +GPIO_PCF50626_NvOdmExternalGpioReadPins( + NvU32 Port, + NvU32 Pin); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/misc/Makefile new file mode 100644 index 000000000000..61c287105a48 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_TEGRA_ODM_HARMONY) += harmony/ +obj-$(CONFIG_TEGRA_ODM_WHISTLER) += whistler/ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/Makefile new file mode 100644 index 000000000000..12af02178d7f --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/Makefile @@ -0,0 +1,14 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +obj-$(CONFIG_KEYBOARD_TEGRA) += nvodm_kbc.o +obj-$(CONFIG_KEYBOARD_TEGRA) += nvodm_kbc_keymapping.o +obj-y += nvodm_sdio.o +obj-y += nvodm_uart.o +obj-y += nvodm_usbulpi.o diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_kbc.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_kbc.c new file mode 100644 index 000000000000..3f07a61a66c4 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_kbc.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2008-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file Nvodm_Kbc.c + * @brief <b>KBC odm implementation</b> + * + * @Description : Implementation of the odm KBC API + */ +#include "nvodm_kbc.h" +#include "../../../query/harmony/nvodm_query_kbc_qwerty_def.h" + +NvU32 +NvOdmKbcFilterKeys( + NvU32 *pRows, + NvU32 *pCols, + NvU32 NumOfKeysPressed) +{ + NvBool IsFunctionKeyFound = NV_FALSE; + NvU32 KeyIndex; + + for (KeyIndex = 0; KeyIndex < NumOfKeysPressed; ++KeyIndex) + { + if ((pRows[KeyIndex] == KBC_QWERTY_FUNCTION_KEY_ROW_NUMBER) && + (pCols[KeyIndex] == KBC_QWERTY_FUNCTION_KEY_COLUMN_NUMBER)) + { + IsFunctionKeyFound = NV_TRUE; + break; + } + } + if (!IsFunctionKeyFound) + return NumOfKeysPressed; + + // Add function row base to treat as special case + for (KeyIndex = 0; KeyIndex < NumOfKeysPressed; ++KeyIndex) + pRows[KeyIndex] += KBC_QWERTY_FUNCTION_KEY_ROW_BASE; + + return NumOfKeysPressed; +} + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_kbc_keymapping.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_kbc_keymapping.c new file mode 100644 index 000000000000..1b316bc511e8 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_kbc_keymapping.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * <b>NVIDIA Tegra ODM Kit: + * Keyboard Controller virtual key mapping</b> + * + * @b Description: Implement the ODM keyboard mapping to the platform + * specific. + */ +#include "nvodm_kbc_keymapping.h" +#include <linux/input.h> + + +#define KBC_QWERTY_NORMAL_KEY_CODE_BASE 0x1000 +#define KBC_QWERTY_FUNCTION_KEY_CODE_BASE 0x2000 + +#define KBC_QWERTY_FUNCTION_KEY_ROW_BASE 0x100 +#define KBC_QWERTY_FUNCTION_KEY_ROW_NUMBER 0 +#define KBC_QWERTY_FUNCTION_KEY_COLUMN_NUMBER 7 + +/** + * @brief Scan Code to Virtual Key mappings. + */ + + +/* The total number of soc scan codes will be (first - last) */ +#define NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_FIRST KBC_QWERTY_NORMAL_KEY_CODE_BASE +#define NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_LAST (KBC_QWERTY_NORMAL_KEY_CODE_BASE +0x7F) + +#define NV_SOC_FUNCTION_KEY_SCAN_CODE_TABLE_FIRST KBC_QWERTY_FUNCTION_KEY_CODE_BASE +#define NV_SOC_FUNCTION_KEY_SCAN_CODE_TABLE_LAST (KBC_QWERTY_FUNCTION_KEY_CODE_BASE +0x7F) + +/** + * @brief This is the actual Scan-code-to-VKey mapping table. For new layouts + * this is the only structure which needs to be modified to return the + * proper vkey depending on the scan code. + */ + +#define KEY_UNUSED 0 + +static NvU32 ScanCodeToVKeyTableKbcQwertyNormal[] = +{ + // Row 0-> Unused, Unused, 'W', 'S', 'A', 'Z', Unused, Function, + // Row 1 ->Unused, Unused, Unused, Unused, Unused, unused, Unused, WIN_SPECIAL + // Row 2 ->Unused, Unused, Unused, Unused, Unused, unused, Alt, Alt2 + // Row 3 ->'5', '4', 'R', 'E', 'F', 'D', 'X', Unused, + // Row 4 ->'7', '6', 'T', 'H', 'G', 'V', 'C', SPACEBAR, + // Row 5 ->'9', '8', 'U', 'Y', 'J', 'N', 'B', '|\', + // Row 6 ->Minus, '0', 'O', 'I', 'L', 'K', '<', M, + // Row 7 ->unused, '+', '}]', '#', Unused, Unused, Unused, WinSpecial, + // Row 8 ->Unused, Unused, Unused, Unused, SHIFT, SHIFT, UnUsed, Unused , + // Row 9 ->Unused, Unused, Unused, Unused, unused, Ctrl, UnUsed, Control, + // Row A ->Unused, Unused, Unused, Unused, unused, unused, UnUsed, Unused, + // Row B ->'{[', 'P', '"', ':;', '/?, '>', UnUsed, Unused, + // Row C ->'F10', 'F9', 'BckSpc','3', '2', 'Up, Prntscr,Pause + // Row D ->INS, DEL, Unused, Pgup, PgDn, right, Down, Left, + // Row E ->F11, F12, F8, 'Q', F4, F3, '1', F7, + // Row F ->ESC, '~', F5, TAB, F1, F2, CAPLOCK,F6, + KEY_UNUSED, KEY_UNUSED, KEY_W, KEY_S, + KEY_A, KEY_Z, KEY_UNUSED, KEY_FN, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_MENU, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_LEFTALT, KEY_RIGHTALT, + KEY_5, KEY_4, KEY_R, KEY_E, + KEY_F, KEY_D, KEY_X, KEY_UNUSED, + KEY_7, KEY_6, KEY_T, KEY_H, + KEY_G, KEY_V, KEY_C, KEY_SPACE, + KEY_9, KEY_8, KEY_U, KEY_Y, + KEY_J, KEY_N, KEY_B, KEY_BACKSLASH, + KEY_MINUS, KEY_0, KEY_O, KEY_I, + KEY_L, KEY_K, KEY_COMMA, KEY_M, + KEY_UNUSED, KEY_EQUAL, KEY_RIGHTBRACE, KEY_ENTER, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_MENU, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_LEFTSHIFT, KEY_RIGHTSHIFT, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_LEFTCTRL, KEY_UNUSED, KEY_RIGHTCTRL, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_LEFTBRACE, KEY_P, KEY_APOSTROPHE, KEY_SEMICOLON, + KEY_SLASH, KEY_DOT, KEY_UNUSED, KEY_UNUSED, + KEY_F10, KEY_F9, KEY_BACKSPACE, KEY_3, + KEY_2, KEY_UP, KEY_PRINT, KEY_PAUSE, + KEY_INSERT, KEY_DELETE, KEY_UNUSED, KEY_PAGEUP, + KEY_PAGEDOWN, KEY_RIGHT, KEY_DOWN, KEY_LEFT, + KEY_F11, KEY_F12, KEY_F8, KEY_Q, + KEY_F4, KEY_F3, KEY_1, KEY_F7, + KEY_ESC, KEY_GRAVE, KEY_F5, KEY_TAB, + KEY_F1, KEY_F2, KEY_CAPSLOCK , KEY_F6 +}; + +static NvU32 ScanCodeToVKeyTableKbcQwertyFunction[] = +{ + // Row 0-> Unused, Unused, 'W', 'S', 'A', 'Z', Unused, Function, + // Row 1 ->WINSPECIAL, Unused, Unused, Unused, Unused, unused, Unused, Win_special + // Row 2 ->Unused, Unused, Unused, Unused, Unused, unused, Alt, Alt2 + // Row 3 ->'5', '4', 'R', 'E', 'F', 'D', 'X', Unused, + // Row 4 ->'7', '6', 'T', 'H', 'G', 'V', 'C', SPACEBAR, + // Row 5 ->'9', '8', 'U', 'Y', 'J', 'N', 'B', '|\', + // Row 6 ->Minus, '0', 'O', 'I', 'L', 'K', '<', M, + // Row 7 ->unused, '+', '}]', '#', Unused, Unused, Unused, WinSpecial, + // Row 8 ->Unused, Unused, Unused, Unused, SHIFT, SHIFT, UnUsed, Unused , + // Row 9 ->Unused, Unused, Unused, Unused, unused, Ctrl, UnUsed, Control, + // Row A ->Unused, Unused, Unused, Unused, unused, unused, UnUsed, Unused, + // Row B ->'{[', 'P', '"', ':;', '/?, '>', UnUsed, Unused, + // Row C ->'F10', 'F9', 'BckSpc','3', '2', 'Up, Prntscr,Pause + // Row D ->INS, DEL, Unused, Pgup, PgDn, right, Down, Left, + // Row E ->F11, F12, F8, 'Q', F4, F3, '1', F7, + // Row F ->ESC, '~', F5, TAB, F1, F2, CAPLOCK,F6, + + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_7, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_9, KEY_8, KEY_4, KEY_UNUSED, KEY_1, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_SLASH, KEY_6, KEY_5, KEY_3, KEY_2, KEY_UNUSED, KEY_0, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_KPASTERISK, KEY_UNUSED, KEY_KPMINUS, KEY_KPPLUS, KEY_DOT, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_VOLUMEUP, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_HOME, KEY_END, KEY_BRIGHTNESSUP, KEY_VOLUMEDOWN, KEY_BRIGHTNESSDOWN, + KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_MUTE,KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, + KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_QUESTION,KEY_UNUSED, KEY_UNUSED, KEY_UNUSED +}; +static struct NvOdmKeyVirtTableDetail s_ScvkQwertyNormalEngUS = +{ + NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_FIRST, // scan code start + NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_LAST, // scan code end + ScanCodeToVKeyTableKbcQwertyNormal // Normal Qwerty keyboard +}; + +static struct NvOdmKeyVirtTableDetail s_ScvkQwertyFunctionEngUS = +{ + NV_SOC_FUNCTION_KEY_SCAN_CODE_TABLE_FIRST, // scan code start + NV_SOC_FUNCTION_KEY_SCAN_CODE_TABLE_LAST, // scan code end + ScanCodeToVKeyTableKbcQwertyFunction // Function Qwerty keyboard +}; + +static const struct NvOdmKeyVirtTableDetail *s_pVirtualKeyTables[] = + {&s_ScvkQwertyNormalEngUS, &s_ScvkQwertyFunctionEngUS}; + + +NvU32 +NvOdmKbcKeyMappingGetVirtualKeyMappingList( + const struct NvOdmKeyVirtTableDetail ***pVirtKeyTableList) +{ + *pVirtKeyTableList = s_pVirtualKeyTables; + return NV_ARRAY_SIZE(s_pVirtualKeyTables); +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_sdio.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_sdio.c new file mode 100644 index 000000000000..946f4ab9ecc4 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_sdio.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2008-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file Nvodm_Sdio.c + * @brief <b>Sdio odm implementation</b> + * + * @Description : Implementation of the odm sdio API + */ +#include "nvodm_sdio.h" +#include "nvodm_services.h" +#include "nvodm_query_discovery.h" +#include "nvodm_services.h" +#include "nvodm_pmu.h" +#include "nvos.h" + +#ifdef NV_DRIVER_DEBUG + #define NV_DRIVER_TRACE(x) NvOdmOsDebugPrintf x +#else + #define NV_DRIVER_TRACE(x) +#endif + +#define WLAN_GUID NV_ODM_GUID('s','d','i','o','w','l','a','n') + +typedef struct NvOdmSdioRec +{ + // NvODM PMU device handle + NvOdmServicesPmuHandle hPmu; + // Gpio Handle + NvOdmServicesGpioHandle hGpio; + // Pin handle to Wlan Reset Gpio pin + NvOdmGpioPinHandle hResetPin; + // Pin handle to Wlan PWR GPIO Pin + NvOdmGpioPinHandle hPwrPin; + NvOdmPeripheralConnectivity *pConnectivity; + // Power state + NvBool PoweredOn; + // Instance + NvU32 Instance; +} NvOdmSdio; + + + +static void NvOdmSetPowerOnSdio(NvOdmSdioHandle pDevice, NvBool IsEnable); +static NvBool SdioOdmWlanSetPowerOn(NvOdmSdioHandle hOdmSdio, NvBool IsEnable); + + +static NvBool SdioOdmWlanSetPowerOn(NvOdmSdioHandle hOdmSdio, NvBool IsEnable) +{ + if (IsEnable) + { + // Wlan Power On Reset Sequence + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x0); //PWD -> Low + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hResetPin, 0x0); //RST -> Low + NvOdmOsWaitUS(2000); + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x1); //PWD -> High + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hResetPin, 0x1); //RST -> High + } + else + { + // Power Off sequence + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x0); //PWD -> Low + } + + return NV_TRUE; +} + +NvOdmSdioHandle NvOdmSdioOpen(NvU32 Instance) +{ + static NvOdmSdio *pDevice = NULL; + NvOdmServicesGpioHandle hGpioTemp = NULL; + NvOdmPeripheralConnectivity *pConnectivity; + NvU32 NumOfGuids = 1; + NvU64 guid; + NvU32 searchVals[2]; + const NvU32 *pOdmConfigs; + NvU32 NumOdmConfigs; + NvBool Status = NV_TRUE; + const NvOdmPeripheralSearch searchAttrs[] = + { + NvOdmPeripheralSearch_IoModule, + NvOdmPeripheralSearch_Instance, + }; + + searchVals[0] = NvOdmIoModule_Sdio; + searchVals[1] = Instance; + + NvOdmQueryPinMux(NvOdmIoModule_Sdio, &pOdmConfigs, &NumOdmConfigs); + if (Instance >= NumOdmConfigs ) + return NULL; + if( pOdmConfigs[Instance] == 0 ) + return NULL; + + NumOfGuids = NvOdmPeripheralEnumerate( + searchAttrs, + searchVals, + 2, + &guid, + NumOfGuids); + + + // Get the peripheral connectivity information + pConnectivity = (NvOdmPeripheralConnectivity *)NvOdmPeripheralGetGuid(guid); + if (pConnectivity == NULL) + return NULL; + + pDevice = NvOdmOsAlloc(sizeof(NvOdmSdio)); + pDevice->hPmu = NULL; + if(pDevice == NULL) + return (pDevice); + + if (pDevice->hPmu == NULL) + { + pDevice->hPmu = NvOdmServicesPmuOpen(); + if(pDevice->hPmu == NULL) + { + NvOdmOsFree(pDevice); + pDevice = NULL; + return (NULL); + } + } + + pDevice->pConnectivity = pConnectivity; + NvOdmSetPowerOnSdio(pDevice, NV_TRUE); + + if (pConnectivity->Guid == WLAN_GUID) + { + // Getting the OdmGpio Handle + hGpioTemp = NvOdmGpioOpen(); + if (hGpioTemp == NULL) + { + NvOdmOsFree(pDevice); + pDevice = NULL; + return (pDevice); + } + + // Search for the Vdd rail and set the proper volage to the rail. + if (pConnectivity->AddressList[1].Interface == NvOdmIoModule_Gpio) + { + // Acquiring Pin Handles for Power Pin + pDevice->hPwrPin= NvOdmGpioAcquirePinHandle(hGpioTemp, + pConnectivity->AddressList[1].Instance, + pConnectivity->AddressList[1].Address); + } + + if (pConnectivity->AddressList[2].Interface == NvOdmIoModule_Gpio) + { + // Acquiring Pin Handles for Reset Pin + pDevice->hResetPin= NvOdmGpioAcquirePinHandle(hGpioTemp, + pConnectivity->AddressList[2].Instance, + pConnectivity->AddressList[2].Address); + } + + // Setting the ON/OFF pin to output mode. + NvOdmGpioConfig(hGpioTemp, pDevice->hPwrPin, NvOdmGpioPinMode_Output); + NvOdmGpioConfig(hGpioTemp, pDevice->hResetPin, NvOdmGpioPinMode_Output); + + // Setting the Output Pin to Low + NvOdmGpioSetState(hGpioTemp, pDevice->hPwrPin, 0x0); + NvOdmGpioSetState(hGpioTemp, pDevice->hResetPin, 0x0); + + pDevice->hGpio = hGpioTemp; + + Status = SdioOdmWlanSetPowerOn(pDevice, NV_TRUE); + if (Status != NV_TRUE) + { + NvOdmOsFree(pDevice); + pDevice = NULL; + return (pDevice); + } + } + pDevice->PoweredOn = NV_TRUE; + pDevice->Instance = Instance; + NV_DRIVER_TRACE(("Open SDIO%d", Instance)); + return pDevice; +} + +void NvOdmSdioClose(NvOdmSdioHandle hOdmSdio) +{ + const NvOdmPeripheralConnectivity *pConnectivity = NULL; + + NV_DRIVER_TRACE(("Close SDIO%d", hOdmSdio->Instance)); + + pConnectivity = hOdmSdio->pConnectivity; + if (pConnectivity->Guid == WLAN_GUID) + { + // Call Turn off power when close is Called + (void)SdioOdmWlanSetPowerOn(hOdmSdio, NV_FALSE); + + NvOdmGpioReleasePinHandle(hOdmSdio->hGpio, hOdmSdio->hPwrPin); + NvOdmGpioReleasePinHandle(hOdmSdio->hGpio, hOdmSdio->hResetPin); + NvOdmGpioClose(hOdmSdio->hGpio); + } + NvOdmSetPowerOnSdio(hOdmSdio, NV_FALSE); + if (hOdmSdio->hPmu != NULL) + { + NvOdmServicesPmuClose(hOdmSdio->hPmu); + } + NvOdmOsFree(hOdmSdio); + hOdmSdio = NULL; +} + +static void NvOdmSetPowerOnSdio(NvOdmSdioHandle pDevice, + NvBool IsEnable) +{ + NvU32 Index = 0; + NvOdmServicesPmuVddRailCapabilities RailCaps; + NvU32 SettlingTime = 0; + const NvOdmPeripheralConnectivity *pConnectivity; + + pConnectivity = pDevice->pConnectivity; + if (IsEnable) // Turn on Power + { + // Search for the Vdd rail and set the proper volage to the rail. + for (Index = 0; Index < pConnectivity->NumAddress; ++Index) + { + if (pConnectivity->AddressList[Index].Interface == NvOdmIoModule_Vdd) + { + NvOdmServicesPmuGetCapabilities(pDevice->hPmu, pConnectivity->AddressList[Index].Address, &RailCaps); + NvOdmServicesPmuSetVoltage(pDevice->hPmu, pConnectivity->AddressList[Index].Address, + RailCaps.requestMilliVolts, &SettlingTime); + if (SettlingTime) + { + NvOdmOsWaitUS(SettlingTime); + } + } + } + } + else // Shutdown Power + { + // Search for the Vdd rail and power Off the module + for (Index = 0; Index < pConnectivity->NumAddress; ++Index) + { + if (pConnectivity->AddressList[Index].Interface == NvOdmIoModule_Vdd) + { + NvOdmServicesPmuGetCapabilities(pDevice->hPmu, pConnectivity->AddressList[Index].Address, &RailCaps); + NvOdmServicesPmuSetVoltage(pDevice->hPmu, pConnectivity->AddressList[Index].Address, + ODM_VOLTAGE_OFF, &SettlingTime); + if (SettlingTime) + { + NvOdmOsWaitUS(SettlingTime); + } + } + } + } +} + +NvBool NvOdmSdioSuspend(NvOdmSdioHandle hOdmSdio) +{ + + const NvOdmPeripheralConnectivity *pConnectivity = NULL; + NvBool Status = NV_TRUE; + + if (!hOdmSdio->PoweredOn) + { + NV_DRIVER_TRACE(("SDIO%d already suspended", hOdmSdio->Instance)); + return NV_TRUE; + } + + NV_DRIVER_TRACE(("Suspend SDIO%d", hOdmSdio->Instance)); + NvOdmSetPowerOnSdio(hOdmSdio, NV_FALSE); + + pConnectivity = hOdmSdio->pConnectivity; + if (pConnectivity->Guid == WLAN_GUID) + { + // Turn off power + Status = SdioOdmWlanSetPowerOn(hOdmSdio, NV_FALSE); + + } + hOdmSdio->PoweredOn = NV_FALSE; + return Status; + +} + +NvBool NvOdmSdioResume(NvOdmSdioHandle hOdmSdio) +{ + const NvOdmPeripheralConnectivity *pConnectivity = NULL; + NvBool Status = NV_TRUE; + + if (hOdmSdio->PoweredOn) + { + NV_DRIVER_TRACE(("SDIO%d already resumed", hOdmSdio->Instance)); + return NV_TRUE; + } + + NvOdmSetPowerOnSdio(hOdmSdio, NV_TRUE); + + pConnectivity = hOdmSdio->pConnectivity; + if (pConnectivity->Guid == WLAN_GUID) + { + // Turn on power + Status = SdioOdmWlanSetPowerOn(hOdmSdio, NV_TRUE); + } + NV_DRIVER_TRACE(("Resume SDIO%d", hOdmSdio->Instance)); + hOdmSdio->PoweredOn = NV_TRUE; + return Status; +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_uart.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_uart.c new file mode 100644 index 000000000000..a3f09ad89c18 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_uart.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file nvodm_uart.c + * @brief <b>Adaptation for uart </b> + * + * @Description : Implementation of the uart adaptation. + */ +#include "nvodm_uart.h" +#include "nvodm_services.h" +#include "nvodm_query_discovery.h" +#include "nvodm_services.h" +#include "nvos.h" +#include "nvodm_pmu.h" + +#ifdef NV_DRIVER_DEBUG + #define NV_DRIVER_TRACE NvOsDebugPrintf +#else + #define NV_DRIVER_TRACE (void) +#endif + +typedef struct NvOdmUartRec +{ + // NvODM PMU device handle + NvOdmServicesPmuHandle hPmu; + // Gpio Handle + NvOdmServicesGpioHandle hGpio; + // Pin handle to Bluetooth Reset Gpio pin + NvOdmGpioPinHandle hResetPin; + NvOdmPeripheralConnectivity *pConnectivity; +} NvOdmUart; + +NvOdmUartHandle NvOdmUartOpen(NvU32 Instance) +{ + NvOdmUart *pDevice = NULL; + NvOdmPeripheralConnectivity *pConnectivity; + NvU32 NumOfGuids = 1; + NvU64 guid; + NvU32 searchVals[2]; + const NvOdmPeripheralSearch searchAttrs[] = + { + NvOdmPeripheralSearch_IoModule, + NvOdmPeripheralSearch_Instance, + }; + + searchVals[0] = NvOdmIoModule_Uart; + searchVals[1] = Instance; + + NumOfGuids = NvOdmPeripheralEnumerate( + searchAttrs, + searchVals, + 2, + &guid, + NumOfGuids); + + pConnectivity = (NvOdmPeripheralConnectivity *)NvOdmPeripheralGetGuid(guid); + if (pConnectivity == NULL) + goto ExitUartOdm; + + pDevice = NvOdmOsAlloc(sizeof(NvOdmUart)); + if(pDevice == NULL) + goto ExitUartOdm; + + pDevice->hPmu = NvOdmServicesPmuOpen(); + if(pDevice->hPmu == NULL) + { + goto ExitUartOdm; + } + + // Switch On UART Interface + + pDevice->pConnectivity = pConnectivity; + + return pDevice; + +ExitUartOdm: + NvOdmOsFree(pDevice); + pDevice = NULL; + + return NULL; +} + +void NvOdmUartClose(NvOdmUartHandle hOdmUart) +{ + + if (hOdmUart) + { + // Switch OFF UART Interface + + if (hOdmUart->hPmu != NULL) + { + NvOdmServicesPmuClose(hOdmUart->hPmu); + } + NvOdmOsFree(hOdmUart); + hOdmUart = NULL; + } +} + +NvBool NvOdmUartSuspend(NvOdmUartHandle hOdmUart) +{ + return NV_FALSE; +} + +NvBool NvOdmUartResume(NvOdmUartHandle hOdmUart) +{ + return NV_FALSE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c new file mode 100644 index 000000000000..63bdf09a14ae --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/harmony/nvodm_usbulpi.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file nvodm_usbulpi.c + * @brief <b>Adaptation for USB ULPI </b> + * + * @Description : Implementation of the USB ULPI adaptation. + */ +#include "nvodm_usbulpi.h" +#include "nvodm_services.h" +#include "nvodm_query_discovery.h" +#include "nvodm_services.h" +#include "nvos.h" + +#define SMSC3317GUID NV_ODM_GUID('s','m','s','c','3','3','1','7') + +#define MAX_CLOCKS 3 + +#define NVODM_PORT(x) ((x) - 'a') +#define ULPI_RESET_PORT NVODM_PORT('v') +#define ULPI_RESET_PIN 1 + + +#ifdef NV_DRIVER_DEBUG + #define NV_DRIVER_TRACE NvOsDebugPrintf +#else + #define NV_DRIVER_TRACE (void) +#endif + +typedef struct NvOdmUsbUlpiRec +{ + NvU64 CurrentGUID; +} NvOdmUsbUlpi; + +static NvOdmServicesGpioHandle s_hGpio = NULL; +static NvOdmGpioPinHandle s_hResetPin = NULL; + +NvOdmUsbUlpiHandle NvOdmUsbUlpiOpen(NvU32 Instance) +{ + NvOdmUsbUlpi*pDevice = NULL; + NvU32 ClockInstances[MAX_CLOCKS]; + NvU32 ClockFrequencies[MAX_CLOCKS]; + NvU32 NumClocks; + + pDevice = NvOdmOsAlloc(sizeof(NvOdmUsbUlpi)); + if(pDevice == NULL) + return NULL; + + if(!NvOdmExternalClockConfig(SMSC3317GUID, NV_FALSE, ClockInstances, + ClockFrequencies, &NumClocks)) + { + NV_DRIVER_TRACE (("ERROR NvOdmUsbUlpiOpen: " + "NvOdmExternalClockConfig fail\n")); + goto ExitUlpiOdm; + } + NvOdmOsSleepMS(10); + + if (!s_hGpio) + s_hGpio = NvOdmGpioOpen(); + if (!s_hGpio) + { + NV_DRIVER_TRACE (("ERROR NvOdmUsbUlpiOpen: " + "Not able to open gpio handle\n")); + goto ExitUlpiOdm; + } + + if (!s_hResetPin) + s_hResetPin = NvOdmGpioAcquirePinHandle(s_hGpio, ULPI_RESET_PORT, + ULPI_RESET_PIN); + if (!s_hResetPin) + { + NvOdmGpioClose(s_hGpio); + s_hGpio = NULL; + NV_DRIVER_TRACE (("ERROR NvOdmGpioAcquirePinHandle: " + "Not able to Acq pinhandle\n")); + goto ExitUlpiOdm; + } + + // Pull high on RESETB ( 22nd pin of smsc3315) + // config as out put pin + NvOdmGpioConfig(s_hGpio,s_hResetPin, NvOdmGpioPinMode_Output); + // Set low to write high on ULPI_RESETB pin + NvOdmGpioSetState(s_hGpio, s_hResetPin, 0x01); + NvOdmGpioSetState(s_hGpio, s_hResetPin, 0x0); + NvOdmOsSleepMS(5); + NvOdmGpioSetState(s_hGpio, s_hResetPin, 0x01); + + pDevice->CurrentGUID = SMSC3317GUID; + return pDevice; + +ExitUlpiOdm: + NvOdmOsFree(pDevice); + return NULL; +} + +void NvOdmUsbUlpiClose(NvOdmUsbUlpiHandle hOdmUlpi) +{ + if (hOdmUlpi) + { + NvOdmOsFree(hOdmUlpi); + } + if (s_hResetPin) + { + NvOdmGpioReleasePinHandle(s_hGpio, s_hResetPin); + s_hResetPin = NULL; + } + if (s_hGpio) + { + NvOdmGpioClose(s_hGpio); + s_hGpio = NULL; + } + +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/Makefile new file mode 100644 index 000000000000..9f3eb8402b6b --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/Makefile @@ -0,0 +1,15 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +obj-$(CONFIG_KEYBOARD_TEGRA) += nvodm_kbc.o +obj-$(CONFIG_KEYBOARD_TEGRA) += nvodm_kbc_keymapping.o +obj-y += nvodm_sdio.o +obj-y += nvodm_uart.o +obj-y += nvodm_usbulpi.o + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_kbc.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_kbc.c new file mode 100644 index 000000000000..70b468d9ff51 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_kbc.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2008-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file Nvodm_Kbc.c + * @brief <b>KBC odm implementation</b> + * + * @Description : Implementation of the odm KBC API + */ +#include "nvodm_kbc.h" + + +#define KEYPAD_HAS_DIODES 1 + +NvU32 +NvOdmKbcFilterKeys( + NvU32 *pRows, + NvU32 *pCols, + NvU32 NumOfKeysPressed) +{ + +#if KEYPAD_HAS_DIODES + return NumOfKeysPressed; +#else + NvU32 i=0; + NvU32 j=0; + NvU32 k=0; + NvU32 FilterKeys[2] = {0}; + NvBool IsFiltered = NV_FALSE; + NvU32 NewKeyPressCount = NumOfKeysPressed; + + if (NumOfKeysPressed <= 3) + { + for (i=0; i<NumOfKeysPressed; i++) + { + for (j=(i+1); j<NumOfKeysPressed; j++) + { + if ((pRows[i]+1==pRows[j])||(pRows[j]+1==pRows[i])) + { + for (k=j; i<(NumOfKeysPressed - 1); i++) + { + pRows[k] = pRows[k+1]; + pCols[k] = pCols[k+1]; + } + NumOfKeysPressed--; + } + if ((pCols[i]+1==pCols[j])||(pCols[j]+1==pCols[i])) + { + for (k=j; i<(NumOfKeysPressed - 1); i++) + { + pRows[k] = pRows[k+1]; + pCols[k] = pCols[k+1]; + } + NumOfKeysPressed--; + } + } + } + return NumOfKeysPressed; + } + + for (i=0; i<NumOfKeysPressed; i++) + { + for (j=(i+1); j<NumOfKeysPressed; j++) + { + if (pRows[i] == pRows[j]) + { + for (k=0; k<NumOfKeysPressed; k++) + { + if (k == i) + continue; + + if(pCols[i] == pCols[k]) + { + FilterKeys[0] = k; + IsFiltered = NV_TRUE; + } + } + for (k=0; k<NumOfKeysPressed; k++) + { + if (k == j) + continue; + + if (pCols[j] == pCols[k]) + { + FilterKeys[1] = k; + IsFiltered = NV_TRUE; + } + } + goto end; + } + } + } + + end: + if (IsFiltered) + { + for (i=FilterKeys[0]; i<(NumOfKeysPressed - 1); i++) + { + pRows[i] = pRows[i+1]; + pCols[i] = pCols[i+1]; + } + NewKeyPressCount--; + for (i=FilterKeys[1]; i<(NumOfKeysPressed - 1); i++) + { + pRows[i] = pRows[i+1]; + pCols[i] = pCols[i+1]; + } + NewKeyPressCount--; + } + NumOfKeysPressed = NewKeyPressCount; + return NewKeyPressCount; +#endif + +} + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_kbc_keymapping.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_kbc_keymapping.c new file mode 100644 index 000000000000..1f2dd7275eae --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_kbc_keymapping.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * <b>NVIDIA Tegra ODM Kit: + * Keyboard Controller virtual key mapping</b> + * + * @b Description: Implement the ODM keyboard mapping to the platform + * specific. + */ +#include "nvodm_kbc_keymapping.h" +#include <linux/input.h> + +/* The total number of soc scan codes will be (first - last) */ +#define NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_FIRST 0 +#define NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_LAST 3 + +static NvU32 KbcLayOutVirtualKey[] = +{ + KEY_MENU, + 0, + KEY_HOME, + KEY_BACK +}; + +static struct NvOdmKeyVirtTableDetail s_ScvkKeyMap = +{ + NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_FIRST, // scan code start + NV_SOC_NORMAL_KEY_SCAN_CODE_TABLE_LAST, // scan code end + KbcLayOutVirtualKey // Normal Qwerty keyboard +}; + + +static const struct NvOdmKeyVirtTableDetail *s_pVirtualKeyTables[] = + {&s_ScvkKeyMap}; + + +NvU32 +NvOdmKbcKeyMappingGetVirtualKeyMappingList( + const struct NvOdmKeyVirtTableDetail ***pVirtKeyTableList) +{ + *pVirtKeyTableList = s_pVirtualKeyTables; + return NV_ARRAY_SIZE(s_pVirtualKeyTables); +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_sdio.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_sdio.c new file mode 100644 index 000000000000..d980dfca3b2b --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_sdio.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2008-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file Nvodm_Sdio.c + * @brief <b>Sdio odm implementation</b> + * + * @Description : Implementation of the odm sdio API + */ +#include "nvodm_sdio.h" +#include "nvodm_services.h" +#include "nvodm_query_discovery.h" +#include "nvodm_services.h" +#include "nvodm_pmu.h" + +#ifdef NV_DRIVER_DEBUG + #define NV_DRIVER_TRACE(x) NvOdmOsDebugPrintf x +#else + #define NV_DRIVER_TRACE(x) +#endif + +#define WLAN_GUID NV_ODM_GUID('s','d','i','o','w','l','a','n') +// Device Board definitions +#define BOARD_ID_E951 (0x0933) /* Decimal 951. => ((9<<8) | 51)*/ + + +typedef enum +{ + NvOdmSdioDiscoveryAddress_0 = 0, + NvOdmSdioDiscoveryAddress_1, + + NvOdmSdioDiscoveryAddress_Force32 = 0x7FFFFFFF, + +} NvOdmSdioDiscoveryAddress; + +typedef struct NvOdmSdioRec +{ + // NvODM PMU device handle + NvOdmServicesPmuHandle hPmu; + // Gpio Handle + NvOdmServicesGpioHandle hGpio; + // Pin handle to Wlan Reset Gpio pin + NvOdmGpioPinHandle hResetPin; + // Pin handle to Wlan PWR GPIO Pin + NvOdmGpioPinHandle hPwrPin; + NvOdmPeripheralConnectivity *pConnectivity; + // Power state + NvBool PoweredOn; + // Instance + NvU32 Instance; +} NvOdmSdio; + +static void NvOdmSetPowerOnSdio(NvOdmSdioHandle pDevice, NvBool IsEnable); +static NvBool SdioOdmWlanSetPowerOn(NvOdmSdioHandle hOdmSdio, NvBool IsEnable); + + +static NvBool SdioOdmWlanSetPowerOn(NvOdmSdioHandle hOdmSdio, NvBool IsEnable) +{ + if (IsEnable) + { + // Wlan Power On Reset Sequence + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x0); //PWD -> Low + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hResetPin, 0x0); //RST -> Low + NvOdmOsWaitUS(2000); + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x1); //PWD -> High + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hResetPin, 0x1); //RST -> High + } + else + { + // Power Off sequence + NvOdmGpioSetState(hOdmSdio->hGpio, hOdmSdio->hPwrPin, 0x0); //PWD -> Low + } + return NV_TRUE; +} + +NvOdmSdioHandle NvOdmSdioOpen(NvU32 Instance) +{ + static NvOdmSdio *pDevice = NULL; + NvOdmServicesGpioHandle hGpioTemp = NULL; + NvOdmPeripheralConnectivity *pConnectivity; + NvU32 NumOfGuids = 1; + NvU64 guid; + NvU32 searchVals[4]; + const NvU32 *pOdmConfigs; + NvU32 NumOdmConfigs; + NvBool Status = NV_TRUE; + const NvOdmPeripheralSearch searchAttrs[] = + { + NvOdmPeripheralSearch_PeripheralClass, + NvOdmPeripheralSearch_IoModule, + NvOdmPeripheralSearch_Instance, + NvOdmPeripheralSearch_Address, + }; + NvOdmBoardInfo BoardInfo; + NvBool status = NV_FALSE; + + searchVals[0] = NvOdmPeripheralClass_Other; + searchVals[1] = NvOdmIoModule_Sdio; + searchVals[2] = Instance; + + NvOdmQueryPinMux(NvOdmIoModule_Sdio, &pOdmConfigs, &NumOdmConfigs); + if ((Instance == 0) && (pOdmConfigs[0] == NvOdmSdioPinMap_Config1)) + { + // sdio is connected to sdio2 slot. + searchVals[3] = NvOdmSdioDiscoveryAddress_1; + } + else + { + // sdio is connected to wifi module. + searchVals[3] = NvOdmSdioDiscoveryAddress_0; + } + + NumOfGuids = NvOdmPeripheralEnumerate(searchAttrs, + searchVals, + 4, + &guid, + NumOfGuids); + + // Get the peripheral connectivity information + pConnectivity = (NvOdmPeripheralConnectivity *)NvOdmPeripheralGetGuid(guid); + if (pConnectivity == NULL) + return NULL; + + pDevice = NvOdmOsAlloc(sizeof(NvOdmSdio)); + if(pDevice == NULL) + return (pDevice); + + pDevice->hPmu = NvOdmServicesPmuOpen(); + if(pDevice->hPmu == NULL) + { + NvOdmOsFree(pDevice); + pDevice = NULL; + return (NULL); + } + + if (pConnectivity->Guid == WLAN_GUID) + { + // WARNING: This function *cannot* be called before RmOpen(). + status = NvOdmPeripheralGetBoardInfo((BOARD_ID_E951), &BoardInfo); + if (NV_TRUE != status) + { + // whistler should have E951 Module, if it is not presnt return NULL Handle. + NvOdmServicesPmuClose(pDevice->hPmu); + NvOdmOsFree(pDevice); + pDevice = NULL; + NvOdmOsDebugPrintf(("No E951 Detected")); + return (pDevice); + } + } + + pDevice->pConnectivity = pConnectivity; + NvOdmSetPowerOnSdio(pDevice, NV_TRUE); + + if (pConnectivity->Guid == WLAN_GUID) + { + // Getting the OdmGpio Handle + hGpioTemp = NvOdmGpioOpen(); + if (hGpioTemp == NULL) + { + NvOdmServicesPmuClose(pDevice->hPmu); + NvOdmOsFree(pDevice); + pDevice = NULL; + return (pDevice); + } + + // Search for the Vdd rail and set the proper volage to the rail. + if (pConnectivity->AddressList[1].Interface == NvOdmIoModule_Gpio) + { + // Acquiring Pin Handles for Power Pin + pDevice->hPwrPin= NvOdmGpioAcquirePinHandle(hGpioTemp, + pConnectivity->AddressList[1].Instance, + pConnectivity->AddressList[1].Address); + } + + if (pConnectivity->AddressList[2].Interface == NvOdmIoModule_Gpio) + { + // Acquiring Pin Handles for Reset Pin + pDevice->hResetPin= NvOdmGpioAcquirePinHandle(hGpioTemp, + pConnectivity->AddressList[2].Instance, + pConnectivity->AddressList[2].Address); + } + + // Setting the ON/OFF pin to output mode. + NvOdmGpioConfig(hGpioTemp, pDevice->hPwrPin, NvOdmGpioPinMode_Output); + NvOdmGpioConfig(hGpioTemp, pDevice->hResetPin, NvOdmGpioPinMode_Output); + + // Setting the Output Pin to Low + NvOdmGpioSetState(hGpioTemp, pDevice->hPwrPin, 0x0); + NvOdmGpioSetState(hGpioTemp, pDevice->hResetPin, 0x0); + + pDevice->hGpio = hGpioTemp; + + Status = SdioOdmWlanSetPowerOn(pDevice, NV_TRUE); + if (Status != NV_TRUE) + { + NvOdmServicesPmuClose(pDevice->hPmu); + NvOdmGpioReleasePinHandle(pDevice->hGpio, pDevice->hPwrPin); + NvOdmGpioReleasePinHandle(pDevice->hGpio, pDevice->hResetPin); + NvOdmGpioClose(pDevice->hGpio); + NvOdmOsFree(pDevice); + pDevice = NULL; + return (pDevice); + } + } + pDevice->PoweredOn = NV_TRUE; + pDevice->Instance = Instance; + NV_DRIVER_TRACE(("Open SDIO%d", Instance)); + return pDevice; +} + +void NvOdmSdioClose(NvOdmSdioHandle hOdmSdio) +{ + const NvOdmPeripheralConnectivity *pConnectivity = NULL; + + NV_DRIVER_TRACE(("Close SDIO%d", hOdmSdio->Instance)); + + pConnectivity = hOdmSdio->pConnectivity; + if (pConnectivity->Guid == WLAN_GUID) + { + // Call Turn off power when close is Called + (void)SdioOdmWlanSetPowerOn(hOdmSdio, NV_FALSE); + + NvOdmGpioReleasePinHandle(hOdmSdio->hGpio, hOdmSdio->hPwrPin); + NvOdmGpioReleasePinHandle(hOdmSdio->hGpio, hOdmSdio->hResetPin); + NvOdmGpioClose(hOdmSdio->hGpio); + } + NvOdmSetPowerOnSdio(hOdmSdio, NV_FALSE); + if (hOdmSdio->hPmu != NULL) + { + NvOdmServicesPmuClose(hOdmSdio->hPmu); + } + NvOdmOsFree(hOdmSdio); + hOdmSdio = NULL; +} + +static void NvOdmSetPowerOnSdio(NvOdmSdioHandle pDevice, NvBool IsEnable) +{ + NvU32 Index = 0; + NvOdmServicesPmuVddRailCapabilities RailCaps; + NvU32 SettlingTime = 0; + const NvOdmPeripheralConnectivity *pConnectivity; + + pConnectivity = pDevice->pConnectivity; + if (IsEnable) // Turn on Power + { + // Search for the Vdd rail and set the proper volage to the rail. + for (Index = 0; Index < pConnectivity->NumAddress; ++Index) + { + if (pConnectivity->AddressList[Index].Interface == NvOdmIoModule_Vdd) + { + NvOdmServicesPmuGetCapabilities(pDevice->hPmu, pConnectivity->AddressList[Index].Address, &RailCaps); + NvOdmServicesPmuSetVoltage(pDevice->hPmu, pConnectivity->AddressList[Index].Address, + RailCaps.requestMilliVolts, &SettlingTime); + if (SettlingTime) + { + NvOdmOsWaitUS(SettlingTime); + } + } + } + } + else // Shutdown Power + { + // Search for the Vdd rail and power Off the module + for (Index = 0; Index < pConnectivity->NumAddress; ++Index) + { + if (pConnectivity->AddressList[Index].Interface == NvOdmIoModule_Vdd) + { + NvOdmServicesPmuGetCapabilities(pDevice->hPmu, pConnectivity->AddressList[Index].Address, &RailCaps); + NvOdmServicesPmuSetVoltage(pDevice->hPmu, pConnectivity->AddressList[Index].Address, + ODM_VOLTAGE_OFF, &SettlingTime); + if (SettlingTime) + { + NvOdmOsWaitUS(SettlingTime); + } + } + } + } +} + +NvBool NvOdmSdioSuspend(NvOdmSdioHandle hOdmSdio) +{ + + const NvOdmPeripheralConnectivity *pConnectivity = NULL; + NvBool Status = NV_TRUE; + + if (!hOdmSdio->PoweredOn) + { + NV_DRIVER_TRACE(("SDIO%d already suspended", hOdmSdio->Instance)); + return NV_TRUE; + } + + NV_DRIVER_TRACE(("Suspend SDIO%d", hOdmSdio->Instance)); + NvOdmSetPowerOnSdio(hOdmSdio, NV_FALSE); + + pConnectivity = hOdmSdio->pConnectivity; + if (pConnectivity->Guid == WLAN_GUID) + { + // Turn off power + Status = SdioOdmWlanSetPowerOn(hOdmSdio, NV_FALSE); + + } + hOdmSdio->PoweredOn = NV_FALSE; + return Status; + +} + +NvBool NvOdmSdioResume(NvOdmSdioHandle hOdmSdio) +{ + const NvOdmPeripheralConnectivity *pConnectivity = NULL; + NvBool Status = NV_TRUE; + + if (hOdmSdio->PoweredOn) + { + NV_DRIVER_TRACE(("SDIO%d already resumed", hOdmSdio->Instance)); + return NV_TRUE; + } + + NvOdmSetPowerOnSdio(hOdmSdio, NV_TRUE); + + pConnectivity = hOdmSdio->pConnectivity; + if (pConnectivity->Guid == WLAN_GUID) + { + // Turn on power + Status = SdioOdmWlanSetPowerOn(hOdmSdio, NV_TRUE); + } + NV_DRIVER_TRACE(("Resume SDIO%d", hOdmSdio->Instance)); + hOdmSdio->PoweredOn = NV_TRUE; + return Status; +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_uart.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_uart.c new file mode 100644 index 000000000000..a3f09ad89c18 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_uart.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file nvodm_uart.c + * @brief <b>Adaptation for uart </b> + * + * @Description : Implementation of the uart adaptation. + */ +#include "nvodm_uart.h" +#include "nvodm_services.h" +#include "nvodm_query_discovery.h" +#include "nvodm_services.h" +#include "nvos.h" +#include "nvodm_pmu.h" + +#ifdef NV_DRIVER_DEBUG + #define NV_DRIVER_TRACE NvOsDebugPrintf +#else + #define NV_DRIVER_TRACE (void) +#endif + +typedef struct NvOdmUartRec +{ + // NvODM PMU device handle + NvOdmServicesPmuHandle hPmu; + // Gpio Handle + NvOdmServicesGpioHandle hGpio; + // Pin handle to Bluetooth Reset Gpio pin + NvOdmGpioPinHandle hResetPin; + NvOdmPeripheralConnectivity *pConnectivity; +} NvOdmUart; + +NvOdmUartHandle NvOdmUartOpen(NvU32 Instance) +{ + NvOdmUart *pDevice = NULL; + NvOdmPeripheralConnectivity *pConnectivity; + NvU32 NumOfGuids = 1; + NvU64 guid; + NvU32 searchVals[2]; + const NvOdmPeripheralSearch searchAttrs[] = + { + NvOdmPeripheralSearch_IoModule, + NvOdmPeripheralSearch_Instance, + }; + + searchVals[0] = NvOdmIoModule_Uart; + searchVals[1] = Instance; + + NumOfGuids = NvOdmPeripheralEnumerate( + searchAttrs, + searchVals, + 2, + &guid, + NumOfGuids); + + pConnectivity = (NvOdmPeripheralConnectivity *)NvOdmPeripheralGetGuid(guid); + if (pConnectivity == NULL) + goto ExitUartOdm; + + pDevice = NvOdmOsAlloc(sizeof(NvOdmUart)); + if(pDevice == NULL) + goto ExitUartOdm; + + pDevice->hPmu = NvOdmServicesPmuOpen(); + if(pDevice->hPmu == NULL) + { + goto ExitUartOdm; + } + + // Switch On UART Interface + + pDevice->pConnectivity = pConnectivity; + + return pDevice; + +ExitUartOdm: + NvOdmOsFree(pDevice); + pDevice = NULL; + + return NULL; +} + +void NvOdmUartClose(NvOdmUartHandle hOdmUart) +{ + + if (hOdmUart) + { + // Switch OFF UART Interface + + if (hOdmUart->hPmu != NULL) + { + NvOdmServicesPmuClose(hOdmUart->hPmu); + } + NvOdmOsFree(hOdmUart); + hOdmUart = NULL; + } +} + +NvBool NvOdmUartSuspend(NvOdmUartHandle hOdmUart) +{ + return NV_FALSE; +} + +NvBool NvOdmUartResume(NvOdmUartHandle hOdmUart) +{ + return NV_FALSE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_usbulpi.c b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_usbulpi.c new file mode 100644 index 000000000000..5bd21b2bd51b --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/misc/whistler/nvodm_usbulpi.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file nvodm_usbulpi.c + * @brief <b>Adaptation for USB ULPI </b> + * + * @Description : Implementation of the USB ULPI adaptation. + */ +#include "nvodm_usbulpi.h" +#include "nvodm_services.h" +#include "nvodm_query_discovery.h" +#include "nvodm_services.h" +#include "nvodm_keylist_reserved.h" +#include "nvrm_drf.h" +#include "nvos.h" + +typedef struct NvOdmUsbUlpiRec { + NvU64 CurrentGUID; +} NvOdmUsbUlpi; + +/* ST-Ericsson U3XX modem power control */ +struct ste_u3xx_info { + NvU32 ste_u3xx_uart_port; + NvU32 ste_u3xx_reset_port; + NvU32 ste_u3xx_reset_pin; + NvU32 ste_u3xx_power_port; + NvU32 ste_u3xx_power_pin; + NvU32 ste_u3xx_awr_port; + NvU32 ste_u3xx_awr_pin; + NvU32 ste_u3xx_cwr_port; + NvU32 ste_u3xx_cwr_pin; + NvU32 ste_u3xx_spi_int_port; + NvU32 ste_u3xx_spi_int_pin; + NvU32 ste_u3xx_slave_select_port; + NvU32 ste_u3xx_slave_select_pin; + NvU32 ste_u3xx_slink_instance; +}; + +/* ST-Ericsson U3XX modem control */ +static struct ste_u3xx_info ste_u3xx_info; +static NvOdmServicesGpioHandle ste_u3xx_gpio; +static NvOdmGpioPinHandle ste_u3xx_reset_gpio_pin; +static NvOdmGpioPinHandle ste_u3xx_power_gpio_pin; +static NvOdmGpioPinHandle ste_u3xx_awr_gpio_pin; +static NvOdmGpioPinHandle ste_u3xx_cwr_gpio_pin; + +static int ste_u3xx_query(struct ste_u3xx_info *info) +{ + NvU64 guid = NV_ODM_GUID('e', 'm', 'p', ' ', 'M', '5', '7', '0'); + NvOdmPeripheralConnectivity *pConnectivity; + + /* query odm kit for modem support */ + pConnectivity = + (NvOdmPeripheralConnectivity *) NvOdmPeripheralGetGuid(guid); + if (pConnectivity == NULL) + return -1; + NV_ASSERT(pConnectivity->NumAddress >= 5); + + /* query for uart port */ + NV_ASSERT(pConnectivity->AddressList[0].Interface == + NvOdmIoModule_Uart); + info->ste_u3xx_uart_port = pConnectivity->AddressList[0].Instance; + + /* query for reset pin */ + NV_ASSERT(pConnectivity->AddressList[1].Interface == + NvOdmIoModule_Gpio); + info->ste_u3xx_reset_port = pConnectivity->AddressList[1].Instance; + info->ste_u3xx_reset_pin = pConnectivity->AddressList[1].Address; + + /* query for power pin */ + NV_ASSERT(pConnectivity->AddressList[2].Interface == + NvOdmIoModule_Gpio); + info->ste_u3xx_power_port = pConnectivity->AddressList[2].Instance; + info->ste_u3xx_power_pin = pConnectivity->AddressList[2].Address; + + /* query for ACPU wakeup request pin */ + NV_ASSERT(pConnectivity->AddressList[3].Interface == + NvOdmIoModule_Gpio); + info->ste_u3xx_awr_port = pConnectivity->AddressList[3].Instance; + info->ste_u3xx_awr_pin = pConnectivity->AddressList[3].Address; + + /* query for CCPU wakeup request pin */ + NV_ASSERT(pConnectivity->AddressList[4].Interface == + NvOdmIoModule_Gpio); + info->ste_u3xx_cwr_port = pConnectivity->AddressList[4].Instance; + info->ste_u3xx_cwr_pin = pConnectivity->AddressList[4].Address; + + return 0; +} + +static void ste_u3xx_turn_on_modem(struct ste_u3xx_info *info) +{ + /* get odm gpio handle */ + ste_u3xx_gpio = NvOdmGpioOpen(); + if (!ste_u3xx_gpio) + return; + + /* acquire pin handle for reset pin */ + ste_u3xx_reset_gpio_pin = + NvOdmGpioAcquirePinHandle(ste_u3xx_gpio, info->ste_u3xx_reset_port, + info->ste_u3xx_reset_pin); + if (!ste_u3xx_reset_gpio_pin) { + NvOdmGpioClose(ste_u3xx_gpio); + return; + } + + /* acquire pin handle for power pin */ + ste_u3xx_power_gpio_pin = + NvOdmGpioAcquirePinHandle(ste_u3xx_gpio, info->ste_u3xx_power_port, + info->ste_u3xx_power_pin); + if (!ste_u3xx_power_gpio_pin) { + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, + ste_u3xx_reset_gpio_pin); + NvOdmGpioClose(ste_u3xx_gpio); + return; + } + + /* acquire pin handle for ACPU wakeup request pin */ + ste_u3xx_awr_gpio_pin = + NvOdmGpioAcquirePinHandle(ste_u3xx_gpio, info->ste_u3xx_awr_port, + info->ste_u3xx_awr_pin); + if (!ste_u3xx_awr_gpio_pin) { + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, + ste_u3xx_power_gpio_pin); + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, + ste_u3xx_reset_gpio_pin); + NvOdmGpioClose(ste_u3xx_gpio); + return; + } + + /* acquire pin handle for CCPU wakeup request pin */ + ste_u3xx_cwr_gpio_pin = + NvOdmGpioAcquirePinHandle(ste_u3xx_gpio, info->ste_u3xx_cwr_port, + info->ste_u3xx_cwr_pin); + if (!ste_u3xx_cwr_gpio_pin) { + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, ste_u3xx_awr_gpio_pin); + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, + ste_u3xx_power_gpio_pin); + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, + ste_u3xx_reset_gpio_pin); + NvOdmGpioClose(ste_u3xx_gpio); + return; + } + + /* set output levels - start with modem power off, reset deasserted */ + NvOdmGpioSetState(ste_u3xx_gpio, ste_u3xx_power_gpio_pin, 0); + NvOdmGpioSetState(ste_u3xx_gpio, ste_u3xx_reset_gpio_pin, 0); + NvOdmGpioConfig(ste_u3xx_gpio, ste_u3xx_power_gpio_pin, + NvOdmGpioPinMode_Output); + NvOdmGpioConfig(ste_u3xx_gpio, ste_u3xx_reset_gpio_pin, + NvOdmGpioPinMode_Output); + NvOdmGpioConfig(ste_u3xx_gpio, ste_u3xx_cwr_gpio_pin, + NvOdmGpioPinMode_InputData); + + NvOdmOsSleepMS(300); + NvOdmGpioSetState(ste_u3xx_gpio, ste_u3xx_reset_gpio_pin, 1); + + /* pulse modem power on for 300 ms */ + NvOdmOsSleepMS(300); + NvOdmGpioSetState(ste_u3xx_gpio, ste_u3xx_power_gpio_pin, 1); + NvOdmOsSleepMS(300); + NvOdmGpioSetState(ste_u3xx_gpio, ste_u3xx_power_gpio_pin, 0); + NvOdmOsSleepMS(100); + + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, ste_u3xx_cwr_gpio_pin); + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, ste_u3xx_awr_gpio_pin); + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, ste_u3xx_power_gpio_pin); + NvOdmGpioReleasePinHandle(ste_u3xx_gpio, ste_u3xx_reset_gpio_pin); + NvOdmGpioClose(ste_u3xx_gpio); +} + +NvOdmUsbUlpiHandle NvOdmUsbUlpiOpen(NvU32 Instance) +{ + const NvOdmUsbProperty *pUsbProperty = + NvOdmQueryGetUsbProperty(NvOdmIoModule_Usb, Instance); + NvOdmUsbUlpi *pDevice = NULL; + + pDevice = NvOdmOsAlloc(sizeof(NvOdmUsbUlpi)); + if (pDevice == NULL) + goto ExitUlpiOdm; + + if (pUsbProperty->UsbInterfaceType == + NvOdmUsbInterfaceType_UlpiNullPhy) { + /* query the modem control pins */ + if (ste_u3xx_query(&ste_u3xx_info) < 0) + goto ExitUlpiOdm; + + NvOsDebugPrintf("turn modem on\n"); + ste_u3xx_turn_on_modem(&ste_u3xx_info); + } + return pDevice; + +ExitUlpiOdm: + if (pDevice) + NvOdmOsFree(pDevice); + return NULL; +} + +void NvOdmUsbUlpiClose(NvOdmUsbUlpiHandle hOdmUlpi) +{ + if (hOdmUlpi) { + NvOdmOsFree(hOdmUlpi); + hOdmUlpi = NULL; + } +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/Makefile new file mode 100644 index 000000000000..b19449bd3cfa --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/Makefile @@ -0,0 +1,18 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626 +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x + +obj-y += pmu_hal.o +obj-y += max8907b/ +obj-y += pcf50626/ +obj-y += tps6586x/ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/Makefile new file mode 100644 index 000000000000..321377d9317f --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/Makefile @@ -0,0 +1,22 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b + +obj-y += ad5258_dpm.o +obj-y += fan5355_buck_i2c.o +obj-y += max8907b_adc.o +obj-y += max8907b_batterycharger.o +obj-y += max8907b.o +obj-y += max8907b_i2c.o +obj-y += max8907b_interrupt.o +obj-y += max8907b_rtc.o +obj-y += mic2826_i2c.o +obj-y += tca6416_expander_i2c.o diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.c new file mode 100644 index 000000000000..7f785f920afc --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_pmu.h" +#include "nvodm_services.h" +#include "ad5258_dpm.h" + + +static NvBool +Ad5258I2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data) +{ + NvU32 i; + NvU8 WriteBuffer[2]; + NvOdmI2cTransactionInfo TransactionInfo; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + + for (i = 0; i < AD5258_I2C_RETRY_CNT; i++) + { + WriteBuffer[0] = Addr & 0xFF; // AD5258 address + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = AD5258_SLAVE_ADDR; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + AD5258_I2C_SPEED_KHZ, AD5258_I2C_TIMEOUT_MS); + if (status == NvOdmI2cStatus_Success) + return NV_TRUE; + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmDpmI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmDpmI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + +static NvBool +Ad5258I2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data) +{ + NvU32 i; + NvU8 ReadBuffer = 0; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + for (i = 0; i < AD5258_I2C_RETRY_CNT; i++) + { + // The AD5258 register address + ReadBuffer = Addr & 0xFF; + + TransactionInfo[0].Address = AD5258_SLAVE_ADDR; + TransactionInfo[0].Buf = &ReadBuffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + + TransactionInfo[1].Address = (AD5258_SLAVE_ADDR | 0x1);; + TransactionInfo[1].Buf = &ReadBuffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + // Read data from PMU at the specified offset + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2, + AD5258_I2C_SPEED_KHZ, AD5258_I2C_TIMEOUT_MS); + if (status == NvOdmI2cStatus_Success) + { + *Data = ReadBuffer; + return NV_TRUE; + } + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmDpmI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmDpmI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + +NvBool +Ad5258I2cSetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 MilliVolts) +{ + static NvU32 s_LastMilliVolts = 0; + + NvU8 Data = 0; + NvU8 Addr = AD5258_RDAC_ADDR; + + if (s_LastMilliVolts == 0) + { + if (!Ad5258I2cGetVoltage(hDevice, &s_LastMilliVolts)) + return NV_FALSE; + NV_ASSERT((s_LastMilliVolts >= AD5258_V0) && + (s_LastMilliVolts <= AD5258_VMAX)); + } + + // Change voltage level one maximum allowed step at a time + while (s_LastMilliVolts != MilliVolts) + { + if (MilliVolts > s_LastMilliVolts + AD5258_MAX_STEP_MV) + s_LastMilliVolts += AD5258_MAX_STEP_MV; + else if (MilliVolts + AD5258_MAX_STEP_MV < s_LastMilliVolts) + s_LastMilliVolts -= AD5258_MAX_STEP_MV; + else + s_LastMilliVolts = MilliVolts; + + // D(Vout) = (Vout - V0) * M1 / 2^b + Data = 0; + if (s_LastMilliVolts > AD5258_V0) + { + Data = (NvU8)(((s_LastMilliVolts - AD5258_V0) * AD5258_M1 + + (0x1 << (AD5258_b - 1))) >> AD5258_b); + Data++; // account for load + } + NV_ASSERT(Data <= AD5258_RDAC_MASK); + if (!Ad5258I2cWrite8(hDevice, Addr, Data)) + return NV_FALSE; + NvOdmOsWaitUS(AD5258_MAX_STEP_SETTLE_TIME_US); + } + return NV_TRUE; +} + +NvBool +Ad5258I2cGetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32* pMilliVolts) +{ + NvU8 Data = 0; + NvU8 Addr = AD5258_RDAC_ADDR; + + if (!Ad5258I2cRead8(hDevice, Addr, &Data)) + return NV_FALSE; + + // Vout(D) = V0 + (D * M2) / 2^b + Data &= AD5258_RDAC_MASK; + *pMilliVolts = AD5258_V0 + + (((NvU32)Data * AD5258_M2 + (0x1 << (AD5258_b - 1))) >> AD5258_b); + + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h new file mode 100644 index 000000000000..8bfd23eecf59 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/ad5258_dpm.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_AD5258_DPM_I2C_H +#define INCLUDED_AD5258_DPM_I2C_H + +#include "nvodm_pmu.h" +#include "max8907b.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define AD5258_SLAVE_ADDR (0x9C) // (7'h4E) +#define AD5258_I2C_SPEED_KHZ (400) +#define AD5258_I2C_RETRY_CNT (2) +#define AD5258_I2C_TIMEOUT_MS (1000) + +#define AD5258_RDAC_ADDR (0x0) +#define AD5258_RDAC_MASK (0x3F) + +/* + * Linear approximation of digital potentiometer (DPM) scaling ladder: + * D(Vout) = (Vout - V0) * M1 / 2^b + * Vout(D) = V0 + (D * M2) / 2^b + * D - DPM setting, Vout - output voltage in mV, b - fixed point calculation + * precision, approximation parameters V0, M1, M2 are determined for the + * particular schematic combining constant resistors, DPM, and DCDC supply. + */ +// On Whistler: +#define AD5258_V0 (815) +#define AD5258_M1 (229) +#define AD5258_M2 (4571) +#define AD5258_b (10) + +#define AD5258_VMAX (AD5258_V0 + ((AD5258_RDAC_MASK * AD5258_M2 + \ + (0x1 << (AD5258_b - 1))) >> AD5258_b)) + +// Minimum voltage step is determined by DPM resolution, maximum voltage step +// is limited to keep dynamic over/under shoot within +/- 50mV +#define AD5258_MIN_STEP_MV ((AD5258_M2 + (0x1 << AD5258_b) - 1) >> AD5258_b) +#define AD5258_MAX_STEP_MV (50) +#define AD5258_MAX_STEP_SETTLE_TIME_US (20) +#define AD5258_TURN_ON_TIME_US (2000) + +NvBool +Ad5258I2cSetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 MilliVolts); + +NvBool +Ad5258I2cGetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32* pMilliVolts); + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_AD5258_DPM_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_i2c.c new file mode 100644 index 000000000000..bb00b0bbab1f --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_i2c.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_pmu.h" +#include "nvodm_services.h" +#include "fan5355_buck_i2c.h" +#include "fan5355_buck_reg.h" + +// Function declaration +NvBool Fan5355I2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data) +{ + NvU8 WriteBuffer[2]; + NvOdmI2cTransactionInfo TransactionInfo; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + + WriteBuffer[0] = Addr & 0xFF; // PMU offset + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = FAN5335_SLAVE_ADDR; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + FAN5335_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + +NvBool Fan5355I2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data) +{ + NvU8 ReadBuffer = 0; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + // Write the PMU offset + ReadBuffer = Addr & 0xFF; + + TransactionInfo[0].Address = FAN5335_SLAVE_ADDR; + TransactionInfo[0].Buf = &ReadBuffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + + TransactionInfo[1].Address = (FAN5335_SLAVE_ADDR | 0x1);; + TransactionInfo[1].Buf = &ReadBuffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + // Read data from PMU at the specified offset + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2, + FAN5335_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + *Data = ReadBuffer; + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_i2c.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_i2c.h new file mode 100644 index 000000000000..7df90a192769 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_i2c.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_FAN5355_BUCK_I2C_H +#define INCLUDED_FAN5355_BUCK_I2C_H + +#include "nvodm_pmu.h" +#include "max8907b.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define FAN5335_SLAVE_ADDR 0x94 // (7'h4A) +#define FAN5335_I2C_SPEED_KHZ 400 + +NvBool Fan5355I2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data); + +NvBool Fan5355I2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data); + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_FAN5355_BUCK_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_reg.h new file mode 100644 index 000000000000..104be89ac462 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/fan5355_buck_reg.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_FAN5355_BUCK_REG_HEADER +#define INCLUDED_FAN5355_BUCK_REG_HEADER + +// Registers + +/* field defines for register bit ops */ + +#define FAN5335_VSEL0 0x0 +#define FAN5335_VSEL1 0x1 +#define FAN5335_CONTROL1 0x2 +#define FAN5335_CONTROL2 0x3 + +#define FAN5335_REG_INVALID 0xFF + +#endif //INCLUDED_FAN5355_BUCK_REG_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c new file mode 100644 index 000000000000..285044034f97 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.c @@ -0,0 +1,2324 @@ +/* + * Copyright (c) 2007-2010 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_query_discovery.h" +#include "nvodm_query.h" +#include "nvodm_services.h" +#include "max8907b.h" +#include "max8907b_reg.h" +#include "max8907b_adc.h" +#include "max8907b_i2c.h" +#include "max8907b_interrupt.h" +#include "max8907b_batterycharger.h" +#include "max8907b_supply_info_table.h" +#include "fan5355_buck_reg.h" +#include "fan5355_buck_i2c.h" +#include "tca6416_expander_reg.h" +#include "tca6416_expander_i2c.h" +#include "mic2826_reg.h" +#include "mic2826_i2c.h" +#include "ad5258_dpm.h" + +// Private PMU context info +Max8907bPrivData *hMax8907bPmu; + +#define PMUGUID NV_ODM_GUID('m','a','x','8','9','0','7','b') + +#define MAX_CHARGER_LIMIT_MA 1000 + +#define ALWAYS_ONLINE (1) + +/** + * MAX8907B regulators can be enabled/disabled via s/w I2C commands only + * when MAX8907B_SEQSEL_I2CEN_LXX (7) is selected as regulator sequencer. + * Otherwise, regulator is controlled by h/w sequencers: SEQ1 (SYSEN), + * which is always On when PMU is On, or SEQ2 (PWREN) which is always On, + * when system is running (it is Off in LPx mode only). + */ +#define MAX8907B_OUT_VOLTAGE_CONTROL_MASK \ + ((MAX8907B_CTL_SEQ_MASK << MAX8907B_CTL_SEQ_SHIFT) | \ + MAX8907B_OUT_VOLTAGE_ENABLE_BIT) + +#define MAX8907B_OUT_VOLTAGE_CONTROL_DISABLE \ + (MAX8907B_SEQSEL_I2CEN_LXX << MAX8907B_CTL_SEQ_SHIFT) + +// MAX8907B revision that requires s/w WAR to connect PWREN input to +// sequencer 2 because of the bug in the silicon. +#define MAX8907B_II2RR_PWREN_WAR (0x12) + +/** +* The FAN5355 is used to scale the voltage of an external +* DC/DC voltage rail (for PCIE). However, voltage scaling is +* not required for this source, since the 1.05V default +* voltage when enabled is OK. On some boards, the FAN5355 may +* not function properly, as an I2C re-work may be required +* (otherwise, the slave address may not be found). Therefore, +* this feature is disabled by default. +*/ +#undef MAX8907B_USE_FAN5355_VOLTAGE_SCALING + +/*-- Output Voltage tables --*/ + +// V1, V2 (millivolts x 10) +static const NvU32 VoltageTable_SD_A[] = { + 6375, 6500, 6625, 6750, 6875, 7000, 7125, 7250, + 7375, 7500, 7625, 7750, 7875, 8000, 8125, 8250, + 8375, 8500, 8625, 8750, 8875, 9000, 9125, 9250, + 9375, 9500, 9625, 9750, 9875, 10000, 10125, 10250, + 10375, 10500, 10625, 10750, 10875, 11000, 11125, 11250, + 11375, 11500, 11625, 11750, 11875, 12000, 12125, 12250, + 12375, 12500, 12625, 12750, 12875, 13000, 13125, 13250, + 13375, 13500, 13625, 13750, 13875, 14000, 14125, 14250 +}; + +// V3, LDO1, LDO4-LDO16, LDO19-20 (millivolts) +static const NvU32 VoltageTable_SD_B_LDO_B[] = { + 750, 800, 850, 900, 950, 1000, 1050, 1100, + 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500, + 1550, 1600, 1650, 1700, 1750, 1800, 1850, 1900, + 1950, 2000, 2050, 2100, 2150, 2200, 2250, 2300, + 2350, 2400, 2450, 2500, 2550, 2600, 2650, 2700, + 2750, 2800, 2850, 2900, 2950, 3000, 3050, 3100, + 3150, 3200, 3250, 3300, 3350, 3400, 3450, 3500, + 3550, 3600, 3650, 3700, 3750, 3800, 3850, 3900 +}; + +// LDO2, LDO3, LDO17, LDO18 (millivolts) +static const NvU32 VoltageTable_LDO_A[] = { + 650, 675, 700, 725, 750, 775, 800, 825, + 850, 875, 900, 925, 950, 975, 1000, 1025, + 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1225, + 1250, 1275, 1300, 1325, 1350, 1375, 1400, 1425, + 1450, 1475, 1500, 1525, 1550, 1575, 1600, 1625, + 1650, 1675, 1700, 1725, 1750, 1775, 1800, 1825, + 1850, 1875, 1900, 1925, 1950, 1975, 2000, 2025, + 2050, 2075, 2100, 2125, 2150, 2175, 2200, 2225 +}; + +// FAN5355 VOUT_02 (millivolts x 10) +static const NvU32 VoltageTable_VOUT_02[] = { + 7500, 7625, 7750, 7875, 8000, 8125, 8250, 8375, + 8500, 8625, 8750, 8875, 9000, 9125, 9250, 9375, + 9500, 9625, 9750, 9875, 10000, 10125, 10250, 10375, + 10500, 10625, 10750, 10875, 11000, 11125, 11250, 11375, + 11500, 11625, 11750, 11875, 12000, 12125, 12250, 12375, + 12500, 12625, 12750, 12875, 13000, 13125, 13250, 13375, + 13500, 13625, 13750, 13875, 14000, 14125, 14250, 14375, +}; + +/*-- Sequencer table --*/ + +// Timer period, microseconds (us). +// Specifies the time between each sequencer event. + +// Disable temporarily to keep the compiler happy. +//static const NvU32 SequencerPeriod[] = { 20, 40, 80, 160, 320, 640, 1280, 2560 }; + +/*-- Voltage translation functions --*/ + +// OutVoltageIndex is the lower six bits of the output voltage registers, VO[5:0] +static NvU32 Max8907bPmuVoltageGet_SD_A(const NvU32 OutVoltageIndex); +static NvU32 Max8907bPmuVoltageGet_SD_B_LDO_B(const NvU32 OutVoltageIndex); +static NvU32 Max8907bPmuVoltageGet_LDO_A(const NvU32 OutVoltageIndex); + +static NvU32 Max8907bPmuVoltageSet_SD_A(const NvU32 OutMilliVolts); +static NvU32 Max8907bPmuVoltageSet_SD_B_LDO_B(const NvU32 OutMilliVolts); +static NvU32 Max8907bPmuVoltageSet_LDO_A(const NvU32 OutMilliVolts); + +#define MAX8907B_MAX_OUTPUT_VOLTAGE_INDEX 0x3F +#define FAN5355_MAX_OUTPUT_VOLTAGE_INDEX 0x37 + +static NvU32 Max8907bPmuVoltageGet_SD_A(const NvU32 OutVoltageIndex) +{ + NV_ASSERT(OutVoltageIndex <= MAX8907B_MAX_OUTPUT_VOLTAGE_INDEX); + return VoltageTable_SD_A[OutVoltageIndex]/10; +} + +static NvU32 Max8907bPmuVoltageGet_SD_B_LDO_B(const NvU32 OutVoltageIndex) +{ + NV_ASSERT(OutVoltageIndex <= MAX8907B_MAX_OUTPUT_VOLTAGE_INDEX); + return VoltageTable_SD_B_LDO_B[OutVoltageIndex]; +} + +static NvU32 Max8907bPmuVoltageGet_LDO_A(const NvU32 OutVoltageIndex) +{ + NV_ASSERT(OutVoltageIndex <= MAX8907B_MAX_OUTPUT_VOLTAGE_INDEX); + return VoltageTable_LDO_A[OutVoltageIndex]; +} + +// Secondary PMU MIC2826 API +static NvBool MIC2826ReadVoltageReg(NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, NvU32* pMilliVolts); + +static NvBool MIC2826WriteVoltageReg( NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, NvU32 MilliVolts, NvU32* pSettleMicroSeconds); + +const NvU8 MIC2826_BUCK_Votage_Table[] = +{ + MIC2826_BUCK_OUT_VOLTAGE_0800, + MIC2826_BUCK_OUT_VOLTAGE_0825, + MIC2826_BUCK_OUT_VOLTAGE_0850, + MIC2826_BUCK_OUT_VOLTAGE_0875, + MIC2826_BUCK_OUT_VOLTAGE_0900, + MIC2826_BUCK_OUT_VOLTAGE_0925, + MIC2826_BUCK_OUT_VOLTAGE_0950, + MIC2826_BUCK_OUT_VOLTAGE_0975, + MIC2826_BUCK_OUT_VOLTAGE_1000, + MIC2826_BUCK_OUT_VOLTAGE_1025, + MIC2826_BUCK_OUT_VOLTAGE_1050, + MIC2826_BUCK_OUT_VOLTAGE_1075, + MIC2826_BUCK_OUT_VOLTAGE_1100, + MIC2826_BUCK_OUT_VOLTAGE_1125, + MIC2826_BUCK_OUT_VOLTAGE_1150, + MIC2826_BUCK_OUT_VOLTAGE_1175, + MIC2826_BUCK_OUT_VOLTAGE_1200, + MIC2826_BUCK_OUT_VOLTAGE_1250, + MIC2826_BUCK_OUT_VOLTAGE_1300, + MIC2826_BUCK_OUT_VOLTAGE_1350, + MIC2826_BUCK_OUT_VOLTAGE_1400, + MIC2826_BUCK_OUT_VOLTAGE_1450, + MIC2826_BUCK_OUT_VOLTAGE_1500, + MIC2826_BUCK_OUT_VOLTAGE_1550, + MIC2826_BUCK_OUT_VOLTAGE_1600, + MIC2826_BUCK_OUT_VOLTAGE_1650, + MIC2826_BUCK_OUT_VOLTAGE_1700, + MIC2826_BUCK_OUT_VOLTAGE_1750, + MIC2826_BUCK_OUT_VOLTAGE_1800 +}; + +const NvU8 MIC2826_LDO_Votage_Table[] = +{ + MIC2826_LDO_OUT_VOLTAGE_0800, + MIC2826_LDO_OUT_VOLTAGE_0850, + MIC2826_LDO_OUT_VOLTAGE_0900, + MIC2826_LDO_OUT_VOLTAGE_0950, + MIC2826_LDO_OUT_VOLTAGE_1000, + MIC2826_LDO_OUT_VOLTAGE_1050, + MIC2826_LDO_OUT_VOLTAGE_1100, + MIC2826_LDO_OUT_VOLTAGE_1150, + MIC2826_LDO_OUT_VOLTAGE_1200, + MIC2826_LDO_OUT_VOLTAGE_1250, + MIC2826_LDO_OUT_VOLTAGE_1300, + MIC2826_LDO_OUT_VOLTAGE_1350, + MIC2826_LDO_OUT_VOLTAGE_1400, + MIC2826_LDO_OUT_VOLTAGE_1450, + MIC2826_LDO_OUT_VOLTAGE_1500, + MIC2826_LDO_OUT_VOLTAGE_1550, + MIC2826_LDO_OUT_VOLTAGE_1600, + MIC2826_LDO_OUT_VOLTAGE_1650, + MIC2826_LDO_OUT_VOLTAGE_1700, + MIC2826_LDO_OUT_VOLTAGE_1750, + MIC2826_LDO_OUT_VOLTAGE_1800, + MIC2826_LDO_OUT_VOLTAGE_1850, + MIC2826_LDO_OUT_VOLTAGE_1900, + MIC2826_LDO_OUT_VOLTAGE_1950, + MIC2826_LDO_OUT_VOLTAGE_2000, + MIC2826_LDO_OUT_VOLTAGE_2050, + MIC2826_LDO_OUT_VOLTAGE_2100, + MIC2826_LDO_OUT_VOLTAGE_2150, + MIC2826_LDO_OUT_VOLTAGE_2200, + MIC2826_LDO_OUT_VOLTAGE_2250, + MIC2826_LDO_OUT_VOLTAGE_2300, + MIC2826_LDO_OUT_VOLTAGE_2350, + MIC2826_LDO_OUT_VOLTAGE_2400, + MIC2826_LDO_OUT_VOLTAGE_2450, + MIC2826_LDO_OUT_VOLTAGE_2500, + MIC2826_LDO_OUT_VOLTAGE_2550, + MIC2826_LDO_OUT_VOLTAGE_2600, + MIC2826_LDO_OUT_VOLTAGE_2650, + MIC2826_LDO_OUT_VOLTAGE_2700, + MIC2826_LDO_OUT_VOLTAGE_2750, + MIC2826_LDO_OUT_VOLTAGE_2800, + MIC2826_LDO_OUT_VOLTAGE_2850, + MIC2826_LDO_OUT_VOLTAGE_2900, + MIC2826_LDO_OUT_VOLTAGE_2950, + MIC2826_LDO_OUT_VOLTAGE_3000, + MIC2826_LDO_OUT_VOLTAGE_3050, + MIC2826_LDO_OUT_VOLTAGE_3100, + MIC2826_LDO_OUT_VOLTAGE_3150, + MIC2826_LDO_OUT_VOLTAGE_3200, + MIC2826_LDO_OUT_VOLTAGE_3250, + MIC2826_LDO_OUT_VOLTAGE_3300 +}; + +#define MIC2826_BUCK_Votage_Table_Size NV_ARRAY_SIZE(MIC2826_BUCK_Votage_Table) +#define MIC2826_LDO_Votage_Table_Size NV_ARRAY_SIZE(MIC2826_LDO_Votage_Table) + +#ifndef MIN +#define MIN(a, b) (a) <= (b) ? (a) : (b) +#endif + +#define MAX8907B_MIN_OUTPUT_VOLTAGE_SD_A_x10 6375 // 637.5 mV +#define MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B 750 // 750 mV +#define MAX8907B_MIN_OUTPUT_VOLTAGE_LDO_A 650 // 650 mV +#define FAN5355_MIN_OUTPUT_VOLTAGE_x10 7500 // 750.0 mV + +#define MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_A_x10 125 // 12.5 mV +#define MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B 50 // 50 mV +#define MAX8907B_OUTPUT_VOLTAGE_INCREMENT_LDO_A 25 // 25 mV +#define FAN5355_OUTPUT_VOLTAGE_INCREMENT_x10 125 // 12.5 mV + +#define MAX8907B_MAX_OUTPUT_VOLTAGE_SD_A_x10 14250 // 1,425.0 mV +#define MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B 3900 // 3,900 mV +#define MAX8907B_MAX_OUTPUT_VOLTAGE_LDO_A 2225 // 2,225 mV +#define FAN5355_MAX_OUTPUT_VOLTAGE_x10 14375 // 1,437.5 mV + +#define MAX8907B_MIN_OUTPUT_VOLTAGE_RTC 0 // 0 mV +#define MAX8907B_OUTPUT_VOLTAGE_INCREMENT_RTC 1 // Protected; use dummy, non-zero value +//#define MAX8907B_MAX_OUTPUT_VOLTAGE_RTC 3300 // 3,300 mV +// WHISTLER/AP16 - Make this 1.2V for now, since ap15rm_power.c expects it that way. +#define MAX8907B_MAX_OUTPUT_VOLTAGE_RTC 1200 + +static NvU32 Max8907bPmuVoltageSet_SD_A(const NvU32 OutMilliVolts) +{ + if (OutMilliVolts < MAX8907B_MIN_OUTPUT_VOLTAGE_SD_A_x10/10) + return 0; + else + return MIN( \ + (OutMilliVolts*10 - MAX8907B_MIN_OUTPUT_VOLTAGE_SD_A_x10) / \ + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_A_x10, \ + MAX8907B_MAX_OUTPUT_VOLTAGE_INDEX); +} + +static NvU32 Max8907bPmuVoltageSet_SD_B_LDO_B(const NvU32 OutMilliVolts) +{ + if (OutMilliVolts < MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B) + return 0; + else + return MIN( \ + (OutMilliVolts - MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B) / \ + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, \ + MAX8907B_MAX_OUTPUT_VOLTAGE_INDEX); +} + +static NvU32 Max8907bPmuVoltageSet_LDO_A(const NvU32 OutMilliVolts) +{ + if (OutMilliVolts < MAX8907B_MIN_OUTPUT_VOLTAGE_LDO_A) + return 0; + else + return MIN( \ + (OutMilliVolts - MAX8907B_MIN_OUTPUT_VOLTAGE_LDO_A) / \ + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_LDO_A, \ + MAX8907B_MAX_OUTPUT_VOLTAGE_INDEX); +} + +static NvU32 Fan5355PmuVoltageGet_VOUT_02(const NvU32 OutVoltageIndex) +{ + NV_ASSERT(OutVoltageIndex <= FAN5355_MAX_OUTPUT_VOLTAGE_INDEX); + return VoltageTable_VOUT_02[OutVoltageIndex]/10; +} + +static NvU32 Fan5355PmuVoltageSet_VOUT_02(const NvU32 OutMilliVolts) +{ + if (OutMilliVolts < FAN5355_MIN_OUTPUT_VOLTAGE_x10/10) + return 0; + else + return MIN( \ + (OutMilliVolts*10 - FAN5355_MIN_OUTPUT_VOLTAGE_x10) / \ + FAN5355_OUTPUT_VOLTAGE_INCREMENT_x10, \ + FAN5355_MAX_OUTPUT_VOLTAGE_x10); +} + +// This board-specific table is indexed by Max8907bPmuSupply +const Max8907bPmuSupplyInfo Max8907bSupplyInfoTable[] = +{ + { + Max8907bPmuSupply_Invalid, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + {NV_TRUE, 0, 0, 0, 0}, + }, + + // LX_V1 (V1) + { + Max8907bPmuSupply_LX_V1, + MAX8907B_SDCTL1, + MAX8907B_SDSEQCNT1, + MAX8907B_SDV1, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_A, + Max8907bPmuVoltageSet_SD_A, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_A_x10/10, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_A_x10/10, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_A_x10/10, + MAX8907B_REQUESTVOLTAGE_LX_V1 + }, + }, + + // LX_V2 (V2) + { + Max8907bPmuSupply_LX_V2, + MAX8907B_SDCTL2, + MAX8907B_SDSEQCNT2, + MAX8907B_SDV2, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_A, + Max8907bPmuVoltageSet_SD_A, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_A_x10/10, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_A_x10/10, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_A_x10/10, + MAX8907B_REQUESTVOLTAGE_LX_V2 + }, + }, + + // LX_V3 (V3) + { + Max8907bPmuSupply_LX_V3, + MAX8907B_SDCTL3, + MAX8907B_SDSEQCNT3, + MAX8907B_SDV3, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LX_V3 + }, + }, + + // VRTC (RTC) + { + Max8907bPmuSupply_VRTC, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + { + NV_TRUE, + MAX8907B_MIN_OUTPUT_VOLTAGE_RTC, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_RTC, + MAX8907B_MAX_OUTPUT_VOLTAGE_RTC, + MAX8907B_MAX_OUTPUT_VOLTAGE_RTC + }, + }, + + // LDO1 (VOUT1) + { + Max8907bPmuSupply_LDO1, + MAX8907B_LDOCTL1, + MAX8907B_LDOSEQCNT1, + MAX8907B_LDO1VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO1 + }, + }, + + // LDO2 (VOUT2) + { + Max8907bPmuSupply_LDO2, + MAX8907B_LDOCTL2, + MAX8907B_LDOSEQCNT2, + MAX8907B_LDO2VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_LDO_A, + Max8907bPmuVoltageSet_LDO_A, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_LDO_A, + MAX8907B_MAX_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_REQUESTVOLTAGE_LDO2 + }, + }, + + // LDO3 (VOUT3) + { + Max8907bPmuSupply_LDO3, + MAX8907B_LDOCTL3, + MAX8907B_LDOSEQCNT3, + MAX8907B_LDO3VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_LDO_A, + Max8907bPmuVoltageSet_LDO_A, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_LDO_A, + MAX8907B_MAX_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_REQUESTVOLTAGE_LDO3 + }, + }, + + // LDO4 (VOUT4) + { + Max8907bPmuSupply_LDO4, + MAX8907B_LDOCTL4, + MAX8907B_LDOSEQCNT4, + MAX8907B_LDO4VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO4 + }, + }, + + // LDO5 (VOUT5) + { + Max8907bPmuSupply_LDO5, + MAX8907B_LDOCTL5, + MAX8907B_LDOSEQCNT5, + MAX8907B_LDO5VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO5 + }, + }, + + // LDO6 (VOUT6) + { + Max8907bPmuSupply_LDO6, + MAX8907B_LDOCTL6, + MAX8907B_LDOSEQCNT6, + MAX8907B_LDO6VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO6 + }, + }, + + // LDO7 (VOUT7) + { + Max8907bPmuSupply_LDO7, + MAX8907B_LDOCTL7, + MAX8907B_LDOSEQCNT7, + MAX8907B_LDO7VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO7 + }, + }, + + // LDO8 (VOUT8) + { + Max8907bPmuSupply_LDO8, + MAX8907B_LDOCTL8, + MAX8907B_LDOSEQCNT8, + MAX8907B_LDO8VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO8 + }, + }, + + // LDO9 (VOUT9) + { + Max8907bPmuSupply_LDO9, + MAX8907B_LDOCTL9, + MAX8907B_LDOSEQCNT9, + MAX8907B_LDO9VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO9 + }, + }, + + // LDO10 (VOUT10) + { + Max8907bPmuSupply_LDO10, + MAX8907B_LDOCTL10, + MAX8907B_LDOSEQCNT10, + MAX8907B_LDO10VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO10 + }, + }, + + // LDO11 (VOUT11) + { + Max8907bPmuSupply_LDO11, + MAX8907B_LDOCTL11, + MAX8907B_LDOSEQCNT11, + MAX8907B_LDO11VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO11 + }, + }, + + // LDO12 (VOUT12) + { + Max8907bPmuSupply_LDO12, + MAX8907B_LDOCTL12, + MAX8907B_LDOSEQCNT12, + MAX8907B_LDO12VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO12 + }, + }, + + // LDO13 (VOUT13) + { + Max8907bPmuSupply_LDO13, + MAX8907B_LDOCTL13, + MAX8907B_LDOSEQCNT13, + MAX8907B_LDO13VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO13 + }, + }, + + // LDO14 (VOUT14) + { + Max8907bPmuSupply_LDO14, + MAX8907B_LDOCTL14, + MAX8907B_LDOSEQCNT14, + MAX8907B_LDO14VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO14 + }, + }, + + // LDO15 (VOUT15) + { + Max8907bPmuSupply_LDO15, + MAX8907B_LDOCTL15, + MAX8907B_LDOSEQCNT15, + MAX8907B_LDO15VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO15 + }, + }, + + // LDO16 (VOUT16) + { + Max8907bPmuSupply_LDO16, + MAX8907B_LDOCTL16, + MAX8907B_LDOSEQCNT16, + MAX8907B_LDO16VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO16 + }, + }, + + // LDO17 (VOUT17) + { + Max8907bPmuSupply_LDO17, + MAX8907B_LDOCTL17, + MAX8907B_LDOSEQCNT17, + MAX8907B_LDO17VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_LDO_A, + Max8907bPmuVoltageSet_LDO_A, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_LDO_A, + MAX8907B_MAX_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_REQUESTVOLTAGE_LDO17 + }, + }, + + // LDO18 (VOUT18) + { + Max8907bPmuSupply_LDO18, + MAX8907B_LDOCTL18, + MAX8907B_LDOSEQCNT18, + MAX8907B_LDO18VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_LDO_A, + Max8907bPmuVoltageSet_LDO_A, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_LDO_A, + MAX8907B_MAX_OUTPUT_VOLTAGE_LDO_A, + MAX8907B_REQUESTVOLTAGE_LDO18 + }, + }, + + // LDO19 (VOUT19) + { + Max8907bPmuSupply_LDO19, + MAX8907B_LDOCTL19, + MAX8907B_LDOSEQCNT19, + MAX8907B_LDO19VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO19 + }, + }, + + // LDO20 (VOUT20) + { + Max8907bPmuSupply_LDO20, + MAX8907B_LDOCTL20, + MAX8907B_LDOSEQCNT20, + MAX8907B_LDO20VOUT, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + Max8907bPmuVoltageGet_SD_B_LDO_B, + Max8907bPmuVoltageSet_SD_B_LDO_B, + { + NV_FALSE, + MAX8907B_MIN_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_OUTPUT_VOLTAGE_INCREMENT_SD_B_LDO_B, + MAX8907B_MAX_OUTPUT_VOLTAGE_SD_B_LDO_B, + MAX8907B_REQUESTVOLTAGE_LDO20 + }, + }, + + // WHITE_LED + { + Max8907bPmuSupply_WHITE_LED, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + {NV_TRUE, 0, 0, 0, 0}, + }, + + // EXT_DC/DC1 (for HDMI, VGA, USB) + // By default, this is hard-wired as "always on" (see schematics) + { + Max8907bPmuSupply_EXT_DCDC_1, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + { + NV_TRUE, + MAX8907B_REQUESTVOLTAGE_EXT_DCDC_1, + 0, + MAX8907B_REQUESTVOLTAGE_EXT_DCDC_1, + MAX8907B_REQUESTVOLTAGE_EXT_DCDC_1 + }, + }, + + // EXT_DC/DC2 (not connected / reserved) + { + Max8907bPmuSupply_EXT_DCDC_2, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + {NV_TRUE, 0, 0, 0, 0}, + }, + + // EXT_DC/DC3 (PCI Express) + { + Max8907bPmuSupply_EXT_DCDC_3, + TCA6416_CONFIG_PORT_0, + MAX8907B_REG_INVALID, + FAN5335_VSEL0, + TCA6416_PORT_0, + TCA6416_PIN_6, + Fan5355PmuVoltageGet_VOUT_02, + Fan5355PmuVoltageSet_VOUT_02, + { + NV_FALSE, + FAN5355_MIN_OUTPUT_VOLTAGE_x10/10, + FAN5355_OUTPUT_VOLTAGE_INCREMENT_x10/10, + FAN5355_MAX_OUTPUT_VOLTAGE_x10/10, + MAX8907B_REQUESTVOLTAGE_EXT_DCDC_3 + }, + }, + + // EXT_DC/DC4 (Backlight-1 Intensity Enable) + // By default, this is hard-wired as "always enabled" (see schematics) + { + Max8907bPmuSupply_EXT_DCDC_4, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + {NV_TRUE, 0, 0, 0, 0}, + }, + + // EXT_DC/DC5 (Backlight-2 Intensity Enable) + // By default, this is hard-wired as "always enabled" (see schematics) + { + Max8907bPmuSupply_EXT_DCDC_5, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + {NV_TRUE, 0, 0, 0, 0}, + }, + + // EXT_DC/DC6 (not connected / reserved) + { + Max8907bPmuSupply_EXT_DCDC_6, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + {NV_TRUE, 0, 0, 0, 0}, + }, + + // USB1 VBUS is wired from with DCDC_3. + { + Max8907bPmuSupply_EXT_DCDC_3_USB1, + TCA6416_CONFIG_PORT_0, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + TCA6416_PORT_0, + TCA6416_PIN_0, + NULL, + NULL, + { + NV_FALSE, + FAN5355_MIN_OUTPUT_VOLTAGE_x10/10, + FAN5355_OUTPUT_VOLTAGE_INCREMENT_x10/10, + FAN5355_MAX_OUTPUT_VOLTAGE_x10/10, + MAX8907B_REQUESTVOLTAGE_EXT_DCDC_3 + }, + }, + + // USB3 VBUS is wired from with DCDC_3. + { + Max8907bPmuSupply_EXT_DCDC_3_USB3, + TCA6416_CONFIG_PORT_0, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + TCA6416_PORT_0, + TCA6416_PIN_1, + NULL, + NULL, + { + NV_FALSE, + FAN5355_MIN_OUTPUT_VOLTAGE_x10/10, + FAN5355_OUTPUT_VOLTAGE_INCREMENT_x10/10, + FAN5355_MAX_OUTPUT_VOLTAGE_x10/10, + MAX8907B_REQUESTVOLTAGE_EXT_DCDC_3 + }, + }, + + // MIC2826 BUCK Regulator(BUCK) + { + MIC2826PmuSupply_BUCK, + MIC2826_REG_ADDR_BUCK, + MIC2826_REG_INVALID, + MIC2826_REG_INVALID, + MIC2826_INVALID_PORT, + MIC2826_INVALID_PORT, + NULL, + NULL, + { + NV_FALSE, + MIC2826_BUCK_VOLTAGE_MIN_MV, + MIC2826_BUCK_VOLTAGE_STEP_MV, + MIC2826_BUCK_VOLTAGE_MAX_MV, + MIC2826_BUCK_REQUESTVOLTAGE_MV + }, + }, + // MIC2826 LDO1 + { + MIC2826PmuSupply_LDO1, + MIC2826_REG_ADDR_LD01, + MIC2826_REG_INVALID, + MIC2826_REG_INVALID, + MIC2826_INVALID_PORT, + MIC2826_INVALID_PORT, + NULL, + NULL, + { + NV_FALSE, + MIC2826_LDO_VOLTAGE_MIN_MV, + MIC2826_LDO_VOLTAGE_STEP_MV, + MIC2826_LDO_VOLTAGE_MAX_MV, + MIC2826_LDO1_REQUESTVOLTAGE_MV + }, + }, + + // MIC2826 LDO2 + { + MIC2826PmuSupply_LDO2, + MIC2826_REG_ADDR_LD02, + MIC2826_REG_INVALID, + MIC2826_REG_INVALID, + MIC2826_INVALID_PORT, + MIC2826_INVALID_PORT, + NULL, + NULL, + { + NV_FALSE, + MIC2826_LDO_VOLTAGE_MIN_MV, + MIC2826_LDO_VOLTAGE_STEP_MV, + MIC2826_LDO_VOLTAGE_MAX_MV, + MIC2826_LDO2_REQUESTVOLTAGE_MV + }, + }, + + // LDO3 + { + MIC2826PmuSupply_LDO3, + MIC2826_REG_ADDR_LD03, + MIC2826_REG_INVALID, + MIC2826_REG_INVALID, + MIC2826_INVALID_PORT, + MIC2826_INVALID_PORT, + NULL, + NULL, + { + NV_FALSE, + MIC2826_LDO_VOLTAGE_MIN_MV, + MIC2826_LDO_VOLTAGE_STEP_MV, + MIC2826_LDO_VOLTAGE_MAX_MV, + MIC2826_LDO3_REQUESTVOLTAGE_MV + }, + }, + + // EXT_DC/DC7 (controlled by LX_V1, scaled by AD5258 DPM) + { + Max8907bLxV1_Ad5258_DPM_EXT_DCDC_7, + AD5258_RDAC_ADDR, + MAX8907B_REG_INVALID, + MAX8907B_REG_INVALID, + TCA6416_INVALID_PORT, + TCA6416_INVALID_PORT, + NULL, + NULL, + { + NV_FALSE, + AD5258_V0, + AD5258_MIN_STEP_MV, + AD5258_VMAX, + MAX8907B_REQUESTVOLTAGE_LX_V1 + }, + } +}; + +static NvBool +Max8907bReadVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + NvU8 data = 0; + NvU32 milliVolts = 0; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + if (pSupplyInfo->ControlRegAddr != MAX8907B_REG_INVALID) + { + if (!Max8907bI2cRead8(hDevice, pSupplyInfo->ControlRegAddr, &data)) + return NV_FALSE; + + if ((data & MAX8907B_OUT_VOLTAGE_CONTROL_MASK) == + MAX8907B_OUT_VOLTAGE_CONTROL_DISABLE) + { + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] = + ODM_VOLTAGE_OFF; + *pMilliVolts = ODM_VOLTAGE_OFF; + return NV_TRUE; + } + } + + if (pSupplyInfo->OutputVoltageRegAddr == MAX8907B_REG_INVALID) + return NV_FALSE; + + if (!Max8907bI2cRead8(hDevice, pSupplyInfo->OutputVoltageRegAddr, &data)) + return NV_FALSE; + + data &= MAX8907B_OUT_VOLTAGE_MASK; + if (!data) //OFF + milliVolts = ODM_VOLTAGE_OFF; + else + milliVolts = pSupplyInfo->GetVoltage(data); + + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] = milliVolts; + *pMilliVolts = milliVolts; + return NV_TRUE; +} + +static NvBool +Max8907bWriteVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + NvU8 data = 0; + NvU32 SettleUS = 0; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + if (MilliVolts == ODM_VOLTAGE_OFF) + { + // check if the supply can be turned off + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] == 1) + { + // turn off the supply + NvOdmServicesPmuSetSocRailPowerState( + ((Max8907bPrivData*)hDevice->pPrivate)->hOdmPmuSevice, pSupplyInfo->supply, NV_FALSE); + + // Disable the output (read-modify-write the control register) + Max8907bI2cRead8(hDevice, pSupplyInfo->ControlRegAddr, &data); + data &= (~MAX8907B_OUT_VOLTAGE_CONTROL_MASK); + data |= MAX8907B_OUT_VOLTAGE_CONTROL_DISABLE; + if (!Max8907bI2cWrite8(hDevice, pSupplyInfo->ControlRegAddr, data)) + return NV_FALSE; + + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] = + ODM_VOLTAGE_OFF; + SettleUS = MAX8907B_TURN_OFF_TIME_US; + } + + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] != 0) + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] --; + + if (pSettleMicroSeconds) + *pSettleMicroSeconds = SettleUS; + else + NvOdmOsWaitUS(SettleUS); + + return NV_TRUE; + } + + // Set voltage level + data = pSupplyInfo->SetVoltage(MilliVolts); + if (!Max8907bI2cWrite8(hDevice, pSupplyInfo->OutputVoltageRegAddr, data)) + return NV_FALSE; + if (MilliVolts > + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail]) + { + NvU32 LastMV = + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail]; + SettleUS = (MilliVolts - LastMV) * 1000 / MAX8907B_SCALE_UP_UV_PER_US; + } + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[vddRail] = MilliVolts; + + // turn on supply + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] == 0) + { + // Enable the output (read-modify-write the control register) + Max8907bI2cRead8(hDevice, pSupplyInfo->ControlRegAddr, &data); + + if ((data & MAX8907B_OUT_VOLTAGE_CONTROL_MASK) == + MAX8907B_OUT_VOLTAGE_CONTROL_DISABLE) + { + // Voltage on/change (supply was off, so it must be turned on) + NvOdmServicesPmuSetSocRailPowerState( + ((Max8907bPrivData*)(hDevice->pPrivate))->hOdmPmuSevice, + pSupplyInfo->supply, NV_TRUE); + data |= MAX8907B_OUT_VOLTAGE_ENABLE_BIT; + if (!Max8907bI2cWrite8(hDevice, pSupplyInfo->ControlRegAddr, data)) + return NV_FALSE; + + SettleUS = MAX8907B_TURN_ON_TIME_US; + } + } + + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] ++; + + if (pSettleMicroSeconds) + *pSettleMicroSeconds = SettleUS; + else + NvOdmOsWaitUS(SettleUS); + + return NV_TRUE; +} + +static NvBool +Max8907bOnOffConfigure(NvOdmPmuDeviceHandle hDevice) +{ + NvU8 data = 0; + + if (!Max8907bI2cRead8(hDevice, MAX8907B_SYSENSEL, &data)) + return NV_FALSE; + + // Enable hard reset - power-off after ONKEY press for 5 seconds + // (must be enabled for thermal auto-shutdown) + data |= (MAX8907B_SYSENSEL_HRDSTEN_MASK << + MAX8907B_SYSENSEL_HRDSTEN_SHIFT); + + return Max8907bI2cWrite8(hDevice, MAX8907B_SYSENSEL, data); +} + +static NvBool +Max8907bPwrEnConfigure(NvOdmPmuDeviceHandle hDevice, NvBool Enable) +{ + NvU8 data = 0; + + if (!Max8907bI2cRead8(hDevice, MAX8907B_RESET_CNFG, &data)) + return NV_FALSE; + + // Enable/disable PWREN h/w control mechanism (PWREN signal must be + // inactive = high at this time) + if (Enable) + data |= (MAX8907B_RESET_CNFG_PWREN_EN_MASK << + MAX8907B_RESET_CNFG_PWREN_EN_SHIFT); + else + data &= (~(MAX8907B_RESET_CNFG_PWREN_EN_MASK << + MAX8907B_RESET_CNFG_PWREN_EN_SHIFT)); + if (!Max8907bI2cWrite8(hDevice, MAX8907B_RESET_CNFG, data)) + return NV_FALSE; + + // When enabled, connect PWREN to SEQ2 by clearing SEQ2 configuration + // settings for silicon revision that requires s/w WAR. On other MAX8907B + // revisions PWREN is always connected to SEQ2. + if (Enable) + { + if (!Max8907bI2cRead8(hDevice, MAX8907B_II2RR, &data)) + return NV_FALSE; + + if (data == MAX8907B_II2RR_PWREN_WAR) + { + data = 0x00; + if (!Max8907bI2cWrite8(hDevice, MAX8907B_SEQ2CNFG, data)) + return NV_FALSE; + } + } + return NV_TRUE; +} + +static NvBool +Max8907bPwrEnAttach( + NvOdmPmuDeviceHandle hDevice, + Max8907bPmuSupply Supply, + NvBool Attach) +{ + NvU8 CtlAddr, CtlData, CntAddr, CntData, SeqSel; + + switch (Supply) + { + case Max8907bPmuSupply_LX_V1: // CPU + // No sequencer delay for CPU rail when it is attached + CntData = Attach ? 0x00 : MAX8907B_SEQCNT_DEFAULT_LX_V1; + SeqSel = Attach ? MAX8907B_SEQSEL_PWREN_LXX : + MAX8907B_SEQSEL_DEFAULT_LX_V1; + break; + + case Max8907bPmuSupply_LX_V2: // Core + // Change CPU sequencer delay when core is attached to assure + // order of Core/CPU rails control; clear CPU delay when core + // is detached + CntAddr = Max8907bSupplyInfoTable[ + Max8907bPmuSupply_LX_V1].SequencerCountRegAddr; + CntData = Attach ? MAX8907B_SEQCNT_PWREN_LX_V1 : 0x00; + if (!Max8907bI2cWrite8(hDevice, CntAddr, CntData)) + return NV_FALSE; + + CntData = Attach ? MAX8907B_SEQCNT_PWREN_LX_V2 : + MAX8907B_SEQCNT_DEFAULT_LX_V2; + SeqSel = Attach ? MAX8907B_SEQSEL_PWREN_LXX : + MAX8907B_SEQSEL_DEFAULT_LX_V2; + break; + + default: + NV_ASSERT(!"This supply must not be attached to PWREN"); + return NV_FALSE; + } + CtlAddr = Max8907bSupplyInfoTable[Supply].ControlRegAddr; + CntAddr = Max8907bSupplyInfoTable[Supply].SequencerCountRegAddr; + + // Read control refgister, and select target sequencer + if (!Max8907bI2cRead8(hDevice, CtlAddr, &CtlData)) + return NV_FALSE; + CtlData &= (~(MAX8907B_CTL_SEQ_MASK << MAX8907B_CTL_SEQ_SHIFT )); + CtlData |= ((SeqSel & MAX8907B_CTL_SEQ_MASK) << MAX8907B_CTL_SEQ_SHIFT ); + + // Attach: set count => set control + // Dettach: reset control => reset count + if (Attach) + { + if (!Max8907bI2cWrite8(hDevice, CntAddr, CntData)) + return NV_FALSE; + } + + if (!Max8907bI2cWrite8(hDevice, CtlAddr, CtlData)) + return NV_FALSE; + + if (!Attach) + { + if (!Max8907bI2cWrite8(hDevice, CntAddr, CntData)) + return NV_FALSE; + } + return NV_TRUE; +} + +static NvBool +Tca6416ConfigPort( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvBool Enable) +{ + const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + NvU32 PortNo; + NvU32 PinNo; + + // Get port number and pin number + PortNo = pSupplyInfo->OutputPort; + PinNo = pSupplyInfo->PmuGpio; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + if (Enable) + { + // Configure GPIO as output + if (!Tca6416ConfigPortPin(hDevice, PortNo, PinNo, GpioPinMode_Output)) + return NV_FALSE; + + // Set the output port + if (!Tca6416WritePortPin(hDevice, PortNo, PinNo, GpioPinState_High)) + return NV_FALSE; + } + else + // check if the supply can be turned off + { + // turn off the supply + NvOdmServicesPmuSetSocRailPowerState( + ((Max8907bPrivData*)hDevice->pPrivate)->hOdmPmuSevice, pSupplyInfo->supply, NV_FALSE); + + // Configure port pin as output + if (!Tca6416ConfigPortPin(hDevice, PortNo, PinNo, GpioPinMode_Output)) + return NV_FALSE; + + // Set the output port (for disable, data = 0) + if (!Tca6416WritePortPin(hDevice, PortNo, PinNo, GpioPinState_Low)) + return NV_FALSE; + } + return NV_TRUE; +} + + +#if defined(MAX8907B_USE_FAN5355_VOLTAGE_SCALING) +static NvBool +Fan5355ReadVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + NvU8 data = 0; + NvU32 milliVolts = 0; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + if (pSupplyInfo->OutputVoltageRegAddr == FAN5335_REG_INVALID) + return NV_FALSE; + + if (!Fan5355I2cRead8(hDevice, pSupplyInfo->OutputVoltageRegAddr, &data)) + return NV_FALSE; + + if (!data) //OFF + milliVolts = 0; + else + milliVolts = pSupplyInfo->GetVoltage(data); + + *pMilliVolts = milliVolts; + return NV_TRUE; +} +#endif + +static NvBool +Fan5355WriteVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts) +{ + const Max8907bPmuSupplyInfo *pSupplyInfo = NULL; + NvU8 data = 0; + + if ((vddRail == Max8907bPmuSupply_EXT_DCDC_3_USB1) || + (vddRail == Max8907bPmuSupply_EXT_DCDC_3_USB3)) + { + vddRail = Max8907bPmuSupply_EXT_DCDC_3; + } + + pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + // TO DO: Account for reference counting + if (MilliVolts == ODM_VOLTAGE_OFF) + { + // check if the supply can be turned off + { + // turn off the supply + NvOdmServicesPmuSetSocRailPowerState( + ((Max8907bPrivData*)hDevice->pPrivate)->hOdmPmuSevice, pSupplyInfo->supply, NV_FALSE); + + // Disable the output + if (!Tca6416ConfigPort(hDevice, vddRail, NV_FALSE)) + return NV_FALSE; + } + } + else + { + // Voltage on/change + NvOdmServicesPmuSetSocRailPowerState( + ((Max8907bPrivData*)(hDevice->pPrivate))->hOdmPmuSevice, pSupplyInfo->supply, NV_TRUE); + + // Set voltage level + data = pSupplyInfo->SetVoltage(MilliVolts); +#if defined(MAX8907B_USE_FAN5355_VOLTAGE_SCALING) + if (!Fan5355I2cWrite8(hDevice, pSupplyInfo->OutputVoltageRegAddr, data)) + return NV_FALSE; +#endif + + // Enable the output + if (!Tca6416ConfigPort(hDevice, vddRail, NV_TRUE)) + return NV_FALSE; + } + return NV_TRUE; +} + +static NvBool +Max8907bLxV1Ad5258ReadVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + const Max8907bPmuSupplyInfo* pSupplyInfo = + &Max8907bSupplyInfoTable[vddRail]; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + // Check if DC/DC has been turned Off (controlled by LxV1 main PMU output) + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[ + pSupplyInfo->supply] == 0) + { + if (!Max8907bReadVoltageReg( + hDevice, Max8907bPmuSupply_LX_V1, pMilliVolts)) + return NV_FALSE; + if (*pMilliVolts == ODM_VOLTAGE_OFF) + return NV_TRUE; + } + + // DC/DC is On - now get DPM-scaled voltage + return Ad5258I2cGetVoltage(hDevice, pMilliVolts); +} + +static NvBool +Max8907bLxV1Ad5258WriteVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + const Max8907bPmuSupplyInfo *pSupplyInfo = + &Max8907bSupplyInfoTable[vddRail]; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + if (MilliVolts == ODM_VOLTAGE_OFF) + { + // Check if the supply can be turned off, and if yes - turn off + // LxV1 main PMU output, which controls DC/DC + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[ + pSupplyInfo->supply] == 1) + { + if (!Max8907bWriteVoltageReg(hDevice, Max8907bPmuSupply_LX_V1, + MilliVolts, pSettleMicroSeconds)) + return NV_FALSE; + } + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[ + pSupplyInfo->supply] != 0) + { + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[ + pSupplyInfo->supply] --; + } + return NV_TRUE; + } + + // Set DPM voltage level (includes DPM and DCDC change level settle time) + if (!Ad5258I2cSetVoltage(hDevice, MilliVolts)) + return NV_FALSE; + + // Turn on control LxV1 supply on main PMU if necessary + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[ + pSupplyInfo->supply] == 0) + { + if (!Max8907bWriteVoltageReg(hDevice, Max8907bPmuSupply_LX_V1, + MAX8907B_REQUESTVOLTAGE_LX_V1, pSettleMicroSeconds)) + return NV_FALSE; + + // Add external DCDC turning On settling time + if (pSettleMicroSeconds) + *pSettleMicroSeconds += AD5258_TURN_ON_TIME_US; + else + NvOdmOsWaitUS(AD5258_TURN_ON_TIME_US); + } + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[ + pSupplyInfo->supply] ++; + + return NV_TRUE; +} + +NvBool +Max8907bSetup(NvOdmPmuDeviceHandle hDevice) +{ + NvOdmIoModule I2cModule = NvOdmIoModule_I2c; + NvU32 I2cInstance = 0; + NvU32 I2cAddress = 0; + NvU32 i = 0; + const NvOdmPeripheralConnectivity *pConnectivity = + NvOdmPeripheralGetGuid(PMUGUID); + + NV_ASSERT(hDevice); + + hMax8907bPmu = (Max8907bPrivData*) NvOdmOsAlloc(sizeof(Max8907bPrivData)); + if (hMax8907bPmu == NULL) + { + NVODMPMU_PRINTF(("Error Allocating Max8907bPrivData.\n")); + return NV_FALSE; + } + NvOdmOsMemset(hMax8907bPmu, 0, sizeof(Max8907bPrivData)); + hDevice->pPrivate = hMax8907bPmu; + + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable = + NvOdmOsAlloc(sizeof(NvU32) * Max8907bPmuSupply_Num); + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable == NULL) + { + NVODMPMU_PRINTF(("Error Allocating RefCntTable. \n")); + goto fail; + } + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages = + NvOdmOsAlloc(sizeof(NvU32) * Max8907bPmuSupply_Num); + if (((Max8907bPrivData*)hDevice->pPrivate)->pVoltages == NULL) + { + NVODMPMU_PRINTF(("Error Allocating shadow voltages table. \n")); + goto fail; + } + + // memset + for (i = 0; i < Max8907bPmuSupply_Num; i++) + { + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[i] = 0; + // Setting shadow to 0 would cause spare delay on the 1st scaling of + // always On rail; however the alternative reading of initial settings + // over I2C is even worse. + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages[i] = 0; + } + + if (pConnectivity != NULL) // PMU is in database + { + NvU32 i = 0; + + for (i = 0; i < pConnectivity->NumAddress; i ++) + { + if (pConnectivity->AddressList[i].Interface == NvOdmIoModule_I2c_Pmu) + { + I2cModule = NvOdmIoModule_I2c_Pmu; + I2cInstance = pConnectivity->AddressList[i].Instance; + I2cAddress = pConnectivity->AddressList[i].Address; + break; + } + } + + NV_ASSERT(I2cModule == NvOdmIoModule_I2c_Pmu); + NV_ASSERT(I2cAddress != 0); + + ((Max8907bPrivData*)hDevice->pPrivate)->hOdmI2C = NvOdmI2cOpen(I2cModule, I2cInstance); + if (!((Max8907bPrivData*)hDevice->pPrivate)->hOdmI2C) + { + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup: Error Opening I2C device. \n")); + NVODMPMU_PRINTF(("[NVODM PMU]Please check PMU device I2C settings. \n")); + return NV_FALSE; + } + ((Max8907bPrivData*)hDevice->pPrivate)->DeviceAddr = I2cAddress; + ((Max8907bPrivData*)hDevice->pPrivate)->hOdmPmuSevice = NvOdmServicesPmuOpen(); + } + else + { + // if PMU is not present in the database, then the platform is PMU-less. + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup: The system did not doscover PMU from the data base.\n")); + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup: If this is not intended, please check the peripheral database for PMU settings.\n")); + return NV_FALSE; + } + + // Configure OnOff options + if (!Max8907bOnOffConfigure(hDevice)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup: Max8907bOnOffConfigure() failed. \n")); + return NV_FALSE; + } + + // Configure PWREN, and attach CPU V1 rail to it. + // TODO: h/w events (power cycle, reset, battery low) auto-disables PWREN. + // Only soft reset (not supported) requires s/w to disable PWREN explicitly + if (!Max8907bPwrEnConfigure(hDevice, NV_TRUE)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup: Max8907bPwrEnConfigure() failed. \n")); + return NV_FALSE; + } + if (!Max8907bPwrEnAttach(hDevice, Max8907bPmuSupply_LX_V1, NV_TRUE)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup: Max8907bPwrEnAttach() failed. \n")); + return NV_FALSE; + } + + //Check battery presence + if (!Max8907bBatteryChargerMainBatt(hDevice,&((Max8907bPrivData*)hDevice->pPrivate)->battPresence)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup: Max8907bBatteryChargerMainBatt() failed. \n")); + return NV_FALSE; + } + + // Power up Whistler thermal monitor (it is reported "not connected" + // if board info ROMs cannot be read when the thermal rail is enabled). + // This has to be done as early as possible because of 100ms+ power up + // delay before interface level shifters are operational. + pConnectivity = + NvOdmPeripheralGetGuid(NV_ODM_GUID('a','d','t','7','4','6','1',' ')); + if (pConnectivity) + { + for (i = 0; i < pConnectivity->NumAddress; i++) + { + if (pConnectivity->AddressList[i].Interface == NvOdmIoModule_Vdd) + { + NvU32 vddRail = pConnectivity->AddressList[i].Address; + NvU32 mv = + Max8907bSupplyInfoTable[vddRail].cap.requestMilliVolts; + if(!Max8907bSetVoltage(hDevice, vddRail, mv, NULL)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Max8907bSetup:" + " Thermal rail setup failed. \n")); + } + } + } + } + + // The interrupt assumes not supported until Max8907bInterruptHandler() is called. + ((Max8907bPrivData*)hDevice->pPrivate)->pmuInterruptSupported = NV_FALSE; + + return NV_TRUE; + +fail: + Max8907bRelease(hDevice); + return NV_FALSE; +} + +void +Max8907bRelease(NvOdmPmuDeviceHandle hDevice) +{ + if (hDevice->pPrivate != NULL) + { + if (((Max8907bPrivData*)hDevice->pPrivate)->hOdmPmuSevice != NULL) + { + NvOdmServicesPmuClose(((Max8907bPrivData*)hDevice->pPrivate)->hOdmPmuSevice); + ((Max8907bPrivData*)hDevice->pPrivate)->hOdmPmuSevice = NULL; + } + + if (((Max8907bPrivData*)hDevice->pPrivate)->hOdmI2C != NULL) + { + NvOdmI2cClose(((Max8907bPrivData*)hDevice->pPrivate)->hOdmI2C); + ((Max8907bPrivData*)hDevice->pPrivate)->hOdmI2C = NULL; + } + + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable != NULL) + { + NvOdmOsFree(((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable); + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable = NULL; + } + + if (((Max8907bPrivData*)hDevice->pPrivate)->pVoltages != NULL) + { + NvOdmOsFree(((Max8907bPrivData*)hDevice->pPrivate)->pVoltages); + ((Max8907bPrivData*)hDevice->pPrivate)->pVoltages = NULL; + } + + + NvOdmOsFree(hDevice->pPrivate); + hDevice->pPrivate = NULL; + } +} + +NvBool +Max8907bGetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + NV_ASSERT(hDevice); + NV_ASSERT(pMilliVolts); + NV_ASSERT(vddRail < Max8907bPmuSupply_Num); + + // RTC is a special case, since it's "always on" + if (vddRail == Max8907bPmuSupply_VRTC) + { + // Fixed voltage + *pMilliVolts = MAX8907B_MAX_OUTPUT_VOLTAGE_RTC; + } + else if (vddRail == Max8907bPmuSupply_EXT_DCDC_1) + { + // Fixed voltage + *pMilliVolts = MAX8907B_REQUESTVOLTAGE_EXT_DCDC_1; + } + else if (vddRail == Max8907bPmuSupply_EXT_DCDC_3) + { +#if defined(MAX8907B_USE_FAN5355_VOLTAGE_SCALING) + if (!Fan5355ReadVoltageReg(hDevice, vddRail, pMilliVolts)) + return NV_FALSE; +#else + // Fixed voltage + *pMilliVolts = MAX8907B_REQUESTVOLTAGE_EXT_DCDC_3; +#endif + } + else if((vddRail == MIC2826PmuSupply_BUCK) || + (vddRail == MIC2826PmuSupply_LDO1) || + (vddRail == MIC2826PmuSupply_LDO2) || + (vddRail == MIC2826PmuSupply_LDO3)) + { + // Secondary PMU Case + if(! MIC2826ReadVoltageReg(hDevice, (vddRail), pMilliVolts)) + return NV_FALSE; + } + else if (vddRail == Max8907bLxV1_Ad5258_DPM_EXT_DCDC_7) + { + // External DCDC controlled by LX_V1, and scaled by DPM + if (!Max8907bLxV1Ad5258ReadVoltageReg(hDevice, vddRail, pMilliVolts)) + return NV_FALSE; + } + else + { + if (!Max8907bReadVoltageReg(hDevice, vddRail, pMilliVolts)) + return NV_FALSE; + } + + return NV_TRUE; +} + + +static NvBool +Tca6416UsbVbusControl( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts) +{ + const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + NvU32 PortNo; + NvU32 PinNo; + + // Get port number and pin number + PortNo = pSupplyInfo->OutputPort; + PinNo = pSupplyInfo->PmuGpio; + + // Configure port pin as output + if (!Tca6416ConfigPortPin(hDevice, PortNo, PinNo, GpioPinMode_Output)) + return NV_FALSE; + + if (MilliVolts == ODM_VOLTAGE_OFF) // to disable VBUS + { + // Set Low on pin + if (!Tca6416WritePortPin(hDevice, PortNo, PinNo, GpioPinState_Low)) + return NV_FALSE; + } + else // to Enable VBUS + { + // Set high on pin + if (!Tca6416WritePortPin(hDevice, PortNo, PinNo, GpioPinState_High)) + return NV_FALSE; + } + return NV_TRUE; +} + +NvBool +Max8907bSetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + NV_ASSERT(hDevice); + NV_ASSERT(vddRail < Max8907bPmuSupply_Num); + + if ( Max8907bSupplyInfoTable[vddRail].cap.OdmProtected == NV_TRUE) + { + NVODMPMU_PRINTF(("The voltage is protected and cannot be set.\n")); + return NV_TRUE; + } + + if ((MilliVolts == ODM_VOLTAGE_ENABLE_EXT_ONOFF) || + (MilliVolts == ODM_VOLTAGE_DISABLE_EXT_ONOFF)) + { + return Max8907bPwrEnAttach(hDevice, (Max8907bPmuSupply)vddRail, + (MilliVolts == ODM_VOLTAGE_ENABLE_EXT_ONOFF)); + } + + if ((MilliVolts == ODM_VOLTAGE_OFF) || + ((MilliVolts <= Max8907bSupplyInfoTable[vddRail].cap.MaxMilliVolts) && + (MilliVolts >= Max8907bSupplyInfoTable[vddRail].cap.MinMilliVolts))) + { + if ((vddRail == Max8907bPmuSupply_EXT_DCDC_1) || + (vddRail == Max8907bPmuSupply_EXT_DCDC_3) || + (vddRail == Max8907bPmuSupply_EXT_DCDC_3_USB1) || + (vddRail == Max8907bPmuSupply_EXT_DCDC_3_USB3)) + { + // Use External DC/DC switcher + if (!Fan5355WriteVoltageReg(hDevice, vddRail, MilliVolts)) + return NV_FALSE; + } + else if((vddRail == MIC2826PmuSupply_BUCK) || + (vddRail == MIC2826PmuSupply_LDO1) || + (vddRail == MIC2826PmuSupply_LDO2) || + (vddRail == MIC2826PmuSupply_LDO3)) + { + // Secondary PMU Case + if (!MIC2826WriteVoltageReg(hDevice, vddRail, MilliVolts, pSettleMicroSeconds)) + return NV_FALSE; + } + else if (vddRail == Max8907bLxV1_Ad5258_DPM_EXT_DCDC_7) + { + // External DCDC controlled by LX_V1, and scaled by DPM + if (!Max8907bLxV1Ad5258WriteVoltageReg( + hDevice, vddRail, MilliVolts, pSettleMicroSeconds)) + return NV_FALSE; + } + else + { + if (!Max8907bWriteVoltageReg(hDevice, vddRail, MilliVolts, pSettleMicroSeconds)) + return NV_FALSE; + } + } + else + { + NVODMPMU_PRINTF(("The requested voltage is not supported.\n")); + return NV_FALSE; + } + + // Check whether need to enable VBUS for any of the USB Instance + if ((vddRail == Max8907bPmuSupply_EXT_DCDC_3_USB1) || + (vddRail == Max8907bPmuSupply_EXT_DCDC_3_USB3)) + { + // Enable VBUS for USB1 or USB3 + if (!Tca6416UsbVbusControl(hDevice, vddRail, MilliVolts)) + return NV_FALSE; + } + return NV_TRUE; +} + +void +Max8907bGetCapabilities( + NvU32 vddRail, + NvOdmPmuVddRailCapabilities* pCapabilities) +{ + NV_ASSERT(pCapabilities); + NV_ASSERT(vddRail < Max8907bPmuSupply_Num); + + *pCapabilities = Max8907bSupplyInfoTable[vddRail].cap; +} + +NvBool +Max8907bGetAcLineStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuAcLineStatus *pStatus) +{ + NvBool acLineStatus = NV_FALSE; + + NV_ASSERT(hDevice); + NV_ASSERT(pStatus); + + // check if battery is present + if (((Max8907bPrivData*)hDevice->pPrivate)->battPresence == NV_FALSE) + { + *pStatus = NvOdmPmuAcLine_Online; + return NV_TRUE; + } + + if ( ((Max8907bPrivData*)hDevice->pPrivate)->pmuInterruptSupported == NV_TRUE ) + { + if ( ((Max8907bPrivData*)hDevice->pPrivate)->pmuStatus.mChgPresent == NV_TRUE ) + { + *pStatus = NvOdmPmuAcLine_Online; + acLineStatus = NV_TRUE; + } + else + { + *pStatus = NvOdmPmuAcLine_Offline; + acLineStatus = NV_FALSE; + } + } + else + { + // battery is present, now check if charger present + if (!Max8907bBatteryChargerOK(hDevice, &acLineStatus)) + { + NVODMPMU_PRINTF(("[NVODM PMU] Max8907bGetAcLineStatus: Error in checking main charger presence.\n")); + return NV_FALSE; + } + + if (acLineStatus == NV_TRUE) + *pStatus = NvOdmPmuAcLine_Online; + else + *pStatus = NvOdmPmuAcLine_Offline; + } + +#if ALWAYS_ONLINE + // Currently on Whistler battery is not used, and AC is connected to PMU + // battery input, causing false battery presence detection. Voyager battery + // management is don't care at the moment. Hence, force OnLine status. + *pStatus = NvOdmPmuAcLine_Online; +#endif + + return NV_TRUE; +} + +NvBool +Max8907bGetBatteryStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU8 *pStatus) +{ + NvU8 status = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pStatus); + NV_ASSERT(batteryInst <= NvOdmPmuBatteryInst_Num); + + if (batteryInst == NvOdmPmuBatteryInst_Main) + { + if ( ((Max8907bPrivData*)hDevice->pPrivate)->battPresence == NV_TRUE ) + { + NvOdmPmuAcLineStatus stat = NvOdmPmuAcLine_Offline; + NvU32 VBatSense = 0; + if (!Max8907bGetAcLineStatus(hDevice, &stat)) + return NV_FALSE; + + if (stat == NvOdmPmuAcLine_Online) + { + if ( ((Max8907bPrivData*)hDevice->pPrivate)->pmuInterruptSupported == NV_TRUE ) + { + if ( ((Max8907bPrivData*)hDevice->pPrivate)->pmuStatus.batFull == NV_FALSE ) + status = NVODM_BATTERY_STATUS_CHARGING; + } + else + { + NvBool batFull = NV_FALSE; + if (!Max8907bBatteryChargerMainBattFull(hDevice, &batFull)) + return NV_FALSE; + if (batFull == NV_FALSE) + status = NVODM_BATTERY_STATUS_CHARGING; + } + } + + // Get VBatSense + if (!Max8907bAdcVBatSenseRead(hDevice, &VBatSense)) + return NV_FALSE; + + // TO DO: Update status based on VBatSense + } + else + { + /* Battery is actually not present */ + status = NVODM_BATTERY_STATUS_NO_BATTERY; + } + *pStatus = status; + } + else + { + *pStatus = NVODM_BATTERY_STATUS_UNKNOWN; + } + + return NV_TRUE; +} + +NvBool +Max8907bGetBatteryData( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryData *pData) +{ + NvOdmPmuBatteryData batteryData; + + batteryData.batteryAverageCurrent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryAverageInterval = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryCurrent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryLifePercent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryLifeTime = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryMahConsumed = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryTemperature = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryVoltage = NVODM_BATTERY_DATA_UNKNOWN; + + NV_ASSERT(hDevice); + NV_ASSERT(pData); + NV_ASSERT(batteryInst <= NvOdmPmuBatteryInst_Num); + + if (batteryInst == NvOdmPmuBatteryInst_Main) + { + NvU32 VBatSense = 0; + NvU32 VBatTemp = 0; + + if (((Max8907bPrivData*)hDevice->pPrivate)->battPresence == NV_TRUE) + { + /* retrieve Battery voltage and temperature */ + + // Get VBatSense + if (!Max8907bAdcVBatSenseRead(hDevice, &VBatSense)) + { + NVODMPMU_PRINTF(("Error reading VBATSense. \n")); + return NV_FALSE; + } + + // Get VBatTemp + if (!Max8907bAdcVBatTempRead(hDevice, &VBatTemp)) + { + NVODMPMU_PRINTF(("Error reading VBATSense. \n")); + return NV_FALSE; + } + + batteryData.batteryVoltage = VBatSense; + batteryData.batteryTemperature = Max8907bBatteryTemperature(VBatSense, VBatTemp); + } + + *pData = batteryData; + } + else + { + *pData = batteryData; + } + + return NV_TRUE; +} + +void +Max8907bGetBatteryFullLifeTime( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU32 *pLifeTime) +{ + *pLifeTime = NVODM_BATTERY_DATA_UNKNOWN; +} + +void +Max8907bGetBatteryChemistry( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryChemistry *pChemistry) +{ + *pChemistry = NvOdmPmuBatteryChemistry_LION; +} + +NvBool +Max8907bSetChargingCurrent( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuChargingPath chargingPath, + NvU32 chargingCurrentLimitMa, + NvOdmUsbChargerType ChargerType) +{ + NvU8 data = 0; + NvU8 fchg = 0; + NV_ASSERT(hDevice); + + // If no battery is connected, then do nothing. + if (((Max8907bPrivData*)hDevice->pPrivate)->battPresence == NV_FALSE) + return NV_TRUE; + + // If requested current is more than supported maximum then limit to supported. + if ( chargingCurrentLimitMa > MAX_CHARGER_LIMIT_MA ) + chargingCurrentLimitMa = MAX_CHARGER_LIMIT_MA; + + // If dedicated charger is connected, request maximum current. + if (chargingPath == NvOdmPmuChargingPath_UsbBus) + { + switch (ChargerType) + { + case NvOdmUsbChargerType_SJ: + case NvOdmUsbChargerType_SK: + case NvOdmUsbChargerType_SE1: + case NvOdmUsbChargerType_SE0: + chargingCurrentLimitMa = MAX_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_UsbHost: + default: + break; + } + } + + // Read the current charger setup. + if ( !Max8907bI2cRead8(hDevice, MAX8907B_CHG_CNTL1, &data) ) + return NV_FALSE; + + // Set charging current to the value no larger than requested. + // If less than 85mA is requested, set to 85mA. + // If larger than 1000mA is requested, set to 1000mA. + if (chargingCurrentLimitMa >= 1000) + fchg = MAX8907B_CHG_CNTL1_FCHG_1000MA; + else if (chargingCurrentLimitMa >= 900) + fchg = MAX8907B_CHG_CNTL1_FCHG_900MA; + else if (chargingCurrentLimitMa >= 800) + fchg = MAX8907B_CHG_CNTL1_FCHG_800MA; + else if (chargingCurrentLimitMa >= 700) + fchg = MAX8907B_CHG_CNTL1_FCHG_700MA; + else if (chargingCurrentLimitMa >= 600) + fchg = MAX8907B_CHG_CNTL1_FCHG_600MA; + else if (chargingCurrentLimitMa >= 460) + fchg = MAX8907B_CHG_CNTL1_FCHG_460MA; + else if (chargingCurrentLimitMa >= 300) + fchg = MAX8907B_CHG_CNTL1_FCHG_300MA; + else + fchg = MAX8907B_CHG_CNTL1_FCHG_85MA; + + data &= ~(MAX8907B_CHG_CNTL1_FCHG_MASK << + MAX8907B_CHG_CNTL1_FCHG_SHIFT); + data |= fchg << MAX8907B_CHG_CNTL1_FCHG_SHIFT; + + // Turn off the charger path if the requested current limit is 0mA. + // Turn on the path otherwise. + if ( chargingCurrentLimitMa == 0 ) + { + // off + data |= (MAX8907B_CHG_CNTL1_NOT_CHGEN_MASK << + MAX8907B_CHG_CNTL1_NOT_CHGEN_SHIFT); + } + else + { + // on + data &= ~(MAX8907B_CHG_CNTL1_NOT_CHGEN_MASK << + MAX8907B_CHG_CNTL1_NOT_CHGEN_SHIFT); + } + + // Update the current charger setup. + if ( !Max8907bI2cWrite8(hDevice, MAX8907B_CHG_CNTL1, data) ) + return NV_FALSE; + + return NV_TRUE; +} + +void Max8907bInterruptHandler( NvOdmPmuDeviceHandle hDevice) +{ + // If the interrupt handle is called, the interrupt is supported. + ((Max8907bPrivData*)hDevice->pPrivate)->pmuInterruptSupported = NV_TRUE; + + Max8907bInterruptHandler_int(hDevice, &((Max8907bPrivData*)hDevice->pPrivate)->pmuStatus); +} + +/**************** Secondary PMU MIC2826 Programming */ +static NvBool +MIC2826ReadVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + NvU32 milliVolts = 0; + NvU32 index = 0; + NvU8 data = 0; + const Max8907bPmuSupplyInfo *pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + if(! MIC2826I2cRead8(hDevice, pSupplyInfo->ControlRegAddr, &data)) + return NV_FALSE; + + // convert Data to MilliVolts + if (!data) //OFF + milliVolts = 0; + else + { + // set voltage + if(vddRail == MIC2826PmuSupply_BUCK) + { + for(index=0;index<MIC2826_BUCK_Votage_Table_Size;index++) + { + if(data == MIC2826_BUCK_Votage_Table[index]) + break; + } + if(index < 0x10) + { + milliVolts = index * MIC2826_BUCK_VOLTAGE_STEP_25MV + MIC2826_BUCK_VOLTAGE_OFFSET ; + }else + { + milliVolts = 1200 + ((index - 0x10) * MIC2826_BUCK_VOLTAGE_STEP_50MV) ; + } + } + else if ( (vddRail == MIC2826PmuSupply_LDO1) || + (vddRail == MIC2826PmuSupply_LDO2) || + (vddRail == MIC2826PmuSupply_LDO3)) + { + for(index=0;index<MIC2826_LDO_Votage_Table_Size;index++) + { + if(data == MIC2826_BUCK_Votage_Table[index]) + break; + } + milliVolts = (index * pSupplyInfo->cap.StepMilliVolts) + MIC2826_LDO_VOLTAGE_OFFSET; + } + } + + *pMilliVolts = milliVolts; + + return NV_TRUE; +} + + +static NvBool +MIC2826WriteVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + NvU8 data = 0; + NvU32 index = 0; + NvU32 settleTime = 0; + const Max8907bPmuSupplyInfo* pSupplyInfo = &Max8907bSupplyInfoTable[vddRail]; + + NV_ASSERT(pSupplyInfo->supply == (Max8907bPmuSupply)vddRail); + + // Require to turn off the supply + if (MilliVolts == ODM_VOLTAGE_OFF) + { + // check if the supply can be turned off + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] == 1) + { + + // Read the current supply info + if(! MIC2826I2cRead8(hDevice, MIC2826_REG_ADDR_ENABLE, &data)) + return NV_FALSE; + + // turn off the supply of particular rail + if(vddRail == MIC2826PmuSupply_BUCK) + data &= MIC2826_REG_DISABLE_BK; + else if(vddRail == MIC2826PmuSupply_LDO1) + data &= MIC2826_REG_DISABLE_LDO1; + else if(vddRail == MIC2826PmuSupply_LDO2) + data &= MIC2826_REG_DISABLE_LDO2; + else if(vddRail == MIC2826PmuSupply_LDO3) + data &= MIC2826_REG_DISABLE_LDO3; + + if (!MIC2826I2cWrite8(hDevice, MIC2826_REG_ADDR_ENABLE, data)) + return NV_FALSE; + } + + //TODO: check if the supply input can be turned off + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] != 0) + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] --; + + if (pSettleMicroSeconds != NULL) + *pSettleMicroSeconds = settleTime; + else + NvOdmOsWaitUS(settleTime); + + return NV_TRUE; + } + + // turn on supply + if (((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] == 0) + { + { + // Read the current supply info + if(! MIC2826I2cRead8(hDevice, MIC2826_REG_ADDR_ENABLE, &data)) + return NV_FALSE; + + // turn on the supply of particular rail + if(vddRail == MIC2826PmuSupply_BUCK) + data |= MIC2826_REG_ENABLE_BK; + else if(vddRail == MIC2826PmuSupply_LDO1) + data |= MIC2826_REG_ENABLE_LDO1; + else if(vddRail == MIC2826PmuSupply_LDO2) + data |= MIC2826_REG_ENABLE_LDO2; + else if(vddRail == MIC2826PmuSupply_LDO3) + data |= MIC2826_REG_ENABLE_LDO3; + + if (!MIC2826I2cWrite8(hDevice, MIC2826_REG_ADDR_ENABLE, data)) + return NV_FALSE; + } + } + + // set voltage + if(vddRail == MIC2826PmuSupply_BUCK) + { + if(MilliVolts < 1200) + { + index = (MilliVolts - MIC2826_BUCK_VOLTAGE_OFFSET) / MIC2826_BUCK_VOLTAGE_STEP_25MV ; + }else + { + index = 0x10 + ((MilliVolts - 1200) / MIC2826_BUCK_VOLTAGE_STEP_50MV) ; + } + data = MIC2826_BUCK_Votage_Table[index]; + } + else if ( (vddRail == MIC2826PmuSupply_LDO1) || + (vddRail == MIC2826PmuSupply_LDO2) || + (vddRail == MIC2826PmuSupply_LDO3)) + { + index = (MilliVolts - MIC2826_LDO_VOLTAGE_OFFSET) / pSupplyInfo->cap.StepMilliVolts; + data = MIC2826_LDO_Votage_Table[index]; + } + + // Program the Rail Voltage + if(! MIC2826I2cRead8(hDevice, pSupplyInfo->ControlRegAddr, &data)) + return NV_FALSE; + + ((Max8907bPrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] ++; + + // TODO: turn on supply input if necessary + if (pSettleMicroSeconds != NULL) + *pSettleMicroSeconds = settleTime; + else + NvOdmOsWaitUS(settleTime); + + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h new file mode 100644 index 000000000000..ce66a64c9716 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_PMU_MAX8907B_H +#define INCLUDED_PMU_MAX8907B_H + +#include "nvodm_pmu.h" +#include"pmu_hal.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if (NV_DEBUG) +#define NVODMPMU_PRINTF(x) NvOdmOsDebugPrintf x +#else +#define NVODMPMU_PRINTF(x) +#endif + +typedef struct Max8907bStatusRec +{ + /* Low Battery voltage detected by BVM */ + NvBool lowBatt; + + /* PMU high temperature */ + NvBool highTemp; + + /* Main charger Present */ + NvBool mChgPresent; + + /* battery Full */ + NvBool batFull; + +} Max8907bStatus; + +typedef struct +{ + /* The handle to the I2C */ + NvOdmServicesI2cHandle hOdmI2C; + + /* The odm pmu service handle */ + NvOdmServicesPmuHandle hOdmPmuSevice; + + /* the PMU I2C device Address */ + NvU32 DeviceAddr; + + /* the PMU status */ + Max8907bStatus pmuStatus; + + /* battery presence */ + NvBool battPresence; + + /* PMU interrupt support enabled */ + NvBool pmuInterruptSupported; + + /* The ref cnt table of the power supplies */ + NvU32 *supplyRefCntTable; + + /* The pointer to supply voltages shadow */ + NvU32 *pVoltages; + +} Max8907bPrivData; + +NvBool +Max8907bSetup(NvOdmPmuDeviceHandle hDevice); + +void +Max8907bRelease(NvOdmPmuDeviceHandle hDevice); + +NvBool +Max8907bGetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts); + +NvBool +Max8907bSetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds); + +void +Max8907bGetCapabilities( + NvU32 vddRail, + NvOdmPmuVddRailCapabilities* pCapabilities); + +NvBool +Max8907bGetAcLineStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuAcLineStatus *pStatus); + +NvBool +Max8907bGetBatteryStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU8 *pStatus); + +NvBool +Max8907bGetBatteryData( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryData *pData); + +void +Max8907bGetBatteryFullLifeTime( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU32 *pLifeTime); + +void +Max8907bGetBatteryChemistry( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryChemistry *pChemistry); + +NvBool +Max8907bSetChargingCurrent( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuChargingPath chargingPath, + NvU32 chargingCurrentLimitMa, + NvOdmUsbChargerType ChargerType); + +void Max8907bInterruptHandler( NvOdmPmuDeviceHandle hDevice); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_PMU_MAX8907B_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_adc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_adc.c new file mode 100644 index 000000000000..14d2c0d87a1a --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_adc.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "max8907b.h" +#include "max8907b_adc.h" +#include "max8907b_i2c.h" +#include "max8907b_reg.h" + +NvBool +Max8907bAdcVBatSenseRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt) +{ +#if 0 + NvU32 timeout = 0; + NvU8 dataS1 = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(volt); + + // Configure ADC (conversion cycle, resolution, etc...) + + // Start conversion + + // Wait for conversion + + // Make sure conversion is complete (or timeout or error) + + // Get result + *volt = << compute >>; + +#endif + *volt = 0; + return NV_TRUE; +} + +NvBool +Max8907bAdcVBatTempRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt) +{ +#if 0 + NvU32 timeout = 0; + NvU8 dataS1 = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(volt); + + // Setup ADC (resolution, etc..) + + // Start conversion + + // Wait for conversion + + // Make sure conversion is complete (or timeout or error) + + // Get result + *volt = << compute >>; + +#endif + *volt = 0; + return NV_TRUE; +} + +NvU32 +Max8907bBatteryTemperature( + NvU32 VBatSense, + NvU32 VBatTemp) +{ + return 0; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_adc.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_adc.h new file mode 100644 index 000000000000..5c3fb34fbf22 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_adc.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_MAX8907B_ADC_HEADER +#define INCLUDED_MAX8907B_ADC_HEADER + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* read voltage from ... */ +NvBool +Max8907bAdcVBatSenseRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt); + +/* read bat temperature voltage from ADC */ +NvBool +Max8907bAdcVBatTempRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt); + +/* Calculate the battery temperature */ +NvU32 +Max8907bBatteryTemperature( + NvU32 VBatSense, + NvU32 VBatTemp); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_MAX8907B_ADC_HEADER diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_batterycharger.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_batterycharger.c new file mode 100644 index 000000000000..00096508b05a --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_batterycharger.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "max8907b.h" +#include "max8907b_batterycharger.h" +#include "max8907b_reg.h" +#include "max8907b_i2c.h" + +NvBool +Max8907bBatteryChargerMainBatt( + NvOdmPmuDeviceHandle hDevice, + NvBool *status) +{ + NvU8 data = 0; + + if(!Max8907bI2cRead8(hDevice, MAX8907B_CHG_STAT, &data)) + return NV_FALSE; + + data = (data >> MAX8907B_CHG_STAT_MBDET_SHIFT) & MAX8907B_CHG_STAT_MBDET_MASK; + *status = (data == 0 ? NV_TRUE : NV_FALSE ); // MBDET low (0) = present + return NV_TRUE; +} + +NvBool +Max8907bBatteryChargerOK( + NvOdmPmuDeviceHandle hDevice, + NvBool *status) +{ + NvU8 data = 0; + + if(!Max8907bI2cRead8(hDevice, MAX8907B_CHG_STAT, &data)) + return NV_FALSE; + + data = (data >> MAX8907B_CHG_STAT_VCHG_OK_SHIFT) & MAX8907B_CHG_STAT_VCHG_OK_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + +NvBool +Max8907bBatteryChargerEnabled( + NvOdmPmuDeviceHandle hDevice, + NvBool *status) +{ + NvU8 data = 0; + + if(!Max8907bI2cRead8(hDevice, MAX8907B_CHG_STAT, &data)) + return NV_FALSE; + + data = (data >> MAX8907B_CHG_STAT_CHG_EN_STAT_SHIFT) & MAX8907B_CHG_STAT_CHG_EN_STAT_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + +NvBool +Max8907bBatteryChargerMainBattFull( + NvOdmPmuDeviceHandle hDevice, + NvBool *status) +{ + NvU8 data = 0; + + if(!Max8907bI2cRead8(hDevice, MAX8907B_CHG_STAT, &data)) + return NV_FALSE; + + data = (data >> MAX8907B_CHG_STAT_MBATTLOW_SHIFT) & MAX8907B_CHG_STAT_MBATTLOW_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_batterycharger.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_batterycharger.h new file mode 100644 index 000000000000..ab7d1212a44f --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_batterycharger.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_MAX8907B_BATTERYCHARGER_HEADER +#define INCLUDED_MAX8907B_BATTERYCHARGER_HEADER + +/* the battery charger functions */ +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* check main battery presence */ +NvBool +Max8907bBatteryChargerMainBatt( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check charger input voltage */ +NvBool +Max8907bBatteryChargerOK( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check charger enable status */ +NvBool +Max8907bBatteryChargerEnabled( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check main battery voltage status */ +NvBool +Max8907bBatteryChargerMainBattFull( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_MAX8907B_BATTERYCHARGER_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c new file mode 100644 index 000000000000..0f7a09446876 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "max8907b.h" +#include "max8907b_i2c.h" +#include "max8907b_reg.h" + +#define MAX8907B_I2C_SPEED_KHZ 400 +#define MAX8907B_I2C_RETRY_CNT 2 + +// Maximum i2c transaction count +#define MAX_TRANSACTION_COUNT 5 + +NvBool Max8907bI2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data) +{ + NvU32 i; + NvU8 WriteBuffer[2]; + NvOdmI2cTransactionInfo TransactionInfo; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + + for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++) + { + WriteBuffer[0] = Addr & 0xFF; // PMU offset + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = hPmu->DeviceAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + + if (status == NvOdmI2cStatus_Success) + return NV_TRUE; + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + +NvBool Max8907bI2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data) +{ + NvU32 i; + NvU8 ReadBuffer = 0; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++) + { + NvU32 TransactionCount = 0; + // Write the PMU offset + ReadBuffer = Addr & 0xFF; + + TransactionInfo[TransactionCount].Address = hPmu->DeviceAddr; + TransactionInfo[TransactionCount].Buf = &ReadBuffer; + TransactionInfo[TransactionCount].Flags = + NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START; + TransactionInfo[TransactionCount++].NumBytes = 1; + + TransactionInfo[TransactionCount].Address = (hPmu->DeviceAddr | 0x1); + TransactionInfo[TransactionCount].Buf = &ReadBuffer; + TransactionInfo[TransactionCount].Flags = 0; + TransactionInfo[TransactionCount++].NumBytes = 1; + + // Read data from PMU at the specified offset + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], + TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + + if (status == NvOdmI2cStatus_Success) + { + *Data = ReadBuffer; + return NV_TRUE; + } + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + +NvBool Max8907bI2cWrite32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 Data) +{ + NvU32 i; + NvU8 WriteBuffer[5]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo; + + for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++) + { + WriteBuffer[0] = (NvU8)(Addr & 0xFF); + WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF); + WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF); + WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF); + WriteBuffer[4] = (NvU8)(Data & 0xFF); + + TransactionInfo.Address = hPmu->DeviceAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 5; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + + if (status == NvOdmI2cStatus_Success) + return NV_TRUE; + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + +NvBool Max8907bI2cRead32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 *Data) +{ + NvU32 i; + NvU8 ReadBuffer[5]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++) + { + NvU32 TransactionCount = 0; + ReadBuffer[0] = Addr & 0xFF; + + TransactionInfo[TransactionCount].Address = hPmu->DeviceAddr; + TransactionInfo[TransactionCount].Buf = &ReadBuffer[0]; + TransactionInfo[TransactionCount].Flags = + NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START; + TransactionInfo[TransactionCount++].NumBytes = 1; + + TransactionInfo[TransactionCount].Address = (hPmu->DeviceAddr | 0x1); + TransactionInfo[TransactionCount].Buf = &ReadBuffer[0]; + TransactionInfo[TransactionCount].Flags = 0; + TransactionInfo[TransactionCount++].NumBytes = 4; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], + TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + + if (status == NvOdmI2cStatus_Success) + { + *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) | + (ReadBuffer[2] << 8) | ReadBuffer[3]; + + return NV_TRUE; + } + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + +NvBool Max8907bRtcI2cWriteTime( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 Data) +{ + NvU32 i; + NvU8 WriteBuffer[5]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo; + + NVODMPMU_PRINTF(("\n RTC I2C write: Addr=0x%x, Data=0x%x ", Addr, Data)); + for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++) + { + WriteBuffer[0] = (NvU8)(Addr & 0xFF); + WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF); + WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF); + WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF); + WriteBuffer[4] = (NvU8)(Data & 0xFF); + + TransactionInfo.Address = MAX8907B_RTC_SLAVE_ADDR; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 5; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + + if (status == NvOdmI2cStatus_Success) + return NV_TRUE; + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("Max8907bRtcI2cWrite32 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + +NvBool Max8907bRtcI2cReadTime( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 *Data) +{ + NvU32 i; + NvU8 ReadBuffer[4]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[MAX_TRANSACTION_COUNT]; + + NVODMPMU_PRINTF(("\n RTC I2C read: Addr=0x%x ", Addr)); + for (i = 0; i < MAX8907B_I2C_RETRY_CNT; i++) + { + NvU32 TransactionCount = 0; + ReadBuffer[0] = Addr & 0xFF; + + TransactionInfo[TransactionCount].Address = MAX8907B_RTC_SLAVE_ADDR; + TransactionInfo[TransactionCount].Buf = &ReadBuffer[0]; + TransactionInfo[TransactionCount].Flags = + NVODM_I2C_IS_WRITE | NVODM_I2C_USE_REPEATED_START; + TransactionInfo[TransactionCount++].NumBytes = 1; + + // Seconds / day + if (TransactionCount >= MAX_TRANSACTION_COUNT) + return NV_FALSE; + TransactionInfo[TransactionCount].Address = + (MAX8907B_RTC_SLAVE_ADDR | 0x1); + TransactionInfo[TransactionCount].Buf = &ReadBuffer[0]; + TransactionInfo[TransactionCount].Flags = 0; + TransactionInfo[TransactionCount++].NumBytes = 1; + + // Minutes / month + if (TransactionCount >= MAX_TRANSACTION_COUNT) + return NV_FALSE; + TransactionInfo[TransactionCount].Address = + (MAX8907B_RTC_SLAVE_ADDR | 0x1); + TransactionInfo[TransactionCount].Buf = &ReadBuffer[1]; + TransactionInfo[TransactionCount].Flags = 0; + TransactionInfo[TransactionCount++].NumBytes = 1; + + // Hours / YY1 + if (TransactionCount >= MAX_TRANSACTION_COUNT) + return NV_FALSE; + TransactionInfo[TransactionCount].Address = + (MAX8907B_RTC_SLAVE_ADDR | 0x1); + TransactionInfo[TransactionCount].Buf = &ReadBuffer[2]; + TransactionInfo[TransactionCount].Flags = 0; + TransactionInfo[TransactionCount++].NumBytes = 1; + + // Weekday / YY2 + if (TransactionCount >= MAX_TRANSACTION_COUNT) + return NV_FALSE; + TransactionInfo[TransactionCount].Address = + (MAX8907B_RTC_SLAVE_ADDR | 0x1); + TransactionInfo[TransactionCount].Buf = &ReadBuffer[3]; + TransactionInfo[TransactionCount].Flags = 0; + TransactionInfo[TransactionCount++].NumBytes = 1; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], + TransactionCount, MAX8907B_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + { + *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) | + (ReadBuffer[2] << 8) | ReadBuffer[3]; + + return NV_TRUE; + } + } + + // Transaction Error + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("Max8907bRtcI2cRead32 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.h new file mode 100644 index 000000000000..c4b5c634c4fa --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_i2c.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_PMU_MAX8907B_I2C_H +#define INCLUDED_NVODM_PMU_MAX8907B_I2C_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// Constant definition +// #define PMU_MAX8907B_DEVADDR TBD +#define PMU_MAX8907B_I2C_SPEED_KHZ 400 + +// Function declaration +NvBool Max8907bI2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data); + +NvBool Max8907bI2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data); + +NvBool Max8907bI2cWrite32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 Data); + +NvBool Max8907bI2cRead32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 *Data); + +NvBool Max8907bRtcI2cWriteTime( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 Data); + +NvBool Max8907bRtcI2cReadTime( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 *Data); + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_NVODM_PMU_MAX8907B_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_interrupt.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_interrupt.c new file mode 100644 index 000000000000..38110f83c5a0 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_interrupt.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "max8907b.h" +#include "max8907b_interrupt.h" +#include "max8907b_i2c.h" +#include "max8907b_reg.h" +#include "max8907b_batterycharger.h" +#include "nvodm_services.h" + +NvBool +Max8907bSetupInterrupt( + NvOdmPmuDeviceHandle hDevice, + Max8907bStatus *pmuStatus) +{ + NvBool status = NV_FALSE; + NvU8 data = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pmuStatus); + + /* Init Pmu Status */ + pmuStatus->lowBatt = NV_FALSE; + pmuStatus->highTemp = NV_FALSE; + + if (!Max8907bBatteryChargerMainBatt(hDevice, &status)) + return NV_FALSE; + pmuStatus->mChgPresent = status; + + /* Set up Interrupt Mask */ + + // CHG_IRQ1 + data = 0; + if (!Max8907bI2cWrite8(hDevice, MAX8907B_CHG_IRQ1, data)) + return NV_FALSE; + + // CHG_IRQ2 + data = MAX8907B_CHG_IRQ2_CHG_DONE_MASK | + MAX8907B_CHG_IRQ2_MBATTLOW_F_SHIFT | + MAX8907B_CHG_IRQ2_THM_OK_F_MASK | + MAX8907B_CHG_IRQ2_THM_OK_R_MASK ; + if (!Max8907bI2cWrite8(hDevice, MAX8907B_CHG_IRQ2, data)) + return NV_FALSE; + + // ON_OFF_IRQ1 + data = 0; + if (!Max8907bI2cWrite8(hDevice, MAX8907B_ON_OFF_IRQ1, data)) + return NV_FALSE; + + // ON_OFF_IRQ2 + data = 0; + if (!Max8907bI2cWrite8(hDevice, MAX8907B_ON_OFF_IRQ2, data)) + return NV_FALSE; + + // RTC_IRQ + data = 0; + if (!Max8907bI2cWrite8(hDevice, MAX8907B_RTC_IRQ, data)) + return NV_FALSE; + + return NV_TRUE; +} + +void +Max8907bInterruptHandler_int( + NvOdmPmuDeviceHandle hDevice, + Max8907bStatus *pmuStatus) +{ + NvU8 data = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pmuStatus); + + /* Check which interrupt... */ + + // CHG_IRQ1 + if (!Max8907bI2cRead8(hDevice, MAX8907B_CHG_IRQ1, &data)) + { + return; + } + + if (data) + { + // VBUS connect interrupt + if (data & + (MAX8907B_CHG_IRQ1_VCHG_R_MASK << MAX8907B_CHG_IRQ1_VCHG_R_SHIFT)) + { + NvOdmEnableOtgCircuitry(NV_TRUE); + } + // VBUS dis-connect interrupt + else if (data & + (MAX8907B_CHG_IRQ1_VCHG_F_MASK << MAX8907B_CHG_IRQ1_VCHG_F_SHIFT)) + { + NvOdmEnableOtgCircuitry(NV_FALSE); + } + } + + // CHG_IRQ2 + if (!Max8907bI2cRead8(hDevice, MAX8907B_CHG_IRQ2, &data)) + { + return; + } + if (data) + { + if (data & MAX8907B_CHG_IRQ2_CHG_DONE_MASK) + { + pmuStatus->mChgPresent = NV_TRUE; + pmuStatus->batFull = NV_TRUE; + } + if (data & MAX8907B_CHG_IRQ2_MBATTLOW_F_SHIFT) + { + pmuStatus->batFull = NV_FALSE; + } + if (data & MAX8907B_CHG_IRQ2_THM_OK_F_MASK) + { + pmuStatus->highTemp = NV_TRUE; + } + if (data & MAX8907B_CHG_IRQ2_THM_OK_R_MASK) + { + pmuStatus->highTemp = NV_FALSE; + } + } + + // ON_OFF_IRQ1 + if (!Max8907bI2cRead8(hDevice, MAX8907B_ON_OFF_IRQ1, &data)) + { + return; + } + + // ON_OFF_IRQ2 + if (!Max8907bI2cRead8(hDevice, MAX8907B_ON_OFF_IRQ2, &data)) + { + return; + } + + // RTC_IRQ + if (!Max8907bI2cRead8(hDevice, MAX8907B_RTC_IRQ, &data)) + { + return; + } + + return; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_interrupt.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_interrupt.h new file mode 100644 index 000000000000..a00cabc17039 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_interrupt.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_MAX8907B_INTERRUPT_HEADER +#define INCLUDED_MAX8907B_INTERRUPT_HEADER + +#include "max8907b.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +NvBool +Max8907bSetupInterrupt( + NvOdmPmuDeviceHandle hDevice, + Max8907bStatus *pmuStatus); + +void +Max8907bInterruptHandler_int( + NvOdmPmuDeviceHandle hDevice, + Max8907bStatus *pmuStatus); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_MAX8907B_INTERRUPT_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_reg.h new file mode 100644 index 000000000000..513e2f6a1812 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_reg.h @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2009-2010 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_MAX8907B_REG_HEADER +#define INCLUDED_MAX8907B_REG_HEADER + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// -- MAX8907B Addresses (See Table 71 of data sheet) -- + +/* MAX8907B Slave Addresses */ + +#define MAX8907B_PMU_SLAVE_ADDR 0x78 +#define MAX8907B_RTC_SLAVE_ADDR 0xD0 +#define MAX8907B_ADC_SLAVE_ADDR 0x8E + +/* MAX8907B Register Addresses */ + +// Main-Battery Charger +#define MAX8907B_CHG_CNTL1 0x7C +#define MAX8907B_CHG_CNTL2 0x7D +#define MAX8907B_CHG_IRQ1 0x7E +#define MAX8907B_CHG_IRQ2 0x7F +#define MAX8907B_CHG_IRQ1_MASK 0x80 +#define MAX8907B_CHG_IRQ2_MASK 0x81 +#define MAX8907B_CHG_STAT 0x82 + +// Backup-Battery Charger +#define MAX8907B_BBATT_CNFG 0x78 +#define MAX8907B_SDBYSEQCNT 0x13 + +// V1 Step Down Regulator +#define MAX8907B_SDCTL1 0x04 +#define MAX8907B_SDSEQCNT1 0x05 +#define MAX8907B_SDV1 0x06 + +// V2 Step Down Regulator +#define MAX8907B_SDCTL2 0x07 +#define MAX8907B_SDSEQCNT2 0x08 +#define MAX8907B_SDV2 0x09 + +// V3 Step Down Regulator +#define MAX8907B_SDCTL3 0x0A +#define MAX8907B_SDSEQCNT3 0x0B +#define MAX8907B_SDV3 0x0C + +// LDO1 Regulator +#define MAX8907B_LDOCTL1 0x18 +#define MAX8907B_LDOSEQCNT1 0x19 +#define MAX8907B_LDO1VOUT 0x1A + +// LDO2 Regulator +#define MAX8907B_LDOCTL2 0x1C +#define MAX8907B_LDOSEQCNT2 0x1D +#define MAX8907B_LDO2VOUT 0x1E + +// LDO3 Regulator +#define MAX8907B_LDOCTL3 0x20 +#define MAX8907B_LDOSEQCNT3 0x21 +#define MAX8907B_LDO3VOUT 0x22 + +// LDO4 Regulator +#define MAX8907B_LDOCTL4 0x24 +#define MAX8907B_LDOSEQCNT4 0x25 +#define MAX8907B_LDO4VOUT 0x26 + +// LDO5 Regulator +#define MAX8907B_LDOCTL5 0x28 +#define MAX8907B_LDOSEQCNT5 0x29 +#define MAX8907B_LDO5VOUT 0x2A + +// LDO6 Regulator +#define MAX8907B_LDOCTL6 0x2C +#define MAX8907B_LDOSEQCNT6 0x2D +#define MAX8907B_LDO6VOUT 0x2E + +// LDO7 Regulator +#define MAX8907B_LDOCTL7 0x30 +#define MAX8907B_LDOSEQCNT7 0x31 +#define MAX8907B_LDO7VOUT 0x32 + +// LDO8 Regulator +#define MAX8907B_LDOCTL8 0x34 +#define MAX8907B_LDOSEQCNT8 0X35 +#define MAX8907B_LDO8VOUT 0x36 + +// LDO9 Regulator +#define MAX8907B_LDOCTL9 0x38 +#define MAX8907B_LDOSEQCNT9 0x39 +#define MAX8907B_LDO9VOUT 0x3A + +// LDO10 Regulator +#define MAX8907B_LDOCTL10 0x3C +#define MAX8907B_LDOSEQCNT10 0x3D +#define MAX8907B_LDO10VOUT 0x3E + +// LDO11 Regulator +#define MAX8907B_LDOCTL11 0x40 +#define MAX8907B_LDOSEQCNT11 0x41 +#define MAX8907B_LDO11VOUT 0x42 + +// LDO12 Regulator +#define MAX8907B_LDOCTL12 0x44 +#define MAX8907B_LDOSEQCNT12 0x45 +#define MAX8907B_LDO12VOUT 0x46 + +// LDO13 Regulator +#define MAX8907B_LDOCTL13 0x48 +#define MAX8907B_LDOSEQCNT13 0x49 +#define MAX8907B_LDO13VOUT 0x4A + +// LDO14 Regulator +#define MAX8907B_LDOCTL14 0x4C +#define MAX8907B_LDOSEQCNT14 0x4D +#define MAX8907B_LDO14VOUT 0x4E + +// LDO15 Regulator +#define MAX8907B_LDOCTL15 0x50 +#define MAX8907B_LDOSEQCNT15 0x51 +#define MAX8907B_LDO15VOUT 0x52 + +// LDO16 Regulator +#define MAX8907B_LDOCTL16 0x10 +#define MAX8907B_LDOSEQCNT16 0x11 +#define MAX8907B_LDO16VOUT 0x12 + +// LDO17 Regulator +#define MAX8907B_LDOCTL17 0x14 +#define MAX8907B_LDOSEQCNT17 0x15 +#define MAX8907B_LDO17VOUT 0x16 + +// LDO18 Regulator +#define MAX8907B_LDOCTL18 0x72 +#define MAX8907B_LDOSEQCNT18 0x73 +#define MAX8907B_LDO18VOUT 0x74 + +// LDO19 Regulator +#define MAX8907B_LDOCTL19 0x5C +#define MAX8907B_LDOSEQCNT19 0x5D +#define MAX8907B_LDO19VOUT 0x5E + +// LDO20 Regulator +#define MAX8907B_LDOCTL20 0x9C +#define MAX8907B_LDOSEQCNT20 0x9D +#define MAX8907B_LDO20VOUT 0x9E + +// OUT5V Regulator +#define MAX8907B_OUT5VEN 0x54 +#define MAX8907B_OUT5VSEQ 0x55 + +// OUT3.3V Regulator +#define MAX8907B_OUT_3_3VEN 0x58 +#define MAX8907B_OUT_3_3VSEQ 0x59 + +// Main Bias Register +#define MAX8907B_LBCNFG 0x60 + +// ON/OFF Controller +#define MAX8907B_SYSENSEL 0x00 +#define MAX8907B_ON_OFF_IRQ1 0x01 +#define MAX8907B_ON_OFF_IRQ1_MASK 0x02 +#define MAX8907B_ON_OFF_STAT 0x03 +#define MAX8907B_ON_OFF_IRQ2 0x0D +#define MAX8907B_ON_OFF_IRQ2_MASK 0x0E +#define MAX8907B_RESET_CNFG 0x0F + +// Flexible Power Sequencer +#define MAX8907B_SEQ1CNFG 0x64 +#define MAX8907B_SEQ2CNFG 0x65 +#define MAX8907B_SEQ3CNFG 0x66 +#define MAX8907B_SEQ4CNFG 0x67 +#define MAX8907B_SEQ5CNFG 0x68 +#define MAX8907B_SEQ6CNFG 0x69 +#define MAX8907B_SEQ7CNFG 0x6A + +// RTC Registers +#define MAX8907B_RTC_SEC 0x00 +#define MAX8907B_RTC_MIN 0x01 +#define MAX8907B_RTC_HOURS 0x02 +#define MAX8907B_RTC_WEEKDAY 0x03 +#define MAX8907B_RTC_DATE 0x04 +#define MAX8907B_RTC_MONTH 0x05 +#define MAX8907B_RTC_YEAR1 0x06 +#define MAX8907B_RTC_YEAR2 0x07 +#define MAX8907B_ALARM0_SEC 0x08 +#define MAX8907B_ALARM0_MIN 0x09 +#define MAX8907B_ALARM0_HOURS 0x0A +#define MAX8907B_ALARM0_WEEKDAY 0x0B +#define MAX8907B_ALARM0_DATE 0x0C +#define MAX8907B_ALARM0_MONTH 0x0D +#define MAX8907B_ALARM0_YEAR1 0x0E +#define MAX8907B_ALARM0_YEAR2 0x0F +#define MAX8907B_ALARM1_SEC 0x10 +#define MAX8907B_ALARM1_MIN 0x11 +#define MAX8907B_ALARM1_HOURS 0x12 +#define MAX8907B_ALARM1_WEEKDAY 0x13 +#define MAX8907B_ALARM1_DATE 0x14 +#define MAX8907B_ALARM1_MONTH 0x15 +#define MAX8907B_ALARM1_YEAR1 0x16 +#define MAX8907B_ALARM1_YEAR2 0x17 +#define MAX8907B_ALARM0_CNTL 0x18 +#define MAX8907B_ALARM1_CNTL 0x19 +#define MAX8907B_RTC_STATUS 0x1A +#define MAX8907B_RTC_CNTL 0x1B +#define MAX8907B_RTC_IRQ 0x1C +#define MAX8907B_RTC_IRQ_MASK 0x1D +#define MAX8907B_MPL_CNTL 0x1E + +// ADC and Touch Screen Controller +#define MAX8907B_TSC_STA_INT 0x00 +#define MAX8907B_TSC_INT_MASK 0x01 +#define MAX8907B_TSC_CNFG1 0x02 +#define MAX8907B_TSC_CNFG2 0x03 +#define MAX8907B_TSC_CNFG3 0x04 +#define MAX8907B_ADC_RES_CNFG1 0x06 +#define MAX8907B_ADC_AVG_CNFG1 0x07 +#define MAX8907B_ADC_ACQ_CNFG1 0x08 +#define MAX8907B_ADC_ACQ_CNFG2 0x09 +#define MAX8907B_ADC_SCHED 0x10 +#define MAX8907B_X_MSB 0x50 +#define MAX8907B_X_LSB 0x51 +#define MAX8907B_Y_MSB 0x52 +#define MAX8907B_Y_LSB 0x53 +#define MAX8907B_Z1_MSB 0x54 +#define MAX8907B_Z1_LSB 0x55 +#define MAX8907B_Z2_MSB 0x56 +#define MAX8907B_Z2_LSB 0x57 +#define MAX8907B_AUX1_MSB 0x60 +#define MAX8907B_AUX1_LSB 0x61 +#define MAX8907B_AUX2_MSB 0x62 +#define MAX8907B_AUX2_LSB 0x63 +#define MAX8907B_VCHG_MSB 0x64 +#define MAX8907B_VCHG_LSB 0x65 +#define MAX8907B_VBBATT_MSB 0x66 +#define MAX8907B_VBBATT_LSB 0x67 +#define MAX8907B_VMBATT_MSB 0x68 +#define MAX8907B_VMBATT_LSB 0x69 +#define MAX8907B_ISNS_MSB 0x6A +#define MAX8907B_ISNS_LSB 0x6B +#define MAX8907B_THM_MSB 0x6C +#define MAX8907B_THM_LSB 0x6D +#define MAX8907B_TDIE_MSB 0x6E +#define MAX8907B_TDIE_LSB 0x6F + +// WLED Driver +#define MAX8907B_WLED_MODE_CNTL 0x84 +#define MAX8907B_ILED_CNTL 0x85 + +// Chip Identification +#define MAX8907B_II1RR 0x8E +#define MAX8907B_II2RR 0x8F + +#define MAX8907B_REG_INVALID 0xFF + +/* field defines for register bit ops */ +#define MAX8907B_OUT_VOLTAGE_MASK 0x3F +#define MAX8907B_OUT_VOLTAGE_ENABLE_BIT 0x01 +#define MAX8907B_OUT_VOLTAGE_DISABLE_MASK 0x3E + +#define MAX8907B_CTL_SEQ_SHIFT 0x02 +#define MAX8907B_CTL_SEQ_MASK 0x07 + +// CHG_CNTL_1 +#define MAX8907B_CHG_CNTL1_NOT_CHGEN_SHIFT 0x7 +#define MAX8907B_CHG_CNTL1_NOT_CHGEN_MASK 0x1 +#define MAX8907B_CHG_CNTL1_CHG_TOPOFF_SHIFT 0x5 +#define MAX8907B_CHG_CNTL1_CHG_TOPOFF_MASK 0x3 +#define MAX8907B_CHG_CNTL1_CHG_RST_HYS_SHIFT 0x3 +#define MAX8907B_CHG_CNTL1_CHG_RST_HYS_MASK 0x3 +#define MAX8907B_CHG_CNTL1_FCHG_SHIFT 0x0 +#define MAX8907B_CHG_CNTL1_FCHG_MASK 0x7 + +#define MAX8907B_CHG_CNTL1_FCHG_85MA 0 +#define MAX8907B_CHG_CNTL1_FCHG_300MA 1 +#define MAX8907B_CHG_CNTL1_FCHG_460MA 2 +#define MAX8907B_CHG_CNTL1_FCHG_600MA 3 +#define MAX8907B_CHG_CNTL1_FCHG_700MA 4 +#define MAX8907B_CHG_CNTL1_FCHG_800MA 5 +#define MAX8907B_CHG_CNTL1_FCHG_900MA 6 +#define MAX8907B_CHG_CNTL1_FCHG_1000MA 7 + +// CHG_CNTL_1 +#define MAX8907B_CHG_CNTL2_FCHG_TMR_SHIFT 0x4 +#define MAX8907B_CHG_CNTL2_FCHG_TMR_MASK 0x3 +#define MAX8907B_CHG_CNTL2_MBAT_REG_TH_SHIFT 0x3 +#define MAX8907B_CHG_CNTL2_MBAT_REG_TH_MASK 0x1 +#define MAX8907B_CHG_CNTL2_TDIE_THERM_REG_SHIFT 0x0 +#define MAX8907B_CHG_CNTL2_TDIE_THERM_REG_MASK 0x3 + +// Interrupts +#define MAX8907B_CHG_STAT_VCHG_OK_SHIFT 0x7 +#define MAX8907B_CHG_STAT_VCHG_OK_MASK 0x1 +#define MAX8907B_CHG_STAT_CHG_TMR_FLT_SHIFT 0x5 +#define MAX8907B_CHG_STAT_CHG_TMR_FLT_MASK 0x1 +#define MAX8907B_CHG_STAT_CHG_EN_STAT_SHIFT 0x4 +#define MAX8907B_CHG_STAT_CHG_EN_STAT_MASK 0x1 +#define MAX8907B_CHG_STAT_CHG_MODE_SHIFT 0x2 +#define MAX8907B_CHG_STAT_CHG_MODE_MASK 0x3 +#define MAX8907B_CHG_STAT_MBDET_SHIFT 0x1 +#define MAX8907B_CHG_STAT_MBDET_MASK 0x1 +#define MAX8907B_CHG_STAT_MBATTLOW_SHIFT 0x0 +#define MAX8907B_CHG_STAT_MBATTLOW_MASK 0x1 + +#define MAX8907B_CHG_IRQ1_VCHG_R_SHIFT 0x2 +#define MAX8907B_CHG_IRQ1_VCHG_R_MASK 0x1 +#define MAX8907B_CHG_IRQ1_VCHG_F_SHIFT 0x1 +#define MAX8907B_CHG_IRQ1_VCHG_F_MASK 0x1 +#define MAX8907B_CHG_IRQ1_VCHG_OVP_SHIFT 0x0 +#define MAX8907B_CHG_IRQ1_VCHG_OVP_MASK 0x1 + +#define MAX8907B_CHG_IRQ2_CHG_TMR_FAULT_SHIFT 0x7 +#define MAX8907B_CHG_IRQ2_CHG_TMR_FAULT_MASK 0x1 +#define MAX8907B_CHG_IRQ2_CHG_TOPOFF_SHIFT 0x6 +#define MAX8907B_CHG_IRQ2_CHG_TOPOFF_MASK 0x1 +#define MAX8907B_CHG_IRQ2_CHG_DONE_SHIFT 0x5 +#define MAX8907B_CHG_IRQ2_CHG_DONE_MASK 0x1 +#define MAX8907B_CHG_IRQ2_CHG_RST_SHIFT 0x4 +#define MAX8907B_CHG_IRQ2_CHG_RST_MASK 0x1 +#define MAX8907B_CHG_IRQ2_MBATTLOW_R_SHIFT 0x3 +#define MAX8907B_CHG_IRQ2_MBATTLOW_R_MASK 0x1 +#define MAX8907B_CHG_IRQ2_MBATTLOW_F_SHIFT 0x2 +#define MAX8907B_CHG_IRQ2_MBATTLOW_F_MASK 0x1 +#define MAX8907B_CHG_IRQ2_THM_OK_F_SHIFT 0x1 +#define MAX8907B_CHG_IRQ2_THM_OK_F_MASK 0x1 +#define MAX8907B_CHG_IRQ2_THM_OK_R_SHIFT 0x0 +#define MAX8907B_CHG_IRQ2_THM_OK_R_MASK 0x1 + +#define MAX8907B_ON_OFF_IRQ1_SW_R_SHIFT 0x7 +#define MAX8907B_ON_OFF_IRQ1_SW_R_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ1_SW_F_SHIFT 0x6 +#define MAX8907B_ON_OFF_IRQ1_SW_F_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ1_SW_1SEC_SHIFT 0x5 +#define MAX8907B_ON_OFF_IRQ1_SW_1SEC_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ1_EXTON_R_SHIFT 0x4 +#define MAX8907B_ON_OFF_IRQ1_EXTON_R_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ1_EXTON_F_SHIFT 0x3 +#define MAX8907B_ON_OFF_IRQ1_EXTON_F_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ1_SW_3SEC_SHIFT 0x2 +#define MAX8907B_ON_OFF_IRQ1_SW_3SEC_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ1_MPL_EVENT_SHIFT 0x1 +#define MAX8907B_ON_OFF_IRQ1_MPL_EVENT_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ1_RSTIN_F_SHIFT 0x0 +#define MAX8907B_ON_OFF_IRQ1_RSTIN_F_MASK 0x1 + +#define MAX8907B_ON_OFF_IRQ2_SYSCKEN_R_SHIFT 0x1 +#define MAX8907B_ON_OFF_IRQ2_SYSCKEN_R_MASK 0x1 +#define MAX8907B_ON_OFF_IRQ2_SYSCKEN_F_SHIFT 0x0 +#define MAX8907B_ON_OFF_IRQ2_SYSCKEN_F_MASK 0x1 + +#define MAX8907B_RTC_IRQ_ALARM0_R_SHIFT 0x3 +#define MAX8907B_RTC_IRQ_ALARM0_R_MASK 0x1 +#define MAX8907B_RTC_IRQ_ALARM1_R_SHIFT 0x2 +#define MAX8907B_RTC_IRQ_ALARM1_R_MASK 0x1 + +// ON/OFF controller +#define MAX8907B_SYSENSEL_HRDSTEN_SHIFT 0x7 +#define MAX8907B_SYSENSEL_HRDSTEN_MASK 0x1 + +#define MAX8907B_RESET_CNFG_PWREN_EN_SHIFT 0x7 +#define MAX8907B_RESET_CNFG_PWREN_EN_MASK 0x1 + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_MAX8907B_REG_HEADER diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c new file mode 100644 index 000000000000..1c4d61a01a98 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <linux/time.h> +#include <linux/rtc.h> +#include "max8907b.h" +#include "max8907b_rtc.h" +#include "max8907b_i2c.h" +#include "max8907b_reg.h" + +/** +* The Maxim 8907B does not have an RTC that simply counts +* seconds from some time t0 (as defined by the OS API). +* Instead, this RTC contains several BCD (Binary Coded Decimal) +* registers, including: seconds, minutes, hours, days, day of +* week, date, etc... These registers account for leap year and +* the various days of the month as well. +* +* Since the OS interpretation of seconds to a particular +* date/time from some OS-defined t0 is unknown at this level of +* the implementation, it is not possible to translate the given +* seconds into these registers (at least, not without a +* dependency on some OS-specific information). +* +*/ + +#define MAX8907B_SECONDS_PER_DAY (60*60*24) +#define MAX8907B_SECONDS_PER_HOUR (60*60) +#define MAX8907B_SECONDS_PER_MINUTE (60) + +#define LINUX_RTC_BASE_YEAR 1900 + +/* Macro for conversion of BCD number to decimal format */ +#define BCD_TO_DECIMAL(BCD) \ + ((((BCD) & 0xF0) >> 4) * 10 + ((BCD) & 0xF)) +/* Macro for conversion of decimal number to BCD format */ +#define DECIMAL_TO_BCD(DEC) \ + ((((DEC) / 10) << 4) | ((DEC) % 10)) + +static NvBool bRtcNotInitialized = NV_TRUE; + +NvBool +Max8907bRtcCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count) +{ + NvU32 data = 0; + NvU32 BcdHours, BcdMinutes, BcdSeconds; + NvU32 Hours, Minutes, Seconds; + NvU32 BcdDD, BcdMM, BcdYY1, BcdYY2; + NvU32 DD, MM, YY1, YY2, YYYY; +#if NV_DEBUG + struct rtc_time tm; +#endif + + *Count = 0; + // Read seconds, minute, hour and weekday data from RTC registers + if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_SEC, &data)) + { + NVODMPMU_PRINTF(("\n Read time data-sec=0x%x ", data)); + // Extract seconds, minute and hour data from RTC registers read + BcdHours = (data >> 8) & 0xFF; + BcdMinutes = (data >> 16) & 0xFF; + BcdSeconds = (data >> 24) & 0xFF; + + // Convert BCD time into decimal values + Hours = BCD_TO_DECIMAL(BcdHours); + Minutes = BCD_TO_DECIMAL(BcdMinutes); + Seconds = BCD_TO_DECIMAL(BcdSeconds); + + // Read day, month, yy1 and yy2 data from RTC registers + if (Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_DATE, &data)) + { + NVODMPMU_PRINTF(("\n Read time data-year=0x%x ", data)); + // Extract day, month, yy1 and yy2 data from RTC registers read + BcdYY2 = (data & 0xFF); + BcdYY1 = (data >> 8) & 0xFF; + BcdMM = (data >> 16) & 0xFF; + BcdDD = (data >> 24) & 0xFF; + // convert bcd day/month/year data to decimal values + YY2 = BCD_TO_DECIMAL(BcdYY2); + YY1 = BCD_TO_DECIMAL(BcdYY1); + YYYY = (YY2 * 100 + YY1) & 0xFFFF; + MM = BCD_TO_DECIMAL(BcdMM); + DD = BCD_TO_DECIMAL(BcdDD); + // get seconds since reference time value given + // year, month, day, hour, minutes and seconds + // NOTE: Using linux specific API mktime for conversion + *Count = mktime(YYYY, (MM + 1), DD, Hours, Minutes, Seconds); + NVODMPMU_PRINTF(("\n Rtc read count=0x%x ", *Count)); + NVODMPMU_PRINTF(("\n mktime: YYYY=%d MM=%d DD=%d Hr=%d Min=%d " + "Sec=%d, *Count=0x%x ", YYYY, (MM + 1), DD, Hours, Minutes, + Seconds, *Count)); +#if NV_DEBUG + // Call to verify that reverse conversion of seconds matches date + rtc_time_to_tm(*Count, &tm); + // Check if Local_rtc_time_to_tm can return values sent to mktime + NVODMPMU_PRINTF(("\n rtc_time_to_tm: YYYY=%d MM=%d DD=%d Hr=%d " + "Min=%d Sec=%d, *Count=0x%x ", (tm.tm_year + + LINUX_RTC_BASE_YEAR), tm.tm_mon, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec, *Count)); +#endif + } + else + { + NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. ")); + return NV_FALSE; + } + } + else + { + NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. ")); + return NV_FALSE; + } + NVODMPMU_PRINTF(("\n *Count=0x%x ", *Count)); + return NV_TRUE; +} + +NvBool +Max8907bRtcAlarmCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count) +{ + return NV_FALSE; +} + +NvBool +Max8907bRtcCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count) +{ + NvU32 BcdHours, BcdMinutes, BcdSeconds; + NvU32 data = 0; + NvU8 BcdDD, BcdMM, BcdYY1, BcdYY2; + NvU16 YYYY; + struct rtc_time tm; +#if NV_DEBUG + NvU32 data1; +#endif + + NVODMPMU_PRINTF(("\n Rtc write count=0x%x ", Count)); + // convert seconds since reference time into date + // NOTE: using linux specific convert function rtc_time_to_tm + rtc_time_to_tm(Count, &tm); + NVODMPMU_PRINTF(("\n rtc_time_to_tm: YYYY=%d MM=%d DD=%d Hr=%d Min=%d " + "Sec=%d, *Count=0x%x ", (tm.tm_year + LINUX_RTC_BASE_YEAR), + (tm.tm_mon + 1), tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, Count)); + + // Convert time to bcd format + BcdHours = DECIMAL_TO_BCD(tm.tm_hour); + BcdMinutes = DECIMAL_TO_BCD(tm.tm_min); + BcdSeconds = DECIMAL_TO_BCD(tm.tm_sec); + + data = (BcdSeconds << 24) | (BcdMinutes << 16) | (BcdHours << 8); + // write time - seconds, minutes and hours in a day to RTC registers + if (Max8907bRtcI2cWriteTime(hDevice, MAX8907B_RTC_SEC, data)) + { + // set the day, month, year + // Assuming we get the days since 1 Jan 1970 + + // convert date to bcd format + BcdDD = DECIMAL_TO_BCD((NvU8)tm.tm_mday); + BcdMM = DECIMAL_TO_BCD((NvU8)tm.tm_mon); + YYYY = (NvU16)tm.tm_year + LINUX_RTC_BASE_YEAR; + BcdYY1 = DECIMAL_TO_BCD((NvU8)(YYYY % 100)); + BcdYY2 = DECIMAL_TO_BCD((NvU8)(YYYY / 100)); + data = (NvU32)((BcdDD << 24) | (BcdMM << 16) | (BcdYY1 << 8) | BcdYY2); + // write date - day, month, and year to RTC registers + if (!(Max8907bRtcI2cWriteTime(hDevice, MAX8907B_RTC_DATE, data))) + { + NVODMPMU_PRINTF(("\n Max8907bRtcCountWrite() error. ")); + return NV_FALSE; + } +#if NV_DEBUG + // verify that read back values from RTC matches written values + if (!(Max8907bRtcI2cReadTime(hDevice, MAX8907B_RTC_DATE, &data1))) + { + NVODMPMU_PRINTF(("\n Max8907bRtcCountRead() error. ")); + return NV_FALSE; + } + if (data1 == data) + { + NVODMPMU_PRINTF(("\n Write read Success. ")); + return NV_TRUE; + } + else + { + // return error when read data does not match written data + NVODMPMU_PRINTF(("\n Error: write data=0x%x, rd data=0x%x. ", data, data1)); + return NV_FALSE; + } +#endif + } + else + { + NVODMPMU_PRINTF(("\n Max8907bRtcCountWrite() error. ")); + return NV_FALSE; + } + + return NV_TRUE; +} + +NvBool +Max8907bRtcAlarmCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count) +{ + return NV_FALSE; +} + +NvBool +Max8907bRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice) +{ + return NV_FALSE; +} + +NvBool +Max8907bRtcAlarmIntEnable( + NvOdmPmuDeviceHandle hDevice, + NvBool Enable) +{ + return NV_FALSE; +} + +NvBool +Max8907bIsRtcInitialized(NvOdmPmuDeviceHandle hDevice) +{ + return (!bRtcNotInitialized); +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.h new file mode 100644 index 000000000000..0baa0de55339 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_rtc.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_MAX8907B_RTC_HEADER +#define INCLUDED_MAX8907B_RTC_HEADER + +#include "pmu_hal.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Read RTC count register */ + +NvBool +Max8907bRtcCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count); + +/* Read RTC alarm count register */ + +NvBool +Max8907bRtcAlarmCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count); + +/* Write RTC count register */ + +NvBool +Max8907bRtcCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count); + +/* Write RTC alarm count register */ + +NvBool +Max8907bRtcAlarmCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count); + +/* Reads RTC alarm interrupt mask status */ + +NvBool +Max8907bRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice); + +/* Enables / Disables the RTC alarm interrupt */ + +NvBool +Max8907bRtcAlarmIntEnable( + NvOdmPmuDeviceHandle hDevice, + NvBool Enable); + +/* Checks if boot was from nopower / powered state */ + +NvBool +Max8907bRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice); + +NvBool +Max8907bIsRtcInitialized(NvOdmPmuDeviceHandle hDevice); + + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_MAX8907B_RTC_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h new file mode 100644 index 000000000000..1b362aac43f4 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/max8907b_supply_info_table.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_MAX8907B_SUPPLY_INFO_HEADER +#define INCLUDED_MAX8907B_SUPPLY_INFO_HEADER + +#include "nvodm_pmu.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// Defines for the requested voltage for each supply (mV). +// This is board specific and ODM should change this based on device. +#define MAX8907B_REQUESTVOLTAGE_LX_V1 1000 +#define MAX8907B_REQUESTVOLTAGE_LX_V2 1200 +#define MAX8907B_REQUESTVOLTAGE_LX_V3 1800 + +#define MAX8907B_REQUESTVOLTAGE_LDO1 3300 +#define MAX8907B_REQUESTVOLTAGE_LDO2 1100 +#define MAX8907B_REQUESTVOLTAGE_LDO3 1800 +#define MAX8907B_REQUESTVOLTAGE_LDO4 3300 +#define MAX8907B_REQUESTVOLTAGE_LDO5 2800 +#define MAX8907B_REQUESTVOLTAGE_LDO6 1800 +#define MAX8907B_REQUESTVOLTAGE_LDO7 2800 +#define MAX8907B_REQUESTVOLTAGE_LDO8 3000 +#define MAX8907B_REQUESTVOLTAGE_LDO9 2800 +#define MAX8907B_REQUESTVOLTAGE_LDO10 3000 +#define MAX8907B_REQUESTVOLTAGE_LDO11 3300 +#define MAX8907B_REQUESTVOLTAGE_LDO12 2800 +#define MAX8907B_REQUESTVOLTAGE_LDO13 2800 +#define MAX8907B_REQUESTVOLTAGE_LDO14 2800 +#define MAX8907B_REQUESTVOLTAGE_LDO15 3300 +#define MAX8907B_REQUESTVOLTAGE_LDO16 1300 +#define MAX8907B_REQUESTVOLTAGE_LDO17 1200 +#define MAX8907B_REQUESTVOLTAGE_LDO18 1800 +#define MAX8907B_REQUESTVOLTAGE_LDO19 2800 +#define MAX8907B_REQUESTVOLTAGE_LDO20 1200 + +#define MAX8907B_REQUESTVOLTAGE_EXT_DCDC_1 5000 // Fixed +#define MAX8907B_REQUESTVOLTAGE_EXT_DCDC_2 0 // Reserved +#define MAX8907B_REQUESTVOLTAGE_EXT_DCDC_3 1050 // Fixed (unless FAN5355 is enabled) +#define MAX8907B_REQUESTVOLTAGE_EXT_DCDC_4 0 // VBL1, controlled by display adaptation +#define MAX8907B_REQUESTVOLTAGE_EXT_DCDC_5 0 // VBL2, controlled by display adaptation +#define MAX8907B_REQUESTVOLTAGE_EXT_DCDC_6 0 // Reserved + +#define MAX8907B_REQUESTVOLTAGE_SDBY 1100 + +// Defines default sequencer selection +#define MAX8907B_SEQSEL_DEFAULT_LX_V1 0 /* SEQ1 (SYSEN) */ +#define MAX8907B_SEQSEL_DEFAULT_LX_V2 0 /* SEQ1 (SYSEN) */ + +// Defines common for all supplies PWREN sequencer selection +#define MAX8907B_SEQSEL_PWREN_LXX 1 /* SEQ2 (PWREN) */ + +// Defines common for all supplies I2C (s/w) sequencer selection +#define MAX8907B_SEQSEL_I2CEN_LXX 7 /* I2CEN (s/w) */ + +// Defines sequencer count default values +#define MAX8907B_SEQCNT_DEFAULT_LX_V1 0x1C +#define MAX8907B_SEQCNT_DEFAULT_LX_V2 0x1C + +// Defines sequencer count PWREN control values (these settings applied +// togeteher, when both CPU/V1 and CORE/V2 rails are attached to PWREN; +// in case when only CPU/V1 rail is attached no delay is specified) +// B[7:4] - power up delay in 20us taps +// B[3:0] - power down delay in 20us taps +#define MAX8907B_SEQCNT_PWREN_LX_V1 0xC0 /* 240us up delay */ +#define MAX8907B_SEQCNT_PWREN_LX_V2 0x00 /* no delay */ + +// Defines PMU output timing parameters. Scaling up time is dynamically +// calculated based on the slew rate maintained by MAX8907B. Turn On delay +// is fixed at max. Turn Off time is "just in case" placeholder - no need +// for s/w to track when output capacitors are discharged. +#define MAX8907B_SCALE_UP_UV_PER_US (2500) +#define MAX8907B_TURN_ON_TIME_US (3000) +#define MAX8907B_TURN_OFF_TIME_US (20) + +// Output voltages supplied by PMU +typedef enum +{ + Max8907bPmuSupply_Invalid = 0x0, + + /*-- Step-Down DC Regulators --*/ + Max8907bPmuSupply_LX_V1, // LX_V1 (V1), step-down DC regulator + Max8907bPmuSupply_LX_V2, // LX_V2 (V2), step-down DC regulator + Max8907bPmuSupply_LX_V3, // LX_V3 (V3), step-down DC regulator + + /*-- Standby LDO --*/ + Max8907bPmuSupply_VRTC, // VRTC (RTC), always-on supply for RTC + + /*-- Linear Regulator Outputs --*/ + Max8907bPmuSupply_LDO1, // LDO1 (VOUT1), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO2, // LDO2 (VOUT2), linear regulator output (default = 1.2V) + Max8907bPmuSupply_LDO3, // LDO3 (VOUT3), linear regulator output (default = 1.2V) + Max8907bPmuSupply_LDO4, // LDO4 (VOUT4), linear regulator output (default = 3.3V) + Max8907bPmuSupply_LDO5, // LDO5 (VOUT5), linear regulator output (default = 1.8V) + Max8907bPmuSupply_LDO6, // LDO6 (VOUT6), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO7, // LDO7 (VOUT7), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO8, // LDO8 (VOUT8), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO9, // LDO9 (VOUT9), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO10, // LDO10 (VOUT10), linear regulator output (default = 1.8V) + Max8907bPmuSupply_LDO11, // LDO11 (VOUT11), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO12, // LDO12 (VOUT12), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO13, // LDO13 (VOUT13), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO14, // LDO14 (VOUT14), linear regulator output (default = 3.3V) + Max8907bPmuSupply_LDO15, // LDO15 (VOUT15), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO16, // LDO16 (VOUT16), linear regulator output (default = 2.8V) + Max8907bPmuSupply_LDO17, // LDO17 (VOUT17), linear regulator output (default = 1.2V) + Max8907bPmuSupply_LDO18, // LDO18 (VOUT18), linear regulator output (default = 1.2V) + Max8907bPmuSupply_LDO19, // LDO19 (VOUT19), linear regulator output (default = 3.3V) + Max8907bPmuSupply_LDO20, // LDO20 (VOUT20), linear regulator output (default = 1.2V) + + /*-- White LED --*/ + Max8907bPmuSupply_WHITE_LED, // (Boost WLED) + + /*-- External DC/DC switcher --*/ + Max8907bPmuSupply_EXT_DCDC_1, // EXT_DC/DC1 + Max8907bPmuSupply_EXT_DCDC_2, // EXT_DC/DC2 + Max8907bPmuSupply_EXT_DCDC_3, // EXT_DC/DC3 + Max8907bPmuSupply_EXT_DCDC_4, // EXT_DC/DC4 + Max8907bPmuSupply_EXT_DCDC_5, // EXT_DC/DC5 + Max8907bPmuSupply_EXT_DCDC_6, // EXT_DC/DC6 + + /** USB1 & USB3 VBus's are getting 5V from DCDC_3 **/ + Max8907bPmuSupply_EXT_DCDC_3_USB1, //USB1 VBUS + Max8907bPmuSupply_EXT_DCDC_3_USB3, // USB3 VBUS + + /** Secondary PMU MIC2826 Rails **/ + MIC2826PmuSupply_BUCK, + MIC2826PmuSupply_LDO1, + MIC2826PmuSupply_LDO2, + MIC2826PmuSupply_LDO3, + + // External DCDC controlled by LX_V1, and scaled by digital + // potentiometer (DPM) AD5258 + Max8907bLxV1_Ad5258_DPM_EXT_DCDC_7, + + Max8907bPmuSupply_Num, + Max8907bPmuSupply_Force32 = 0x7FFFFFFF +} Max8907bPmuSupply; + +typedef NvU32 (*Max8907bPmuVoltageFunc)(const NvU32 data); + +typedef struct Max8907bPmuSupplyInfoRec +{ + Max8907bPmuSupply supply; + + // I2C Registers + NvU8 ControlRegAddr; + NvU8 SequencerCountRegAddr; + NvU8 OutputVoltageRegAddr; + NvU8 OutputPort; + NvU8 PmuGpio; + + Max8907bPmuVoltageFunc GetVoltage; // Function to convert register bits to real voltage + Max8907bPmuVoltageFunc SetVoltage; // Function to convert real voltage to register bits + + NvOdmPmuVddRailCapabilities cap; +} Max8907bPmuSupplyInfo; + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_MAX8907B_SUPPLY_INFO_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_i2c.c new file mode 100644 index 000000000000..097f0510d581 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_i2c.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_pmu.h" +#include "nvodm_services.h" +#include "mic2826_i2c.h" +#include "mic2826_reg.h" + +NvBool MIC2826I2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data) +{ + NvU8 WriteBuffer[2]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo; + + WriteBuffer[0] = Addr & 0xFF; + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = MIC2826_SLAVE_ADDR; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + MIC2826_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + +NvBool MIC2826I2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data) +{ + NvU8 ReadBuffer = 0; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + ReadBuffer = Addr & 0xFF; + + TransactionInfo[0].Address = MIC2826_SLAVE_ADDR; + TransactionInfo[0].Buf = &ReadBuffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + TransactionInfo[1].Address = (MIC2826_SLAVE_ADDR | 0x1); + TransactionInfo[1].Buf = &ReadBuffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2, + MIC2826_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + *Data = ReadBuffer; + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_i2c.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_i2c.h new file mode 100644 index 000000000000..850ab9907b11 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_i2c.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_PMU_MIC2826_I2C_H +#define INCLUDED_NVODM_PMU_MIC2826_I2C_H + +#include "nvodm_pmu.h" +#include "max8907b.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// Constant definition +#define MIC2826_SLAVE_ADDR 0xB4 +#define MIC2826_I2C_SPEED_KHZ 400 + +// Function declaration +NvBool MIC2826I2cWrite8( + NvOdmPmuDeviceHandle hPmu, + NvU8 Addr, + NvU8 Data); + +NvBool MIC2826I2cRead8( + NvOdmPmuDeviceHandle hPmu, + NvU8 Addr, + NvU8 *Data); + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_NVODM_PMU_MIC2826_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_reg.h new file mode 100644 index 000000000000..24b31cfa8824 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/mic2826_reg.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MIC2826_REG_HEADER +#define MIC2826_REG_HEADER + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define MIC2826_REG_INVALID ~0x0 +#define MIC2826_REG_ADDR_ENABLE 0x00 +#define MIC2826_REG_ADDR_STATUS 0x01 +#define MIC2826_REG_ADDR_BUCK 0x02 +#define MIC2826_REG_ADDR_LD01 0x03 +#define MIC2826_REG_ADDR_LD02 0x04 +#define MIC2826_REG_ADDR_LD03 0x05 + +#define MIC2826_REG_ENABLE_BK 0x1 +#define MIC2826_REG_ENABLE_LDO1 0x2 +#define MIC2826_REG_ENABLE_LDO2 0x4 +#define MIC2826_REG_ENABLE_LDO3 0x8 +#define MIC2826_REG_ENABLE_SEQCNT ~0x10 +#define MIC2826_REG_ENABLE_POAF ~0x20 + +#define MIC2826_REG_DISABLE_BK ~0x1 +#define MIC2826_REG_DISABLE_LDO1 ~0x2 +#define MIC2826_REG_DISABLE_LDO2 ~0x4 +#define MIC2826_REG_DISABLE_LDO3 ~0x8 +#define MIC2826_REG_DISABLE_SEQCNT 0x10 +#define MIC2826_REG_DISABLE_POAF 0x20 + +#define MIC2826_REG_STATUS_BK 0x1 +#define MIC2826_REG_STATUS_LDO1 0x2 +#define MIC2826_REG_STATUS_LDO2 0x4 +#define MIC2826_REG_STATUS_LDO3 0x8 +#define MIC2826_TSD_STATUS_TSD 0x10 +#define MIC2826_REG_STATUS_UVLO 0x20 +#define MIC2826_REG_STATUS_TSD_NORMAL ~0x10 +#define MIC2826_REG_STATUS_UVLO_NORMAL ~0x20 + +#define MIC2826_REG_STATUS_INT_EN 0x40 +#define MIC2826_REG_STATUS_INT_DIS ~0x40 + +#define MIC2826_BUCK_OUT_VOLTAGE_0800 0x00 //0.800 V +#define MIC2826_BUCK_OUT_VOLTAGE_0825 0x01 //0.825 V +#define MIC2826_BUCK_OUT_VOLTAGE_0850 0x02 //0.850 V +#define MIC2826_BUCK_OUT_VOLTAGE_0875 0x03 //0.875 V +#define MIC2826_BUCK_OUT_VOLTAGE_0900 0x04 //0.900 V +#define MIC2826_BUCK_OUT_VOLTAGE_0925 0x05 //0.925 V +#define MIC2826_BUCK_OUT_VOLTAGE_0950 0x06 //0.950 V +#define MIC2826_BUCK_OUT_VOLTAGE_0975 0x07 //0.975 V +#define MIC2826_BUCK_OUT_VOLTAGE_1000 0x08 //1.000 V +#define MIC2826_BUCK_OUT_VOLTAGE_1025 0x09 //1.025 V +#define MIC2826_BUCK_OUT_VOLTAGE_1050 0x0A //1.050 V +#define MIC2826_BUCK_OUT_VOLTAGE_1075 0x0B //1.075 V +#define MIC2826_BUCK_OUT_VOLTAGE_1100 0x0C //1.100 V +#define MIC2826_BUCK_OUT_VOLTAGE_1125 0x0D //1.125 V +#define MIC2826_BUCK_OUT_VOLTAGE_1150 0x0E //1.150 V +#define MIC2826_BUCK_OUT_VOLTAGE_1175 0x0F //1.175 V +#define MIC2826_BUCK_OUT_VOLTAGE_1200 0x10 //1.200 V +#define MIC2826_BUCK_OUT_VOLTAGE_1250 0x11 //1.250 V +#define MIC2826_BUCK_OUT_VOLTAGE_1300 0x12 //1.300 V +#define MIC2826_BUCK_OUT_VOLTAGE_1350 0x13 //1.350 V +#define MIC2826_BUCK_OUT_VOLTAGE_1400 0x14 //1.400 V +#define MIC2826_BUCK_OUT_VOLTAGE_1450 0x15 //1.450 V +#define MIC2826_BUCK_OUT_VOLTAGE_1500 0x16 //1.500 V +#define MIC2826_BUCK_OUT_VOLTAGE_1550 0x17 //1.550 V +#define MIC2826_BUCK_OUT_VOLTAGE_1600 0x18 //1.600 V +#define MIC2826_BUCK_OUT_VOLTAGE_1650 0x19 //1.650 V +#define MIC2826_BUCK_OUT_VOLTAGE_1700 0x1A //1.700 V +#define MIC2826_BUCK_OUT_VOLTAGE_1750 0x1B //1.750 V +#define MIC2826_BUCK_OUT_VOLTAGE_1800 0x1C //1.800 V + +#define MIC2826_LDO_OUT_VOLTAGE_0800 0x00 //0.800 V +#define MIC2826_LDO_OUT_VOLTAGE_0850 0x0B //0.850 V +#define MIC2826_LDO_OUT_VOLTAGE_0900 0x14 //0.900 V +#define MIC2826_LDO_OUT_VOLTAGE_0950 0x1D //0.950 V +#define MIC2826_LDO_OUT_VOLTAGE_1000 0x25 //1.000 V +#define MIC2826_LDO_OUT_VOLTAGE_1050 0x2E //1.050 V +#define MIC2826_LDO_OUT_VOLTAGE_1100 0x37 //1.100 V +#define MIC2826_LDO_OUT_VOLTAGE_1150 0x3E //1.150 V +#define MIC2826_LDO_OUT_VOLTAGE_1200 0x45 //1.200 V +#define MIC2826_LDO_OUT_VOLTAGE_1250 0x4B //1.250 V +#define MIC2826_LDO_OUT_VOLTAGE_1300 0x51 //1.300 V +#define MIC2826_LDO_OUT_VOLTAGE_1350 0x57 //1.350 V +#define MIC2826_LDO_OUT_VOLTAGE_1400 0x5C //1.400 V +#define MIC2826_LDO_OUT_VOLTAGE_1450 0x60 //1.450 V +#define MIC2826_LDO_OUT_VOLTAGE_1500 0x65 //1.500 V +#define MIC2826_LDO_OUT_VOLTAGE_1550 0x69 //1.550 V +#define MIC2826_LDO_OUT_VOLTAGE_1600 0x6D //1.600 V +#define MIC2826_LDO_OUT_VOLTAGE_1650 0x72 //1.650 V +#define MIC2826_LDO_OUT_VOLTAGE_1700 0x78 //1.700 V +#define MIC2826_LDO_OUT_VOLTAGE_1750 0x75 //1.750 V +#define MIC2826_LDO_OUT_VOLTAGE_1800 0x85 //1.800 V +#define MIC2826_LDO_OUT_VOLTAGE_1850 0x8B //1.850 V +#define MIC2826_LDO_OUT_VOLTAGE_1900 0x90 //1.900 V +#define MIC2826_LDO_OUT_VOLTAGE_1950 0x95 //1.950 V +#define MIC2826_LDO_OUT_VOLTAGE_2000 0x9A //2.000 V +#define MIC2826_LDO_OUT_VOLTAGE_2050 0x9F //2.050 V +#define MIC2826_LDO_OUT_VOLTAGE_2100 0xA3 //2.100 V +#define MIC2826_LDO_OUT_VOLTAGE_2150 0xA7 //2.150 V +#define MIC2826_LDO_OUT_VOLTAGE_2200 0xAB //2.200 V +#define MIC2826_LDO_OUT_VOLTAGE_2250 0xA0 //2.250 V +#define MIC2826_LDO_OUT_VOLTAGE_2300 0xB3 //2.300 V +#define MIC2826_LDO_OUT_VOLTAGE_2350 0xB7 //2.350 V +#define MIC2826_LDO_OUT_VOLTAGE_2400 0xBA //2.400 V +#define MIC2826_LDO_OUT_VOLTAGE_2450 0xBD //2.450 V +#define MIC2826_LDO_OUT_VOLTAGE_2500 0xC1 //2.500 V +#define MIC2826_LDO_OUT_VOLTAGE_2550 0xC3 //2.550 V +#define MIC2826_LDO_OUT_VOLTAGE_2600 0xC6 //2.600 V +#define MIC2826_LDO_OUT_VOLTAGE_2650 0xC9 //2.650 V +#define MIC2826_LDO_OUT_VOLTAGE_2700 0xCB //2.700 V +#define MIC2826_LDO_OUT_VOLTAGE_2750 0xCE //2.750 V +#define MIC2826_LDO_OUT_VOLTAGE_2800 0xD1 //2.800 V +#define MIC2826_LDO_OUT_VOLTAGE_2850 0xD3 //2.850 V +#define MIC2826_LDO_OUT_VOLTAGE_2900 0xD5 //2.900 V +#define MIC2826_LDO_OUT_VOLTAGE_2950 0xD8 //2.950 V +#define MIC2826_LDO_OUT_VOLTAGE_3000 0xDA //3.000 V +#define MIC2826_LDO_OUT_VOLTAGE_3050 0xDC //3.050 V +#define MIC2826_LDO_OUT_VOLTAGE_3100 0xDE //3.100 V +#define MIC2826_LDO_OUT_VOLTAGE_3150 0xE0 //3.150 V +#define MIC2826_LDO_OUT_VOLTAGE_3200 0xE3 //3.200 V +#define MIC2826_LDO_OUT_VOLTAGE_3250 0xE6 //3.250 V +#define MIC2826_LDO_OUT_VOLTAGE_3300 0xE8 //3.300 V + +#define MIC2826_BUCK_VOLTAGE_OFFSET 800 +#define MIC2826_BUCK_VOLTAGE_MIN_MV 800 +#define MIC2826_BUCK_VOLTAGE_STEP_MV 25 +#define MIC2826_BUCK_VOLTAGE_STEP_25MV 25 +#define MIC2826_BUCK_VOLTAGE_STEP_50MV 50 +#define MIC2826_BUCK_VOLTAGE_MAX_MV 1800 +#define MIC2826_BUCK_REQUESTVOLTAGE_MV 1800 + +#define MIC2826_LDO_VOLTAGE_OFFSET 800 +#define MIC2826_LDO_VOLTAGE_MIN_MV 800 +#define MIC2826_LDO_VOLTAGE_STEP_MV 50 +#define MIC2826_LDO_VOLTAGE_MAX_MV 3300 +#define MIC2826_LDO1_REQUESTVOLTAGE_MV 1800 +#define MIC2826_LDO2_REQUESTVOLTAGE_MV 1800 +#define MIC2826_LDO3_REQUESTVOLTAGE_MV 1200 + +#define MIC2826_INVALID_PORT 0xFF + + +#if defined(__cplusplus) +} +#endif + + +#endif diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_i2c.c new file mode 100644 index 000000000000..4ca397b9951b --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_i2c.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_pmu.h" +#include "nvodm_services.h" +#include "tca6416_expander_i2c.h" +#include "tca6416_expander_reg.h" + + + +#define TCA6416_SLAVE_ADDR 0x40 // (7'h20) +#define TCA6416_I2C_SPEED_KHZ 400 + + +NvBool +Tca6416ConfigPortPin( + NvOdmPmuDeviceHandle hDevice, + NvU32 PortNo, + NvU32 PinNo, + GpioPinMode Mode) +{ + NvU8 WriteBuffer[2]; + NvOdmI2cStatus Error; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + + NvOdmI2cTransactionInfo TransactionInfo; + static NvU8 ConfigPort1Val = 0xFF; // set to default value + static NvU8 ConfigPort2Val = 0xFF; // set to default value + + if (PortNo == TCA6416_PORT_0) + { + WriteBuffer[0] = TCA6416_CONFIG_PORT_0 & 0xFF; + + if (Mode == GpioPinMode_Output) + { + WriteBuffer[1] = ((ConfigPort1Val & (0xFF & (~(1 << PinNo)))) | (0x0 << PinNo)); + } else if (Mode == GpioPinMode_InputData) + { + WriteBuffer[1] = ((ConfigPort1Val & (0xFF & (~(1 << PinNo)))) | (0x1 << PinNo)); + } + ConfigPort1Val = WriteBuffer[1]; + }else if (PortNo == TCA6416_PORT_1) + { + WriteBuffer[0] = TCA6416_CONFIG_PORT_1 & 0xFF; + + if (Mode == GpioPinMode_Output) + { + WriteBuffer[1] = (ConfigPort2Val & (0xFF & (~(1 << PinNo)))); + } else if (Mode == GpioPinMode_InputData) + { + WriteBuffer[1] = ((ConfigPort2Val & (0xFF & (~(1 << PinNo)))) | (0x1 << PinNo)); + } + ConfigPort2Val = WriteBuffer[1]; + } + + TransactionInfo.Address = TCA6416_SLAVE_ADDR; + TransactionInfo.Buf = WriteBuffer; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + // write the pmu Offset (from where data gpio need to be set) + Error = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + TCA6416_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + + if (Error == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (Error) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("Tca6416ConfigPortPin Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("Tca6416ConfigPortPin Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + + +NvBool +Tca6416WritePortPin( + NvOdmPmuDeviceHandle hDevice, + NvU32 PortNo, + NvU32 PinNo, + GpioPinState data) +{ + NvOdmI2cTransactionInfo TransactionInfo; + NvOdmI2cStatus Error; + NvU8 WriteBuffer[2]; + Max8907bPrivData *hPmu = (Max8907bPrivData*)hDevice->pPrivate; + + static NvU8 OutPut1Val = 0xFF; // set to default value + static NvU8 OutPut2Val = 0xFF; // set to default value + + + /* set the command byte */ + if (PortNo == TCA6416_PORT_0) + { + WriteBuffer[0] = TCA6416_OUTPUT_PORT_0 & 0xFF; + // Set the data + WriteBuffer[1] = ((OutPut1Val & (0xFF & (~(1 << PinNo)))) | (data << PinNo)); + + OutPut1Val = WriteBuffer[1]; + + } else if (PortNo == TCA6416_PORT_1) + { + WriteBuffer[0] = TCA6416_OUTPUT_PORT_1 & 0xFF; + // Set the data + WriteBuffer[1] = ((OutPut2Val & (0xFF & (~(1 << PinNo)))) | (data << PinNo)); + + OutPut2Val = WriteBuffer[1]; + } + + TransactionInfo.Address = TCA6416_SLAVE_ADDR; + TransactionInfo.Buf = WriteBuffer; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + Error = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + TCA6416_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + + if (Error == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (Error) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("Tca6416I2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("Tca6416I2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + +NvBool +Tca6416ReadPortPin( + NvOdmPmuDeviceHandle hDevice, + NvU32 PortNo, + NvU32 PinNo, + GpioPinState*State) +{ + + // Need to implement + return NV_TRUE; +} + + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_i2c.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_i2c.h new file mode 100644 index 000000000000..ce14b79df090 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_i2c.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_TCA6416_EXPANDER_I2C_H +#define INCLUDED_TCA6416_EXPANDER_I2C_H + +#include "nvodm_pmu.h" +#include "max8907b.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + + + +/** + * @brief Defines the possible modes. + */ + +typedef enum +{ + + /** + * Specifies the gpio pin as not in use. + */ + GpioPinMode_Inactive = 0, + + /// Specifies the gpio pin mode as input. + GpioPinMode_InputData, + + /// Specifies the gpio pin mode as output. + GpioPinMode_Output, + + GpioPinMode_Num, + GpioPinMode_Force32 = 0x7FFFFFFF +} GpioPinMode; + + +/** + * @brief Defines the pin state + */ + +typedef enum +{ + // Pin state high + GpioPinState_Low = 0, + // Pin is high + GpioPinState_High, + GpioPinState_Num, + GpioPinState_Force32 = 0x7FFFFFFF +} GpioPinState; + + +NvBool Tca6416ConfigPortPin( + NvOdmPmuDeviceHandle hDevice, + NvU32 portNo, + NvU32 pinNo, + GpioPinMode Mode); + +NvBool Tca6416WritePortPin( + NvOdmPmuDeviceHandle hDevice, + NvU32 portNo, + NvU32 pinNo, + GpioPinState data); + +NvBool Tca6416ReadPortPin( + NvOdmPmuDeviceHandle hDevice, + NvU32 portNo, + NvU32 pinNo, + GpioPinState*State); + + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_TCA6416_EXPANDER_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_reg.h new file mode 100644 index 000000000000..588335a804c8 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/max8907b/tca6416_expander_reg.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef INCLUDED_TCA6416_EXPANDER_REG_HEADER +#define INCLUDED_TCA6416_EXPANDER_REG_HEADER + + +// Ports evailable on TCA6416. it is having 2 ports +#define TCA6416_PORT_0 0 +#define TCA6416_PORT_1 1 + + +// Each port is having 8 pins +#define TCA6416_PIN_0 0 +#define TCA6416_PIN_1 1 +#define TCA6416_PIN_2 2 +#define TCA6416_PIN_3 3 +#define TCA6416_PIN_4 4 +#define TCA6416_PIN_5 5 +#define TCA6416_PIN_6 6 +#define TCA6416_PIN_7 7 + + +// Registers +#define TCA6416_INPUT_PORT_0 0x00 // For ports 00 to 07 +#define TCA6416_INPUT_PORT_1 0x01 // For ports 10 to 17 +#define TCA6416_OUTPUT_PORT_0 0x02 // For ports 00 to 07 +#define TCA6416_OUTPUT_PORT_1 0x03 // For ports 10 to 17 +#define TCA6416_POLARITY_INV_PORT_0 0x04 // For ports 00 to 07 +#define TCA6416_POLARITY_INV_PORT_1 0x05 // For ports 10 to 17 +#define TCA6416_CONFIG_PORT_0 0x06 // For ports 00 to 07 +#define TCA6416_CONFIG_PORT_1 0x07 // For ports 10 to 17 + + + +#define TCA6416_INVALID_PORT 0xFF + +#endif //INCLUDED_TCA6416_EXPANDER_REG_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/Makefile new file mode 100644 index 000000000000..9e7fe0bcdb16 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/Makefile @@ -0,0 +1,21 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626 + +obj-y += ds2482_bridge.o +obj-y += ds2482_i2c.o +obj-y += pcf50626_adc.o +obj-y += pcf50626_batterycharger.o +obj-y += pcf50626.o +obj-y += pcf50626_i2c.o +obj-y += pcf50626_interrupt.o +obj-y += pcf50626_rtc.o +obj-y += platform.o diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_bridge.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_bridge.c new file mode 100644 index 000000000000..ecc09f8e6775 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_bridge.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "ds2482_bridge.h" +#include "pcf50626_i2c.h" +#include "ds2482_i2c.h" +#include "pcf50626_reg.h" +#include "ds2482_reg.h" + +NvBool +Ds2482Setup(NvOdmPmuDeviceHandle hDevice) +{ + NvU8 data = 0; + + // One wire I2C bridge + //Device Reset Status + if (!Ds2482OWI2cRead8(hDevice, DS2482_DEVICE_RESET, &data)) + return NV_FALSE; + //NVODMPMU_PRINTF(("Device Reset reg 0x%02x = 0x%02x\n", DS2482_DEVICE_RESET, data)); + + //1-Wire Reset Status + if (!Ds2482OWI2cRead8(hDevice, DS2482_1WIRE_RESET, &data)) + return NV_FALSE; + //NVODMPMU_PRINTF(("1-Wire Reset reg 0x%02x = 0x%02x\n", DS2482_1WIRE_RESET, data)); + + while(1) + { + if (!Ds2482OWI2cWrite8(hDevice, DS2482_READ_DATA_REG_ADDR, DS2482_DEVICE_RESET)) + return NV_FALSE; + + if (!Ds2482OWI2cRead8(hDevice, DS2482_READ_DATA_REG_ADDR, &data)) + return NV_FALSE; + + if (!(data & 0x01)) + break; + } + + + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_bridge.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_bridge.h new file mode 100644 index 000000000000..84111f8a7876 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_bridge.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_DS2482_BRIDGE_H +#define INCLUDED_DS2482_BRIDGE_H + +#include "nvodm_pmu.h" +#include "pcf50626.h" + + +#if defined(__cplusplus) +extern "C" +{ +#endif + +NvBool +Ds2482Setup(NvOdmPmuDeviceHandle hDevice); + +NvBool +Ds2482BatteryPresented( + NvOdmPmuDeviceHandle hDevice, + NvBool *BattPresence); + +#if defined(__cplusplus) +} +#endif + + +#endif // INCLUDED_DS2482_BRIDGE_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_i2c.c new file mode 100644 index 000000000000..09f1194e2a30 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_i2c.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "ds2482_i2c.h" +#include "nvodm_pmu.h" +#include "nvodm_services.h" +#include "ds2482_reg.h" + +NvBool Ds2482OWI2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data) +{ + NvU8 WriteBuffer[2]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Pcf50626PrivData *hPmu = (Pcf50626PrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo; + + WriteBuffer[0] = Addr & 0xFF; + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = DS2482_SLAVE_ADDR; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + DS2482_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + +NvBool Ds2482OWI2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data) +{ + NvU8 ReadBuffer = 0; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Pcf50626PrivData *hPmu = (Pcf50626PrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + ReadBuffer = Addr & 0xFF; + + TransactionInfo[0].Address = DS2482_SLAVE_ADDR; + TransactionInfo[0].Buf = &ReadBuffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + TransactionInfo[1].Address = (DS2482_SLAVE_ADDR | 0x1); + TransactionInfo[1].Buf = &ReadBuffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2, + DS2482_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuOWI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + *Data = ReadBuffer; + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_i2c.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_i2c.h new file mode 100644 index 000000000000..af6ea8c9330e --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_i2c.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_PMU_DS2482_I2C_H +#define INCLUDED_NVODM_PMU_DS2482_I2C_H + +#include "pcf50626.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// Constant definition +#define DS2482_SLAVE_ADDR 0x32 +#define DS2482_I2C_SPEED_KHZ 400 + +// Function declaration +NvBool Ds2482OWI2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data); + +NvBool Ds2482OWI2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data); + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_NVODM_PMU_DS2482_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_reg.h new file mode 100644 index 000000000000..6ce603046918 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/ds2482_reg.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef DS2482_REG_HEADER +#define DS2482_REG_HEADER + +#define DS2482_DEVICE_RESET 0xF0 +#define DS2482_1WIRE_RESET 0xB4 +#define DS2482_STATUS_REG_ADDR 0xF0 +#define DS2482_READ_DATA_REG_ADDR 0xE1 +#define DS2482_CONFIGURATION_REG_ADDR 0xC3 + + +#endif //DS2482_REG_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/nvodm_pmu_pcf50626_supply_info.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/nvodm_pmu_pcf50626_supply_info.h new file mode 100644 index 000000000000..bf46e600401f --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/nvodm_pmu_pcf50626_supply_info.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PCF50626_SUPPLY_INFO_HEADER +#define PCF50626_SUPPLY_INFO_HEADER + +#include "pcf50626.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + + + typedef enum +{ + PCF50626PmuSupply_Invalid = 0x0, + + //DCD1 + PCF50626PmuSupply_DCD1, + + //DCD2 + PCF50626PmuSupply_DCD2, + + //DCUD + PCF50626PmuSupply_DCUD, + + //DCULED + PCF50626PmuSupply_DCULED, + + //RF1REG + PCF50626PmuSupply_RF1REG, + + //RF2REG + PCF50626PmuSupply_RF2REG, + + //RF3REG + PCF50626PmuSupply_RF3REG, + + //RF4REG + PCF50626PmuSupply_RF4REG, + + //D1REG + PCF50626PmuSupply_D1REG, + + //D2REG + PCF50626PmuSupply_D2REG, + + //D3REG + PCF50626PmuSupply_D3REG, + + //D4REG + PCF50626PmuSupply_D4REG, + + //D5REG + PCF50626PmuSupply_D5REG, + + //D6REG + PCF50626PmuSupply_D6REG, + + //D7REG + PCF50626PmuSupply_D7REG, + + //D8REG + PCF50626PmuSupply_D8REG, + + //HCREG + PCF50626PmuSupply_HCREG, + + //IOREG + PCF50626PmuSupply_IOREG, + + //USIMREG + PCF50626PmuSupply_USIMREG, + + //USBREG + PCF50626PmuSupply_USBREG, + + //LCREG + PCF50626PmuSupply_LCREG, + + //VBAT + PCF50626PmuSupply_VBAT, + + PCF50626PmuSupply_Num, + PCF50626PmuSupply_Force32 = 0x7FFFFFFF +} PCF50626PmuSupply; + + +typedef struct PCF50626PmuSupplyInfoRec +{ + PCF50626PmuSupply supply; + PCF50626PmuSupply supplyInput; + NvU8 control1Addr; + NvU8 control2Addr; + NvU8 control3Addr; + NvU8 control4Addr; + + NvU8 dvm1Addr; + NvU8 dvm2Addr; + NvU8 dvm3Addr; + NvU8 dvmTimAddr; + + NvOdmPmuVddRailCapabilities cap; + NvU32 offsetVoltage; + NvU32 turnOnTimeMicroSec; + NvU32 switchTimeMicroSec; +} PCF50626PmuSupplyInfo; + +#if defined(__cplusplus) +} +#endif + +#endif //PCF50626_VOLTAGE_INFO_TABLE_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626.c new file mode 100644 index 000000000000..9272dbdddbc5 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626.c @@ -0,0 +1,938 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_query_discovery.h" +#include "nvodm_query.h" +#include "nvodm_services.h" +#include "pcf50626_i2c.h" +#include "pcf50626.h" +#include "pcf50626_batterycharger.h" +#include "pcf50626_adc.h" +#include "pcf50626_interrupt.h" +#include "pcf50626_supply_info_table.h" + +#ifndef PMU_MAX +#define PMU_MAX(a,b) ((a)<(b)?(b):(a)) +#endif + +#define BATTEMP_CONTROL (0) + +// Board IDs +#define NVODM_PMU_BOARD_ID_E924 0x0918 +#define NVODM_PMU_BOARD_ID_E934 0x0922 + +// SKUs +#define NVODM_PMU_BOARD_SAMSUNG_26_MHZ_OSC 0x0A00 +#define NVODM_PMU_BOARD_HYNIX_12_MHZ_XTAL 0x0A01 + +// h/w configuration +#define CHARGER_CONSTANT_CURRENT_SET_MA (NvU32)(125000/127) +#define MAX_CHARGER_LIMIT_MA 850 + +// This PMU does not have differnet charger programming +// So setting all types of charger limit to the default charger limit +#define SE0_TYPE_CHARGER_LIMIT_MA MAX_CHARGER_LIMIT_MA +#define SE1_TYPE_CHARGER_LIMIT_MA MAX_CHARGER_LIMIT_MA +#define SJ_TYPE_CHARGER_LIMIT_MA MAX_CHARGER_LIMIT_MA +#define SK_TYPE_CHARGER_LIMIT_MA MAX_CHARGER_LIMIT_MA + + +// threshold for battery status. need to fine tune based on battery/system characterisation +#define NVODM_BATTERY_FULL_VOLTAGE_MV 4150 +#define NVODM_BATTERY_HIGH_VOLTAGE_MV 3900 +#define NVODM_BATTERY_LOW_VOLTAGE_MV 3300 +#define NVODM_BATTERY_CRITICAL_VOLTAGE_MV 3100 + +#define NVODM_BATTERY_OVERHEAT_THRESHOLD 70 + + +Pcf50626PrivData *pPrivData; +//Concorde WAR for the USB Host mode +NvBool UsbHostMode; + +#define PMUGUID NV_ODM_GUID('p','c','f','_','p','m','u','0') + + +// Calulate the battery life percentage according to the battery voltage. +static NvU32 +Pcf50626CalulateBatteryLifePercent_int(NvU32 vBatSense); + +#if BATTEMP_CONTROL +// switch off the chargeer if the battery temperature is too high +static NvBool +Pcf50626BatteryTemperatureControl_int( + NvOdmPmuDeviceHandle hDevice, + NvU32 batTemp); +#endif + +// Read the voltage setting from PCF50626 registers +static NvBool +Pcf50626ReadVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts); + +// Write the voltage setting from PCF50626 registers +static NvBool +Pcf50626WriteVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds); + + +void +Pcf50626GetCapabilities( + NvU32 vddRail, + NvOdmPmuVddRailCapabilities* pCapabilities) +{ + NvOdmBoardInfo BoardInfo; + NvBool Status = NV_FALSE; + + NV_ASSERT(pCapabilities); + NV_ASSERT(vddRail < PCF50626PmuSupply_Num); + + *pCapabilities = pcf50626SupplyInfoTable[vddRail].cap; + + if (vddRail == PCF50626PmuSupply_DCD2) + { + Status = NvOdmPeripheralGetBoardInfo(NVODM_PMU_BOARD_ID_E924, &BoardInfo); + if (Status == NV_TRUE) + { + if ((BoardInfo.SKU == NVODM_PMU_BOARD_SAMSUNG_26_MHZ_OSC) || + (BoardInfo.SKU == NVODM_PMU_BOARD_HYNIX_12_MHZ_XTAL)) + { + // Use 1.8v DDR (TO DO: Don't use a magic number here; define this.) + pCapabilities->requestMilliVolts = 1800; + } + } + else + { + Status = NvOdmPeripheralGetBoardInfo(NVODM_PMU_BOARD_ID_E934, &BoardInfo); + if (Status == NV_TRUE) + { + if (BoardInfo.SKU == NVODM_PMU_BOARD_HYNIX_12_MHZ_XTAL) + { + // Use 1.8v DDR (TO DO: Don't use a magic number here; define this.) + pCapabilities->requestMilliVolts = 1800; + } + } + else + { + // Use default DDR voltage (1.925v) + ; + } + } + } +} + + +NvBool Pcf50626Setup(NvOdmPmuDeviceHandle hDevice) +{ + NvOdmIoModule I2cModule = NvOdmIoModule_I2c; + NvU32 I2cInstance = 0; + NvU32 I2cAddress = 0; + NvU32 i = 0; + NvBool status = NV_FALSE; + + const NvOdmPeripheralConnectivity *pConnectivity = + NvOdmPeripheralGetGuid(PMUGUID); + + NV_ASSERT(hDevice); + + + pPrivData = (Pcf50626PrivData*) NvOdmOsAlloc(sizeof(Pcf50626PrivData)); + if (pPrivData == NULL) + { + NVODMPMU_PRINTF(("Error Allocating Pcf50626PrivData. \n")); + return NV_FALSE; + } + NvOdmOsMemset(pPrivData, 0, sizeof(Pcf50626PrivData)); + hDevice->pPrivate = pPrivData; + + ((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable = NvOdmOsAlloc(sizeof(NvU32) * PCF50626PmuSupply_Num); + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable == NULL) + { + NVODMPMU_PRINTF(("Error Allocating RefCntTable. \n")); + goto fail; + } + + // memset + for (i = 0; i < PCF50626PmuSupply_Num; i++) + { + ((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[i] = 0; + } + + + if (pConnectivity != NULL) // PMU is in database + { + for (i = 0; i < pConnectivity->NumAddress; i ++) + { + if (pConnectivity->AddressList[i].Interface == NvOdmIoModule_I2c_Pmu) + { + I2cModule = NvOdmIoModule_I2c_Pmu; + I2cInstance = pConnectivity->AddressList[i].Instance; + I2cAddress = pConnectivity->AddressList[i].Address; + break; + } + } + + NV_ASSERT(I2cModule == NvOdmIoModule_I2c_Pmu); + NV_ASSERT(I2cAddress != 0); + + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmI2C = NvOdmI2cOpen(I2cModule, I2cInstance); + if (!((Pcf50626PrivData*)hDevice->pPrivate)->hOdmI2C) + { + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: Error Open I2C device. \n")); + NVODMPMU_PRINTF(("[NVODM PMU]Please check PMU device I2C settings. \n")); + goto fail; + } + + ((Pcf50626PrivData*)hDevice->pPrivate)->DeviceAddr = I2cAddress; + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice = NvOdmServicesPmuOpen(); + if (!((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice) + { + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: Error Open PMU Odm service. \n")); + goto fail; + } + } + else + { + // if PMU is not presented in the database, then the platform is PMU-less. + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: The system did not doscover PMU fromthe data base. \n")); + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: If this is not intended, please check the peripheral database for PMU settings. \n")); + goto fail; + } + + if (!Pcf50626BatteryChargerSetup(hDevice)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: Pcf50626BatteryChargerSetup() failed. \n")); + goto fail; + } + + //Check battery presence + if (!Pcf50626BatteryChargerCBCMainBatt(hDevice,&((Pcf50626PrivData*)hDevice->pPrivate)->battPresence)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: Pcf50626BatteryChargerCBCMainBatt() failed. \n")); + goto fail; + } + + // The interrupt assumes not supported until pcf50626InterruptHandler() is called. + ((Pcf50626PrivData*)hDevice->pPrivate)->pmuInterruptSupported = NV_FALSE; + + // setup the interrupt any way. + if (!Pcf50626SetupInterrupt(hDevice, &((Pcf50626PrivData*)hDevice->pPrivate)->pmuStatus)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: Pcf50626SetupInterrupt() failed. \n")); + goto fail; + } + + // Check battery Fullness + if (((Pcf50626PrivData*)hDevice->pPrivate)->battPresence == NV_TRUE) + { + if (!Pcf50626BatteryChargerCBCBattFul(hDevice,&status)) + { + NVODMPMU_PRINTF(("[NVODM PMU]Pcf50626Setup: Pcf50626BatteryChargerCBCBattFul() failed. \n")); + goto fail; + } + + ((Pcf50626PrivData*)hDevice->pPrivate)->pmuStatus.batFull = status; + } + else + { + ((Pcf50626PrivData*)hDevice->pPrivate)->pmuStatus.batFull = NV_FALSE; + } + + return NV_TRUE; + +fail: + Pcf50626Release(hDevice); + return NV_FALSE; + + +} + +void Pcf50626Release(NvOdmPmuDeviceHandle hDevice) +{ + if (hDevice->pPrivate != NULL) + { + if (((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice != NULL) + { + NvOdmServicesPmuClose(((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice); + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice = NULL; + } + + if (((Pcf50626PrivData*)hDevice->pPrivate)->hOdmI2C != NULL) + { + NvOdmI2cClose(((Pcf50626PrivData*)hDevice->pPrivate)->hOdmI2C); + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmI2C = NULL; + } + + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable != NULL) + { + NvOdmOsFree(((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable); + ((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable = NULL; + } + + NvOdmOsFree(hDevice->pPrivate); + hDevice->pPrivate = NULL; + } +} + + +NvBool +Pcf50626GetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + NV_ASSERT(hDevice); + NV_ASSERT(pMilliVolts); + NV_ASSERT(vddRail < PCF50626PmuSupply_Num); + + if(! Pcf50626ReadVoltageReg(hDevice, vddRail,pMilliVolts)) + return NV_FALSE; + + return NV_TRUE; +} + + +NvBool +Pcf50626SetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + NvU8 data = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(vddRail < PCF50626PmuSupply_Num); + + if (pcf50626SupplyInfoTable[vddRail].cap.OdmProtected == NV_TRUE) + { + NVODMPMU_PRINTF(("[NVODM PMU] Pcf50626SetVoltage Warning: The voltage is protected and can not be set: %d.\n", vddRail)); + return NV_TRUE; + } + + if ((MilliVolts == ODM_VOLTAGE_OFF) || + ((MilliVolts <= pcf50626SupplyInfoTable[vddRail].cap.MaxMilliVolts) + && (MilliVolts >= pcf50626SupplyInfoTable[vddRail].cap.MinMilliVolts))) + { + if (! Pcf50626WriteVoltageReg(hDevice, vddRail, MilliVolts, pSettleMicroSeconds)) + return NV_FALSE; + } + else + { + NVODMPMU_PRINTF(("[NVODM OPMU] Pcf50626SetVoltage Error: The required voltage is not supported..\n")); + return NV_FALSE; + } + + if (vddRail == PCF50626PmuSupply_DCUD) + { + // VBUs rail is enabled bydefault, so no need to enable set voltage. + // "Millivolts" field is used as Enable or disable VBUS GPIO + if (MilliVolts == ODM_VOLTAGE_OFF) + { + data = 0x7; // all bits to low fixed 0 + } + else + { + data = 0x0; // default reset value high impedence state + } + if (!Pcf50626I2cWrite8(hDevice,PCF50626_GPIO5C1_ADDR, data)) + return NV_FALSE; + } + return NV_TRUE; +} + +static NvBool +Pcf50626ReadVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + NvU32 milliVolts = 0; + NvU8 data = 0; + const PCF50626PmuSupplyInfo *pSupplyInfo = &pcf50626SupplyInfoTable[vddRail]; + + NV_ASSERT(pSupplyInfo->supply == (PCF50626PmuSupply)vddRail); + + if(! Pcf50626I2cRead8(hDevice, pSupplyInfo->control2Addr, &data)) + return NV_FALSE; + + data >>= PCF50626_C2_OPMOD_SHIFT; + if (!data) //OFF + milliVolts = 0; + else + { + if (!Pcf50626I2cRead8(hDevice, pSupplyInfo->control1Addr, &data)) + return NV_FALSE; + + if ( (vddRail == PCF50626PmuSupply_DCD1) + |(vddRail == PCF50626PmuSupply_DCD2) + |(vddRail == PCF50626PmuSupply_DCUD)) + { + milliVolts = pSupplyInfo->offsetVoltage + pSupplyInfo->cap.StepMilliVolts * ((NvU32)(data & 0x7F)); + } + else if (vddRail == PCF50626PmuSupply_LCREG) + { + milliVolts = pSupplyInfo->offsetVoltage + pSupplyInfo->cap.StepMilliVolts * ((NvU32)(data & 0x7F) >> 1); + } + else + { + milliVolts = pSupplyInfo->offsetVoltage + pSupplyInfo->cap.StepMilliVolts * ((NvU32)(data & 0x7F) >> 2); + } + } + + *pMilliVolts = milliVolts; + return NV_TRUE; +} + + +static NvBool +Pcf50626WriteVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + NvU8 data = 0; + NvU8 reg = 0; + NvU32 settleTime = 0; + + const PCF50626PmuSupplyInfo* pSupplyInfo = &pcf50626SupplyInfoTable[vddRail]; + const PCF50626PmuSupplyInfo* pSupplyInputInfo = &pcf50626SupplyInfoTable[pSupplyInfo->supplyInput]; + + NV_ASSERT(pSupplyInfo->supply == (PCF50626PmuSupply)vddRail); + + // Require to turn off the supply + if (MilliVolts == ODM_VOLTAGE_OFF) + { + // check if the supply can be turned off + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] == 1) + { + // turn off the supply + data = PCF50626_C2_OPMOD_OFF; + NvOdmServicesPmuSetSocRailPowerState( + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice, pSupplyInfo->supply, NV_FALSE); + if (!Pcf50626I2cWrite8(hDevice, pSupplyInfo->control2Addr, data)) + return NV_FALSE; + } + + //check if the supply input can be turned off + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInputInfo->supply] == 1) + { + // turn off the supply input + data = PCF50626_C2_OPMOD_OFF; + NvOdmServicesPmuSetSocRailPowerState( + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice, pSupplyInputInfo->supply, NV_FALSE); + if(! Pcf50626I2cWrite8(hDevice, pSupplyInputInfo->control2Addr, data)) + return NV_FALSE; + } + + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] != 0) + ((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] --; + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInputInfo->supply] != 0) + ((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInputInfo->supply] --; + + settleTime = PMU_MAX (pSupplyInfo->switchTimeMicroSec, pSupplyInputInfo->switchTimeMicroSec); + + if (pSettleMicroSeconds != NULL) + *pSettleMicroSeconds = settleTime; + else + NvOdmOsWaitUS(settleTime); + return NV_TRUE; + } + + // set voltage + if ( (vddRail == PCF50626PmuSupply_HCREG) || + ((vddRail == PCF50626PmuSupply_LCREG) && + (MilliVolts > PCF50626_LCREGOUT_VOLTAGE_RESCHANGE_MV))) + { + data = (NvU8)((MilliVolts - pSupplyInfo->offsetVoltage) / pSupplyInfo->cap.StepMilliVolts); + if (data % 2) + data --; + } + else + { + data = (NvU8)((MilliVolts - pSupplyInfo->offsetVoltage) / pSupplyInfo->cap.StepMilliVolts); + } + + reg = 0; + reg &= ~PCF50626_C1_OUTPUT_MASK; + if ( (pSupplyInfo->supply == PCF50626PmuSupply_DCD1) + |(pSupplyInfo->supply == PCF50626PmuSupply_DCD2) + |(pSupplyInfo->supply == PCF50626PmuSupply_DCUD)) + { + reg |= data; + } + else if (pSupplyInfo->supply == PCF50626PmuSupply_LCREG) + { + reg |= (data << 1); + } + else + { + reg |= (data << 2); + } + + if(! Pcf50626I2cWrite8(hDevice, pSupplyInfo->control1Addr, reg)) + return NV_FALSE; + + settleTime = pSupplyInfo->switchTimeMicroSec; + + // turn on supply + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] == 0) + { + if (! Pcf50626I2cRead8(hDevice, pSupplyInfo->control2Addr, &data)) + return NV_FALSE; + data >>= PCF50626_C2_OPMOD_SHIFT; + if (!data) + { + // Require to turn on the supply + data = PCF50626_C2_OPMOD_ON; + NvOdmServicesPmuSetSocRailPowerState( + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice, pSupplyInfo->supply, NV_TRUE); + if(! Pcf50626I2cWrite8(hDevice, pSupplyInfo->control2Addr, data)) + return NV_FALSE; + + settleTime += pSupplyInfo->turnOnTimeMicroSec; + } + } + + // turn on supply input if necessary + if (((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInputInfo->supply] == 0) + { + if(! Pcf50626I2cRead8(hDevice, pSupplyInputInfo->control2Addr, &data)) + return NV_FALSE; + + data >>= PCF50626_C2_OPMOD_SHIFT; + if (!data) + { + // Require to turn on the supply input + data = PCF50626_C2_OPMOD_ON; + NvOdmServicesPmuSetSocRailPowerState( + ((Pcf50626PrivData*)hDevice->pPrivate)->hOdmPmuSevice, pSupplyInputInfo->supply, NV_TRUE); + if(! Pcf50626I2cWrite8(hDevice,pSupplyInputInfo->control2Addr, data)) + return NV_FALSE; + + settleTime += pSupplyInputInfo->turnOnTimeMicroSec; + } + } + + ((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInputInfo->supply] ++; + ((Pcf50626PrivData*)hDevice->pPrivate)->supplyRefCntTable[pSupplyInfo->supply] ++; + + + if (pSettleMicroSeconds != NULL) + *pSettleMicroSeconds = settleTime; + else + NvOdmOsWaitUS(settleTime); + + return NV_TRUE; +} + +NvBool +Pcf50626GetAcLineStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuAcLineStatus *pStatus) +{ + NvBool acLineStatus = NV_FALSE; + + NV_ASSERT(hDevice); + NV_ASSERT(pStatus); + + // check if charger presents + if (((Pcf50626PrivData*)hDevice->pPrivate)->battPresence == NV_FALSE) + { + *pStatus = NvOdmPmuAcLine_Online; + return NV_TRUE; + } + + if (((Pcf50626PrivData*)hDevice->pPrivate)->pmuInterruptSupported == NV_TRUE) + { + if (( ((Pcf50626PrivData*)hDevice->pPrivate)->pmuStatus.mChgPresent == NV_TRUE ) && + (UsbHostMode == NV_FALSE)) + { + *pStatus = NvOdmPmuAcLine_Online; + acLineStatus = NV_TRUE; + } + else + { + *pStatus = NvOdmPmuAcLine_Offline; + acLineStatus = NV_FALSE; + } + } + else + { + // battery is present, now check if charger presents + if (!Pcf50626BatteryChargerMainChgPresent(hDevice, &acLineStatus)) + { + NVODMPMU_PRINTF(("[NVODM PMU] Pcf50626GetAcLineStatus: Error in checking main charger presence.\n")); + return NV_FALSE; + } + + if ((acLineStatus == NV_TRUE) && (UsbHostMode == NV_FALSE)) + *pStatus = NvOdmPmuAcLine_Online; + else + *pStatus = NvOdmPmuAcLine_Offline; + } + return NV_TRUE; +} + + +NvBool +Pcf50626GetBatteryStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU8 *pStatus) +{ + NvU8 status = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pStatus); + NV_ASSERT(batteryInst <= NvOdmPmuBatteryInst_Num); + + if (batteryInst == NvOdmPmuBatteryInst_Main) + { + if (((Pcf50626PrivData*)hDevice->pPrivate)->battPresence == NV_TRUE) + { + NvOdmPmuAcLineStatus stat = NvOdmPmuAcLine_Offline; + NvU32 VBatSense = 0; + if (!Pcf50626GetAcLineStatus(hDevice, &stat)) + return NV_FALSE; + + if (stat == NvOdmPmuAcLine_Online) + { + if (((Pcf50626PrivData*)hDevice->pPrivate)->pmuInterruptSupported == NV_TRUE) + { + if (((Pcf50626PrivData*)hDevice->pPrivate)->pmuStatus.batFull == NV_FALSE) + status = NVODM_BATTERY_STATUS_CHARGING; + } + else + { + NvBool batFull = NV_FALSE; + if (!Pcf50626BatteryChargerCBCBattFul(hDevice, &batFull)) + return NV_FALSE; + if (batFull == NV_FALSE) + status = NVODM_BATTERY_STATUS_CHARGING; + } + } + + // Get VBatSense + if (!Pcf50626AdcVBatSenseRead(hDevice, &VBatSense)) + return NV_FALSE; + + if (VBatSense > NVODM_BATTERY_HIGH_VOLTAGE_MV) + status |= NVODM_BATTERY_STATUS_HIGH; + else if ((VBatSense < NVODM_BATTERY_LOW_VOLTAGE_MV)&& + (VBatSense > NVODM_BATTERY_CRITICAL_VOLTAGE_MV)) + status |= NVODM_BATTERY_STATUS_LOW; + else if (VBatSense <= NVODM_BATTERY_CRITICAL_VOLTAGE_MV) + status |= NVODM_BATTERY_STATUS_CRITICAL; + + } + else + { + /* Battery is actually not present */ + status = NVODM_BATTERY_STATUS_NO_BATTERY; + } + + *pStatus = status; + } + + else + { + *pStatus = NVODM_BATTERY_STATUS_UNKNOWN; + } + + return NV_TRUE; +} + +NvBool +Pcf50626GetBatteryData( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryData *pData) +{ + NvOdmPmuBatteryData batteryData; + batteryData.batteryAverageCurrent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryAverageInterval = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryCurrent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryLifePercent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryLifeTime = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryMahConsumed = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryTemperature = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryVoltage = NVODM_BATTERY_DATA_UNKNOWN; + + + NV_ASSERT(hDevice); + NV_ASSERT(pData); + NV_ASSERT(batteryInst <= NvOdmPmuBatteryInst_Num); + + + if (batteryInst == NvOdmPmuBatteryInst_Main) + { + NvU32 VBatSense = 0; + NvU32 VBatTemp = 0; + + if (((Pcf50626PrivData*)hDevice->pPrivate)->battPresence == NV_TRUE) + { + /* retrieve Battery voltage and temperature */ + + // Get VBatSense + if (!Pcf50626AdcVBatSenseRead(hDevice, &VBatSense)) + { + NVODMPMU_PRINTF(("[NVODM PMU] Pcf50626GetBatteryData: Error reading VBATSense. \n")); + return NV_FALSE; + } + + // Get VBatTemp + if (!Pcf50626AdcVBatTempRead(hDevice, &VBatTemp)) + { + NVODMPMU_PRINTF(("[NVODM PMU] Pcf50626GetBatteryData: Error reading VBATSense. \n")); + return NV_FALSE; + } + + batteryData.batteryLifePercent = + Pcf50626CalulateBatteryLifePercent_int(VBatSense); + +#if BATTEMP_CONTROL + if (!Pcf50626BatteryTemperatureControl_int(hDevice, VBatTemp)) + { + NVODMPMU_PRINTF(("[NVODM PMU] Pcf50626GetBatteryData: Error in battery ctemperature controls. \n")); + return NV_FALSE; + } +#endif + + batteryData.batteryVoltage = VBatSense; + batteryData.batteryTemperature = Pcf50626BatteryTemperature(VBatSense, + VBatTemp); + } + + *pData = batteryData; + } + else + { + *pData = batteryData; + } + + return NV_TRUE; +} + +void +Pcf50626GetBatteryFullLifeTime( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU32 *pLifeTime) +{ + *pLifeTime = NVODM_BATTERY_DATA_UNKNOWN; +} + +void +Pcf50626GetBatteryChemistry( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryChemistry *pChemistry) +{ + //return fixed data for now. + *pChemistry = NvOdmPmuBatteryChemistry_LION; +} + +NvBool +Pcf50626SetChargingCurrent( +NvOdmPmuDeviceHandle hDevice, +NvOdmPmuChargingPath chargingPath, +NvU32 chargingCurrentLimitMa, +NvOdmUsbChargerType chargerType) +{ + NvU8 data = 0; + NV_ASSERT(hDevice); + + // if no battery, then do nothing + if (((Pcf50626PrivData*)hDevice->pPrivate)->battPresence == NV_FALSE) + return NV_TRUE; + //Concorde s/w WAR for USB Host mode + if (chargingCurrentLimitMa == NVODM_USB_HOST_MODE_LIMIT) + { + chargingCurrentLimitMa = 0; // turn off the charging path + UsbHostMode = NV_TRUE; + } + else + { + UsbHostMode = NV_FALSE; + } + + // if requested current is more than max supported current then limit to supported + if ( chargingCurrentLimitMa > MAX_CHARGER_LIMIT_MA ) + chargingCurrentLimitMa = MAX_CHARGER_LIMIT_MA; + + if (chargingPath == NvOdmPmuChargingPath_UsbBus) + { + switch (chargerType) + { + case NvOdmUsbChargerType_SJ: + chargingCurrentLimitMa = SJ_TYPE_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_SK: + chargingCurrentLimitMa = SK_TYPE_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_SE1: + chargingCurrentLimitMa = SE1_TYPE_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_SE0: + chargingCurrentLimitMa = SE0_TYPE_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_UsbHost: + default: + // USB Host based charging, nothing to do. Just pass current limit to PMU. + break; + } + } + + data = (NvU8)((( chargingCurrentLimitMa << 8 ) - chargingCurrentLimitMa ) + / CHARGER_CONSTANT_CURRENT_SET_MA ); + + if (!Pcf50626I2cWrite8(hDevice, PCF50626_CBCC3_ADDR, data)) + return NV_FALSE; + + // turn off the charger path if the requested current limit is 0mA. Turn on the path otherwise. + data = 0; + if ( !Pcf50626I2cRead8(hDevice, PCF50626_CBCC1_ADDR, &data) ) + return NV_FALSE; + + if ( chargingCurrentLimitMa == 0 ) + data &= ~(PCF50626_CBCC1_CHGENA_MASK); //off + else + data |= PCF50626_CBCC1_CHGENA_MASK; //on + + if ( !Pcf50626I2cWrite8(hDevice, PCF50626_CBCC1_ADDR, data) ) + return NV_FALSE; + + + data = 0; + if ( !Pcf50626I2cRead8(hDevice, PCF50626_CBCC2_ADDR, &data) ) + return NV_FALSE; + if ( chargingCurrentLimitMa == 0 ) + { + //enable USB suspend mode regardless of the SCUSB pin state + data |= (PCF50626_CBCC2_SUSPENA_MASK << PCF50626_CBCC2_SUSPENA_SHIFT); + } + else + { + //disable USB suspend mode regardless of the SCUSB pin state + data &= ~(PCF50626_CBCC2_SUSPENA_MASK << PCF50626_CBCC2_SUSPENA_SHIFT); + } + if ( !Pcf50626I2cWrite8(hDevice, PCF50626_CBCC2_ADDR, data) ) + return NV_FALSE; + + //Dump the register value for debug purpose, can be commented out is undesired.. + NVODMPMU_PRINTF(("NvOdmPmuSetChargingCurrent: \n")); + NVODMPMU_PRINTF((" chargingCurrentLimitMa:%d\n", chargingCurrentLimitMa)); + + if ( !Pcf50626I2cRead8(hDevice, PCF50626_CBCC1_ADDR, &data) ) + return NV_FALSE; + NVODMPMU_PRINTF((" CBCC1:0x%02x\n", data)); + + if ( !Pcf50626I2cRead8(hDevice, PCF50626_CBCC2_ADDR, &data) ) + return NV_FALSE; + NVODMPMU_PRINTF((" CBCC2:0x%02x\n", data)); + + if ( !Pcf50626I2cRead8(hDevice, PCF50626_CBCC3_ADDR, &data) ) + return NV_FALSE; + NVODMPMU_PRINTF((" CBCC3:0x%02x\n", data)); + + return NV_TRUE; +} + +void Pcf50626InterruptHandler( NvOdmPmuDeviceHandle hDevice) +{ + // If the interrupt handle is called, the interrupt is supported. + ((Pcf50626PrivData*)hDevice->pPrivate)->pmuInterruptSupported = NV_TRUE; + + Pcf50626InterruptHandler_int(hDevice, &((Pcf50626PrivData*)hDevice->pPrivate)->pmuStatus); +} + + +static NvU32 Pcf50626CalulateBatteryLifePercent_int(NvU32 vBatSense) +{ + NvU32 lifePerc = 0; + NvU32 vbat = vBatSense; + + if (vbat < NVODM_BATTERY_CRITICAL_VOLTAGE_MV) + vbat = NVODM_BATTERY_CRITICAL_VOLTAGE_MV; + + // using the linear mapping between the battery voltage and the life percentage. + lifePerc = ( ( vbat - NVODM_BATTERY_CRITICAL_VOLTAGE_MV ) * 50 + / ( NVODM_BATTERY_FULL_VOLTAGE_MV - NVODM_BATTERY_CRITICAL_VOLTAGE_MV ) ) << 1; + + if (lifePerc > 100) + lifePerc = 100; + + return lifePerc; +} + + +#if BATTEMP_CONTROL +static NvBool Pcf50626BatteryTemperatureControl_int( + NvOdmPmuDeviceHandle hDevice, + NvU32 batTemp) +{ + NvU8 data = 0; + + //turn off the charger if the battery is overheating. + if ( batTemp > NVODM_BATTERY_OVERHEAT_THRESHOLD ) + { + if (!Pcf50626I2cRead8(hDevice, PCF50626_CBCC1_ADDR, &data)) + return NV_FALSE; + + data &= 0xFE; + if (!Pcf50626I2cWrite8(hDevice, PCF50626_CBCC1_ADDR, data)) + return NV_FALSE; + } + // turn it on otherwise + else + { + if (!Pcf50626I2cRead8(hDevice, PCF50626_CBCC1_ADDR, &data)) + return NV_FALSE; + + data |= 0x01; + if (!Pcf50626I2cWrite8(hDevice, PCF50626_CBCC1_ADDR, data)) + return NV_FALSE; + } + + return NV_TRUE; +} +#endif + + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626.h new file mode 100644 index 000000000000..2325fb75a9d2 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_PMU_PCF50626_H +#define INCLUDED_PMU_PCF50626_H + +#include "nvodm_pmu.h" +#include"pmu_hal.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + + +#if (NV_DEBUG) +#define NVODMPMU_PRINTF(x) NvOdmOsDebugPrintf x +#else +#define NVODMPMU_PRINTF(x) +#endif + + +typedef struct Pcf50626StatusRec +{ + /* Low Battery voltage detected by BVM */ + NvBool lowBatt; + + /* PMU high temperature */ + NvBool highTemp; + + /* charger switch from CC mode to CV mode */ + NvBool chgCcToCv; + + /* Main charger Presents */ + NvBool mChgPresent; + + /* battery Full */ + NvBool batFull; + +} Pcf50626Status; + + + +typedef struct +{ + /* The handle to the I2C */ + NvOdmServicesI2cHandle hOdmI2C; + + /* The odm pmu service handle */ + NvOdmServicesPmuHandle hOdmPmuSevice; + + /* the PMU I2C device Address */ + NvU32 DeviceAddr; + + /* the PMU status */ + Pcf50626Status pmuStatus; + + /* battery presence */ + NvBool battPresence; + + /* PMU interrupt support enabled */ + NvBool pmuInterruptSupported; + + + /* The ref cnt table of the power supplies */ + NvU32 *supplyRefCntTable; + +}Pcf50626PrivData; + + +NvBool +Pcf50626Setup(NvOdmPmuDeviceHandle hDevice); + +void +Pcf50626Release(NvOdmPmuDeviceHandle hDevice); + +NvBool +Pcf50626GetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts); + +NvBool +Pcf50626SetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds); + +void +Pcf50626GetCapabilities( + NvU32 vddRail, + NvOdmPmuVddRailCapabilities* pCapabilities); + + +NvBool +Pcf50626GetAcLineStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuAcLineStatus *pStatus); + + +NvBool +Pcf50626GetBatteryStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU8 *pStatus); + +NvBool +Pcf50626GetBatteryData( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryData *pData); + +void +Pcf50626GetBatteryFullLifeTime( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU32 *pLifeTime); + +void +Pcf50626GetBatteryChemistry( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryChemistry *pChemistry); + +NvBool +Pcf50626SetChargingCurrent( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuChargingPath chargingPath, + NvU32 chargingCurrentLimitMa, + NvOdmUsbChargerType ChargerType); + +void Pcf50626InterruptHandler( NvOdmPmuDeviceHandle hDevice); + +#if defined(__cplusplus) +} +#endif + + +#endif // INCLUDED_PMU_PCF50626_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_adc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_adc.c new file mode 100644 index 000000000000..95347fa42cd7 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_adc.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "pcf50626_adc.h" +#include "pcf50626_i2c.h" +#include "pcf50626_reg.h" +//#include "pcf50626_supply_info.h" + +#define ADC_CONVERSION_DELAY_USEC 70 +#define ADC_CONVERSION_TIMEOUT_USEC 500 +#define ADC_CONVERSION_VOLTAGE_RANGE 2000 +#define ADC_CONVERSION_DIVIDOR 3 +#define ADC_CONVERSION_PRECISION 10 +#define ADC_CONVERSION_SUB_OFFSET 2250 + + +static NvBool +Pcf50626AdcIn1Read(NvOdmPmuDeviceHandle hDevice, NvU32 *volt); + +static NvBool +Pcf50626AdcIn2Read(NvOdmPmuDeviceHandle hDevice, NvU32 *volt); + + +/* read voltage from VBATSENSE */ +NvBool +Pcf50626AdcVBatSenseRead(NvOdmPmuDeviceHandle hDevice, NvU32 *volt) +{ + return Pcf50626AdcIn1Read(hDevice, volt); +} + +static NvBool +Pcf50626AdcIn1Read(NvOdmPmuDeviceHandle hDevice, NvU32 *volt) +{ + + NvU32 timeout = 0; + NvU8 dataS1 = 0; + NvU8 dataS3 = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(volt); + + // Turn off GPIO7 + if(! Pcf50626I2cWrite8(hDevice, PCF50626_GPIO7C1_ADDR, 0x0)) + return NV_FALSE; + + + //ADCC3 - Division sel + if(! Pcf50626I2cWrite8(hDevice, PCF50626_ADCC3_ADDR, PCF50626_ADCC3_RESET)) + return NV_FALSE; + + + //ADCC1 - Resolustion, Mux Sel, Avg sel + if(! Pcf50626I2cWrite8(hDevice, PCF50626_ADCC1_ADDR, 0x0C)) + return NV_FALSE; + + // Start Converstion + if(! Pcf50626I2cWrite8(hDevice, PCF50626_ADCC1_ADDR, 0x0D)) + return NV_FALSE; + + // Wait for conversion + NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + + // make sure the conversion is completed, or timeout. + while (timeout < ADC_CONVERSION_TIMEOUT_USEC) + { + if(! Pcf50626I2cRead8(hDevice, PCF50626_ADCS3_ADDR, &dataS3)) + return NV_FALSE; + + if (dataS3 & 0x80) + break; + + NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + timeout += ADC_CONVERSION_DELAY_USEC; + } + + if (timeout >= ADC_CONVERSION_TIMEOUT_USEC) + { + NVODMPMU_PRINTF(("ADC conversion timeout.\n")); + return NV_FALSE; + } + + // read the conversion result + if (!Pcf50626I2cRead8(hDevice, PCF50626_ADCS1_ADDR, &dataS1)) + return NV_FALSE; + + // Get result + *volt = (((NvU32)((dataS1 << 2) | (dataS3 & 0x03))) * + ADC_CONVERSION_VOLTAGE_RANGE * ADC_CONVERSION_DIVIDOR) + >> ADC_CONVERSION_PRECISION; + + return NV_TRUE; +} + + + +/* read bat temperature voltage from ADC2 */ +NvBool +Pcf50626AdcVBatTempRead(NvOdmPmuDeviceHandle hDevice, NvU32 *volt) +{ + return Pcf50626AdcIn2Read(hDevice, volt); +} + +static NvBool +Pcf50626AdcIn2Read(NvOdmPmuDeviceHandle hDevice, NvU32 *volt) +{ + NvU32 timeout = 0; + NvU8 dataS1 = 0; + NvU8 dataS3 = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(volt); + + // Turn off GPIO7 + if(! Pcf50626I2cWrite8(hDevice, PCF50626_GPIO7C1_ADDR, 0x0)) + return NV_FALSE; + + + //ADCC3 - Division sel + if(! Pcf50626I2cWrite8(hDevice, PCF50626_ADCC3_ADDR, PCF50626_ADCC3_RESET)) + return NV_FALSE; + + + //ADCC1 - Resolustion, Mux Sel, Avg sel + if(! Pcf50626I2cWrite8(hDevice, PCF50626_ADCC1_ADDR, 0x2C)) + return NV_FALSE; + + // Start Converstion + if(! Pcf50626I2cWrite8(hDevice, PCF50626_ADCC1_ADDR, 0x2D)) + return NV_FALSE; + + // Wait for conversion + NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + + // make sure the conversion is completed, or timeout. + while (timeout < ADC_CONVERSION_TIMEOUT_USEC) + { + if(! Pcf50626I2cRead8(hDevice, PCF50626_ADCS3_ADDR, &dataS3)) + return NV_FALSE; + + if (dataS3 & 0x80) + break; + + NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + timeout += ADC_CONVERSION_DELAY_USEC; + } + + if (timeout >= ADC_CONVERSION_TIMEOUT_USEC) + { + NVODMPMU_PRINTF(("ADC conversion timeout.\n")); + return NV_FALSE; + } + + // read the conversion result + if (!Pcf50626I2cRead8(hDevice, PCF50626_ADCS1_ADDR, &dataS1)) + return NV_FALSE; + + // Get result + *volt = (((NvU32)((dataS1 << 2) | (dataS3 & 0x03))) * + ADC_CONVERSION_VOLTAGE_RANGE * ADC_CONVERSION_DIVIDOR) + >> ADC_CONVERSION_PRECISION; + + return NV_TRUE; +} + + + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_adc.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_adc.h new file mode 100644 index 000000000000..e5022c449289 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_adc.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_PCF50626_ADC_HEADER +#define INCLUDED_PCF50626_ADC_HEADER + + +/* the ADC is used for battery voltage conversion */ +#include "pcf50626.h" + + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* read voltage from VBATSENSE */ + +NvBool +Pcf50626AdcVBatSenseRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt); + + +/* read bat temperature voltage from ADC2 */ +NvBool +Pcf50626AdcVBatTempRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt); + +/* Calculate the battery temperature */ +NvU32 Pcf50626BatteryTemperature( + NvU32 VBatSense, + NvU32 VBatTemp); + + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_PCF50626_ADC_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_batterycharger.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_batterycharger.c new file mode 100644 index 000000000000..814d12319dd5 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_batterycharger.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "pcf50626_batterycharger.h" +#include "pcf50626_adc.h" +#include "pcf50626_i2c.h" +#include "pcf50626_reg.h" + + +/* Get battery Voltage */ +NvBool +Pcf50626BatteryChargerGetVoltage(NvOdmPmuDeviceHandle hDevice, NvU32 *res) +{ + NvU32 volt = 0; + ///TODO: check on HW to see the relation between adc output and the voltage. for now, assume they are the same. + if(! Pcf50626AdcVBatSenseRead(hDevice,&volt)) + return NV_FALSE; + + *res = volt; + return NV_TRUE; +} + + + +/* check OnKey Level */ +NvBool +Pcf50626BatteryChargerOnKeyStatus(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_OOCS_ADDR, &data)) + return NV_FALSE + ; + data = (data >> PCF50626_OOCS_ONKEY_SHIFT) & PCF50626_OOCS_ONKEY_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + + return NV_TRUE; +} + +/* check OnKey Level */ +NvBool +Pcf50626BatteryChargerRec1Status(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_OOCS_ADDR, &data)) + return NV_FALSE; + data = (data >> PCF50626_OOCS_REC1_SHIFT) & PCF50626_OOCS_REC1_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + + return NV_TRUE; +} + +/* check battery status */ +NvBool +Pcf50626BatteryChargerBattStatus(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_OOCS_ADDR, &data)) + return NV_FALSE; + data = (data >> PCF50626_OOCS_BATOK_SHIFT) & PCF50626_OOCS_BATOK_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + + return NV_TRUE; +} + +/* check main charger status */ +NvBool +Pcf50626BatteryChargerMainChgPresent(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_OOCS_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_OOCS_MCHGOK_SHIFT) & PCF50626_OOCS_MCHGOK_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + + +/* check USB charger status */ +NvBool +Pcf50626BatteryChargerUsbChgPresent(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_OOCS_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_OOCS_UCHGOK_SHIFT) & PCF50626_OOCS_UCHGOK_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + + +/* check temparature status */ +NvBool +Pcf50626BatteryChargerTempStatus(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_OOCS_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_OOCS_TEMPOK_SHIFT) & PCF50626_OOCS_TEMPOK_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + +/* check CBC batt_ful status */ +NvBool +Pcf50626BatteryChargerCBCBattFul(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS1_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS1_BATTFUL_SHIFT) & PCF50626_CBCS1_BATTFUL_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + + +/* check CBC thermal limit activation status */ +NvBool +Pcf50626BatteryChargerCBCTlimStatus(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS1_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS1_TLIMIT_SHIFT) & PCF50626_CBCS1_TLIMIT_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + +/* check CBC batt_ful status */ +NvBool +Pcf50626BatteryChargerCBCWdExpired(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS1_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS1_WDEXP_SHIFT) & PCF50626_CBCS1_WDEXP_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + + +/* check CBC charger current status */ +NvBool +Pcf50626BatteryChargerCBCChgCurStatus(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS1_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS1_ILIMIT_SHIFT) & PCF50626_CBCS1_ILIMIT_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + +/* check CBC charger voltage status */ +NvBool +Pcf50626BatteryChargerCBCChgVoltStatus(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS1_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS1_VLIMIT_SHIFT) & PCF50626_CBCS1_VLIMIT_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + +/* check CBC charger resume status */ +NvBool +Pcf50626BatteryChargerCBCChgResStatus(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS1_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS1_RESSTAT_SHIFT) & PCF50626_CBCS1_RESSTAT_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + + +/* check USB suspend status */ +NvBool +Pcf50626BatteryChargerCBCUsbSuspStat(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS2_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS2_USBSUSPSTAT_SHIFT) & PCF50626_CBCS2_USBSUSPSTAT_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + +/* check charger over-voltage protection status */ +NvBool +Pcf50626BatteryChargerCBCChgOvpStat(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU8 data = 0; + + if(! Pcf50626I2cRead8(hDevice, PCF50626_CBCS2_ADDR, &data)) + return NV_FALSE; + + data = (data >> PCF50626_CBCS2_CHGOVP_SHIFT) & PCF50626_CBCS2_CHGOVP_MASK; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + return NV_TRUE; +} + + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_batterycharger.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_batterycharger.h new file mode 100644 index 000000000000..ad5ebbc9f344 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_batterycharger.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_PCF50626_BATTERYCHARGER_HEADER +#define INCLUDED_PCF50626_BATTERYCHARGER_HEADER + + + +#include "pcf50626.h" + +/* the battery charger functions */ +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Initliase all registers that related to battery charger */ +NvBool +Pcf50626BatteryChargerSetup(NvOdmPmuDeviceHandle hDevice); + +/* Get battery Voltage */ +NvBool +Pcf50626BatteryChargerGetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 *res); + + +/* check OnKey level */ +NvBool +Pcf50626BatteryChargerOnKeyStatus( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check rec1 level */ +NvBool +Pcf50626BatteryChargerRec1Status( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check battery status */ +NvBool +Pcf50626BatteryChargerBattStatus( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check main charger status */ +NvBool +Pcf50626BatteryChargerMainChgPresent( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check USB charger status */ +NvBool +Pcf50626BatteryChargerUsbChgPresent( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check temparature status */ +NvBool +Pcf50626BatteryChargerTempStatus( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + + +/* check CBC batt_ful status */ +NvBool +Pcf50626BatteryChargerCBCBattFul( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + + + +/* check CBC thermal limit activation status */ +NvBool +Pcf50626BatteryChargerCBCTlimStatus( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check CBC batt_ful status */ +NvBool +Pcf50626BatteryChargerCBCWdExpired( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + + +/* check CBC charger current status */ +NvBool +Pcf50626BatteryChargerCBCChgCurStatus( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check CBC charger voltage status */ +NvBool +Pcf50626BatteryChargerCBCChgVoltStatus( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check CBC charger resume status */ +NvBool +Pcf50626BatteryChargerCBCChgResStatus( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check CBC main batt presence */ +NvBool +Pcf50626BatteryChargerCBCMainBatt( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check USB suspend status */ +NvBool +Pcf50626BatteryChargerCBCUsbSuspStat( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + +/* check charger over-voltage protection status */ +NvBool +Pcf50626BatteryChargerCBCChgOvpStat( + NvOdmPmuDeviceHandle hDevice, + NvBool *status); + + + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_PCF50626_BATTERYCHARGER_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_i2c.c new file mode 100644 index 000000000000..38990b3ffada --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_i2c.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "pcf50626_i2c.h" +#include "nvodm_pmu.h" +#include "nvodm_services.h" + + +NvBool Pcf50626I2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data) +{ + NvU8 WriteBuffer[2]; + NvOdmI2cTransactionInfo TransactionInfo; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Pcf50626PrivData *hPmu = (Pcf50626PrivData*)hDevice->pPrivate; + + WriteBuffer[0] = Addr & 0xFF; // PMU offset + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = hPmu->DeviceAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + PCF506226_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + +NvBool Pcf50626I2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data) +{ + NvU8 ReadBuffer = 0; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Pcf50626PrivData *hPmu = (Pcf50626PrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + // Write the PMU offset + ReadBuffer = Addr & 0xFF; + + TransactionInfo[0].Address = hPmu->DeviceAddr; + TransactionInfo[0].Buf = &ReadBuffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + TransactionInfo[1].Address = (hPmu->DeviceAddr | 0x1); + TransactionInfo[1].Buf = &ReadBuffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + // Read data from PMU at the specified offset + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2, + PCF506226_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + *Data = ReadBuffer; + return NV_TRUE; +} + +NvBool Pcf50626I2cWrite32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 Data) +{ + NvU8 WriteBuffer[5]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Pcf50626PrivData *hPmu = (Pcf50626PrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo; + + WriteBuffer[0] = (NvU8)(Addr & 0xFF); + WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF); + WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF); + WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF); + WriteBuffer[4] = (NvU8)(Data & 0xFF); + + TransactionInfo.Address = hPmu->DeviceAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 5; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo, 1, + PCF506226_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite32 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + return NV_TRUE; +} + +NvBool Pcf50626I2cRead32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 *Data) +{ + NvU8 ReadBuffer[5]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + Pcf50626PrivData *hPmu = (Pcf50626PrivData*)hDevice->pPrivate; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + + ReadBuffer[0] = Addr & 0xFF; + + TransactionInfo[0].Address = hPmu->DeviceAddr; + TransactionInfo[0].Buf = &ReadBuffer[0]; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + + TransactionInfo[1].Address = (hPmu->DeviceAddr | 0x1); + TransactionInfo[1].Buf = &ReadBuffer[0]; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 4; + + status = NvOdmI2cTransaction(hPmu->hOdmI2C, &TransactionInfo[0], 2, + PCF506226_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead32 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) | + (ReadBuffer[2] << 8) | ReadBuffer[3]; + + return NV_TRUE; +} + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_i2c.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_i2c.h new file mode 100644 index 000000000000..bc4b5aead9c8 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_i2c.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_PMU_PCF50626_I2C_H +#define INCLUDED_NVODM_PMU_PCF50626_I2C_H + +#include "pcf50626.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// Constant definition +#define PMU_PCF50626_DEVADDR 0xE0 +#define PCF506226_I2C_SPEED_KHZ 400 + +// Function declaration +NvBool Pcf50626I2cWrite8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 Data); + +NvBool Pcf50626I2cRead8( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU8 *Data); + +NvBool Pcf50626I2cWrite32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 Data); + +NvBool Pcf50626I2cRead32( + NvOdmPmuDeviceHandle hDevice, + NvU8 Addr, + NvU32 *Data); + + + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_NVODM_PMU_PCF50626_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_interrupt.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_interrupt.c new file mode 100644 index 000000000000..da9c4b605976 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_interrupt.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "pcf50626_interrupt.h" +#include "pcf50626_batterycharger.h" +#include "pcf50626_i2c.h" +#include "pcf50626_reg.h" +#include "nvodm_services.h" + +NvBool Pcf50626SetupInterrupt(NvOdmPmuDeviceHandle hDevice, + Pcf50626Status *pmuStatus) +{ + NvBool status = NV_FALSE; + NvU8 data = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pmuStatus); + + /* Init Pmu Status */ + pmuStatus->lowBatt = NV_FALSE; + pmuStatus->highTemp = NV_FALSE; + pmuStatus->chgCcToCv = NV_FALSE; + + if (!Pcf50626BatteryChargerMainChgPresent(hDevice,&status)) + return NV_FALSE; + pmuStatus->mChgPresent = status; + + + /* Set up Interrupt Mask */ + data = (NvU8) ~(PCF50626_INT1_LOWBATT | PCF50626_INT1_HIGHTEMP); + if(! Pcf50626I2cWrite8(hDevice, PCF50626_INT1M_ADDR, data )) + return NV_FALSE; + + data = 0; + data = (NvU8) ~PCF50626_INT2_VMAX; + if(! Pcf50626I2cWrite8(hDevice, PCF50626_INT2M_ADDR, data )) + return NV_FALSE; + + data = 0; + data = (NvU8) ~(PCF50626_INT3_MCHGINS | PCF50626_INT3_MCHGRM); + if(! Pcf50626I2cWrite8(hDevice, PCF50626_INT3M_ADDR, data )) + return NV_FALSE; + + data = 0; + data = (NvU8) ~(PCF50626_INT4_BATFUL | PCF50626_INT4_CHGRES); + if(! Pcf50626I2cWrite8(hDevice, PCF50626_INT4M_ADDR, data )) + return NV_FALSE; + + //if(! Pcf50626I2cWrite8(hDevice, PCF50626_INT5M_ADDR, 0xff)) + // return NV_FALSE; + + //if(! Pcf50626I2cWrite8(hDevice, PCF50626_INT6M_ADDR, 0xff)) + // return NV_FALSE; + + //if(! Pcf50626I2cWrite8(hDevice, PCF50626_INT7M_ADDR, 0xff)) + // return NV_FALSE; + + return NV_TRUE; +} + +void Pcf50626InterruptHandler_int(NvOdmPmuDeviceHandle hDevice, + Pcf50626Status *pmuStatus) +{ + + NvU8 data = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pmuStatus); + + // INT1 + if (!Pcf50626I2cRead8(hDevice, PCF50626_INT1_ADDR, &data)) + { + NVODMPMU_PRINTF(("Error reading INT1")); + return; + } + if (data != 0) + { + if (data & PCF50626_INT1_HIGHTEMP) + pmuStatus->highTemp = NV_TRUE; + else + pmuStatus->highTemp = NV_FALSE; + if (data & PCF50626_INT1_LOWBATT) + pmuStatus->lowBatt = NV_TRUE; + else + pmuStatus->lowBatt = NV_FALSE; + } + + // INT2 + if (!Pcf50626I2cRead8(hDevice, PCF50626_INT2_ADDR, &data)) + { + NVODMPMU_PRINTF(("Error reading INT2")); + return; + } + if (data != 0) + { + if (data & PCF50626_INT2_VMAX) + pmuStatus->chgCcToCv = NV_TRUE; + else + pmuStatus->chgCcToCv = NV_FALSE; + } + + // INT3 + if (!Pcf50626I2cRead8(hDevice, PCF50626_INT3_ADDR, &data)) + { + NVODMPMU_PRINTF(("Error reading INT3")); + return; + } + if (data != 0) + { + if (data & PCF50626_INT3_MCHGRM) + pmuStatus->mChgPresent = NV_FALSE; + + if (data & PCF50626_INT3_MCHGINS) + { + pmuStatus->mChgPresent = NV_TRUE; + NvOdmEnableOtgCircuitry(NV_TRUE); + } + } + + // INT4 + if (!Pcf50626I2cRead8(hDevice, PCF50626_INT4_ADDR, &data)) + { + NVODMPMU_PRINTF(("Error reading INT4")); + return; + } + if (data != 0) + { + if (data & PCF50626_INT4_CHGRES) + pmuStatus->batFull = NV_FALSE; + + if (data & PCF50626_INT4_BATFUL) + pmuStatus->batFull = NV_TRUE; + } + +} + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_interrupt.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_interrupt.h new file mode 100644 index 000000000000..2cf1b404bc8c --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_interrupt.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_PCF50626_INTERRUPT_HEADER +#define INCLUDED_PCF50626_INTERRUPT_HEADER + +#include "pcf50626.h" + + +#if defined(__cplusplus) +extern "C" +{ +#endif + + +NvBool +Pcf50626SetupInterrupt( + NvOdmPmuDeviceHandle hDevice, + Pcf50626Status *pmuStatus); + + + +void +Pcf50626InterruptHandler_int( + NvOdmPmuDeviceHandle hDevice, + Pcf50626Status *pmuStatus); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_PCF50626_INTERRUPT_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_reg.h new file mode 100644 index 000000000000..2454487149e8 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_reg.h @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2007-2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PCF50626_REG_HEADER +#define PCF50626_REG_HEADER + +#if defined(__cplusplus) +extern "C" +{ +#endif + + +// The following are the OTP reset values +#define PCF50626_ID_DEFAULT 0x31 // TBD, may change +#define PCF50626_BVMC_RESET 0x18 + +#define PCF50626_D1REGC1_RESET 0x6C +#define PCF50626_D1REGC2_RESET 0x01 +#define PCF50626_D1REGC3_RESET 0x00 + +#define PCF50626_D2REGC1_RESET 0x6C +#define PCF50626_D2REGC2_RESET 0xE1 +#define PCF50626_D2REGC3_RESET 0x00 + +#define PCF50626_D3REGC1_RESET 0x18 +#define PCF50626_D3REGC2_RESET 0xE1 +#define PCF50626_D3REGC3_RESET 0x80 + +#define PCF50626_D7REGC2_RESET 0x01 +#define PCF50626_D7REGC3_RESET 0x00 + +#define PCF50626_D8REGC2_RESET 0xE1 +#define PCF50626_D8REGC3_RESET 0x40 + +#define PCF50626_RF1REGC1_RESET 0x58 +#define PCF50626_RF1REGC2_RESET 0x01 +#define PCF50626_RF1REGC3_RESET 0x40 + +#define PCF50626_RF2REGC1_RESET 0x58 +#define PCF50626_RF2REGC2_RESET 0x01 +#define PCF50626_RF2REGC3_RESET 0x40 + +#define PCF50626_IOREGC1_RESET 0x30 +#define PCF50626_IOREGC2_RESET 0xE1 +#define PCF50626_IOREGC3_RESET 0x40 + +#define PCF50626_USBREGC1_RESET 0x58 +#define PCF50626_USBREGC2_RESET 0xE1 +#define PCF50626_USBREGC3_RESET 0x40 + +#define PCF50626_LCREGC1_RESET 0x18 +#define PCF50626_LCREGC2_RESET 0xE1 +#define PCF50626_LCREGC3_RESET 0x00 + +#define PCF50626_DCD1C1_RESET 0x18 +#define PCF50626_DCD1C2_RESET 0xE1 +#define PCF50626_DCD1C3_RESET 0x00 +#define PCF50626_DCD1C4_RESET 0x0F + +#define PCF50626_DCD2C1_RESET 0x30 +#define PCF50626_DCD2C2_RESET 0xE1 +#define PCF50626_DCD2C3_RESET 0x80 +#define PCF50626_DCD2C4_RESET 0x0F + +#define PCF50626_DCUDC2_RESET 0xE1 +#define PCF50626_DCUDC3_RESET 0xC0 + +#define PCF50626_ALMCAL_RESET 0x11 +#define PCF50626_ALMCRV1_RESET 0x01 +#define PCF50626_ALMCRV2_RESET 0x28 +#define PCF50626_ALMCRV3_RESET 0x50 +#define PCF50626_ALMCRV4_RESET 0x78 +#define PCF50626_LED1C_RESET 0x4D +#define PCF50626_LEDCC_RESET 0x01 + +#define PCF50626_ADCC1_RESET 0x02 +#define PCF50626_ADCC2_RESET 0x00 +#define PCF50626_ADCC3_RESET 0x00 +#define PCF50626_ADCC4_RESET 0x00 + +#define PCF50626_DCULEDC1_RESET 0x08 +#define PCF50626_DCULEDC2_RESET 0x01 +#define PCF50626_DCULEDC3_RESET 0x00 +#define PCF50626_DCULEDDIMMAN_RESET 0x3F + +#define PCF50626_CBCC1_RESET 0x2B +#define PCF50626_CBCC2_RESET 0x5A +#define PCF50626_CBCC3_RESET 0x12 +#define PCF50626_CBCC4_RESET 0x12 +#define PCF50626_CBCC5_RESET 0x0B +#define PCF50626_CBCC6_RESET 0x02 + +#define PCF50626_BBCC1_RESET 0x00 + + +//Table. 168 +#define PCF50626_ID_ADDR 0x00 +#define PCF50626_INT1_ADDR 0x01 +#define PCF50626_INT2_ADDR 0x02 +#define PCF50626_INT3_ADDR 0x03 +#define PCF50626_INT4_ADDR 0x04 +#define PCF50626_INT5_ADDR 0x05 +#define PCF50626_INT6_ADDR 0x06 +#define PCF50626_INT7_ADDR 0x09 + +#define PCF50626_INT1M_ADDR 0x0A +#define PCF50626_INT2M_ADDR 0x0B +#define PCF50626_INT3M_ADDR 0x0C +#define PCF50626_INT4M_ADDR 0x0D +#define PCF50626_INT5M_ADDR 0x0E +#define PCF50626_INT6M_ADDR 0x0F +#define PCF50626_INT7M_ADDR 0x12 + +#define PCF50626_ERROR_ADDR 0x13 + +#define PCF50626_OOCC1_ADDR 0x14 +#define PCF50626_OOCC2_ADDR 0x15 +#define PCF50626_OOCPH_ADDR 0x16 +#define PCF50626_OOCS_ADDR 0x17 + +#define PCF50626_BVMC_ADDR 0x18 + +#define PCF50626_RECC1_ADDR 0x19 +#define PCF50626_RECC2_ADDR 0x1A +#define PCF50626_RECS_ADDR 0x1B + +#define PCF50626_RTC1_ADDR 0x1C +#define PCF50626_RTC2_ADDR 0x1D +#define PCF50626_RTC3_ADDR 0x1E +#define PCF50626_RTC4_ADDR 0x1F + +#define PCF50626_RTC1A_ADDR 0x20 +#define PCF50626_RTC2A_ADDR 0x21 +#define PCF50626_RTC3A_ADDR 0x22 +#define PCF50626_RTC4A_ADDR 0x23 + +#define PCF50626_CBCC1_ADDR 0x24 +#define PCF50626_CBCC2_ADDR 0x25 +#define PCF50626_CBCC3_ADDR 0x26 +#define PCF50626_CBCC4_ADDR 0x27 +#define PCF50626_CBCC5_ADDR 0x28 +#define PCF50626_CBCC6_ADDR 0x29 + +#define PCF50626_CBCS1_ADDR 0x2A +#define PCF50626_CBCS2_ADDR 0x2B +#define PCF50626_BBCC1_ADDR 0x2C +#define PCF50626_PWM1S_ADDR 0x2D +#define PCF50626_PWM1D_ADDR 0x2E +#define PCF50626_PWM2S_ADDR 0x2F +#define PCF50626_PWM2D_ADDR 0x30 + +#define PCF50626_LED1C_ADDR 0x31 +#define PCF50626_LED2C_ADDR 0x32 +#define PCF50626_LEDCC_ADDR 0x33 + +#define PCF50626_ADCC2_ADDR 0x34 +#define PCF50626_ADCC3_ADDR 0x35 +#define PCF50626_ADCC4_ADDR 0x36 +#define PCF50626_ADCC1_ADDR 0x37 +#define PCF50626_ADCS1_ADDR 0x38 +#define PCF50626_ADCS2_ADDR 0x39 +#define PCF50626_ADCS3_ADDR 0x3A + +#define PCF50626_TSIC2_ADDR 0x3B +#define PCF50626_TSIC1_ADDR 0x3C +#define PCF50626_TSIDAT1_ADDR 0x3D +#define PCF50626_TSIDAT2_ADDR 0x3E +#define PCF50626_TSIDAT3_ADDR 0x3F + +#define PCF50626_GPIO1C1_ADDR 0x40 +#define PCF50626_E1REGC2_ADDR 0x41 +#define PCF50626_E1REGC3_ADDR 0x42 +#define PCF50626_GPIO2C1_ADDR 0x43 +#define PCF50626_E2REGC2_ADDR 0x44 +#define PCF50626_E2REGC3_ADDR 0x45 +#define PCF50626_GPIO3C1_ADDR 0x46 +#define PCF50626_E3REGC2_ADDR 0x47 +#define PCF50626_E3REGC3_ADDR 0x48 +#define PCF50626_GPIO4C1_ADDR 0x49 +#define PCF50626_E4REGC2_ADDR 0x4A +#define PCF50626_E4REGC3_ADDR 0x4B +#define PCF50626_GPIO5C1_ADDR 0x4C +#define PCF50626_E5REGC2_ADDR 0x4D +#define PCF50626_E5REGC3_ADDR 0x4E +#define PCF50626_GPIO6C1_ADDR 0x4F +#define PCF50626_E6REGC2_ADDR 0x50 +#define PCF50626_E6REGC3_ADDR 0x51 + +#define PCF50626_GPO1C1_ADDR 0x52 +#define PCF50626_EO1REGC2_ADDR 0x53 +#define PCF50626_EO1REGC3_ADDR 0x54 +#define PCF50626_GPO2C1_ADDR 0x55 +#define PCF50626_EO2REGC2_ADDR 0x56 +#define PCF50626_EO2REGC3_ADDR 0x57 +#define PCF50626_GPO3C1_ADDR 0x58 +#define PCF50626_EO3REGC2_ADDR 0x59 +#define PCF50626_EO3REGC3_ADDR 0x5A +#define PCF50626_GPO4C1_ADDR 0x5B +#define PCF50626_EO4REGC2_ADDR 0x5C +#define PCF50626_EO4REGC3_ADDR 0x5D + +#define PCF50626_D1REGC1_ADDR 0x5E +#define PCF50626_D1REGC2_ADDR 0x5F +#define PCF50626_D1REGC3_ADDR 0x60 + +#define PCF50626_D2REGC1_ADDR 0x61 +#define PCF50626_D2REGC2_ADDR 0x62 +#define PCF50626_D2REGC3_ADDR 0x63 + +#define PCF50626_D3REGC1_ADDR 0x64 +#define PCF50626_D3REGC2_ADDR 0x65 +#define PCF50626_D3REGC3_ADDR 0x66 + +#define PCF50626_D4REGC1_ADDR 0x67 +#define PCF50626_D4REGC2_ADDR 0x68 +#define PCF50626_D4REGC3_ADDR 0x69 + +#define PCF50626_D5REGC1_ADDR 0x6A +#define PCF50626_D5REGC2_ADDR 0x6B +#define PCF50626_D5REGC3_ADDR 0x6C + +#define PCF50626_D6REGC1_ADDR 0x6D +#define PCF50626_D6REGC2_ADDR 0x6E +#define PCF50626_D6REGC3_ADDR 0x6F + +#define PCF50626_D7REGC1_ADDR 0x70 +#define PCF50626_D7REGC2_ADDR 0x71 +#define PCF50626_D7REGC3_ADDR 0x72 + +#define PCF50626_D8REGC1_ADDR 0x73 +#define PCF50626_D8REGC2_ADDR 0x74 +#define PCF50626_D8REGC3_ADDR 0x75 + +#define PCF50626_RF1REGC1_ADDR 0x76 +#define PCF50626_RF1REGC2_ADDR 0x77 +#define PCF50626_RF1REGC3_ADDR 0x78 + +#define PCF50626_RF2REGC1_ADDR 0x79 +#define PCF50626_RF2REGC2_ADDR 0x7A +#define PCF50626_RF2REGC3_ADDR 0x7B + +#define PCF50626_RF3REGC1_ADDR 0x7C +#define PCF50626_RF3REGC2_ADDR 0x7D +#define PCF50626_RF3REGC3_ADDR 0x7E + +#define PCF50626_RF4REGC1_ADDR 0x7F +#define PCF50626_RF4REGC2_ADDR 0x80 +#define PCF50626_RF4REGC3_ADDR 0x81 + +#define PCF50626_IOREGC1_ADDR 0x82 +#define PCF50626_IOREGC2_ADDR 0x83 +#define PCF50626_IOREGC3_ADDR 0x84 + +#define PCF50626_USBREGC1_ADDR 0x85 +#define PCF50626_USBREGC2_ADDR 0x86 +#define PCF50626_USBREGC3_ADDR 0x87 + +#define PCF50626_USIMREGC1_ADDR 0x88 +#define PCF50626_USIMREGC2_ADDR 0x89 +#define PCF50626_USIMREGC3_ADDR 0x8A + +#define PCF50626_LCREGC1_ADDR 0x8B +#define PCF50626_LCREGC2_ADDR 0x8C +#define PCF50626_LCREGC3_ADDR 0x8D + +#define PCF50626_HCREGC1_ADDR 0x8E +#define PCF50626_HCREGC2_ADDR 0x8F +#define PCF50626_HCREGC3_ADDR 0x90 + +#define PCF50626_DCD1C1_ADDR 0x91 +#define PCF50626_DCD1C2_ADDR 0x92 +#define PCF50626_DCD1C3_ADDR 0x93 +#define PCF50626_DCD1C4_ADDR 0x94 + +#define PCF50626_DCD1DVM1_ADDR 0x95 +#define PCF50626_DCD1DVM2_ADDR 0x96 +#define PCF50626_DCD1DVM3_ADDR 0x97 +#define PCF50626_DCD1DVMTIM_ADDR 0x98 + +#define PCF50626_DCD2C1_ADDR 0x99 +#define PCF50626_DCD2C2_ADDR 0x9A +#define PCF50626_DCD2C3_ADDR 0x9B +#define PCF50626_DCD2C4_ADDR 0x9C + +#define PCF50626_DCD2DVM1_ADDR 0x9D +#define PCF50626_DCD2DVM2_ADDR 0x9E +#define PCF50626_DCD2DVM3_ADDR 0x9F +#define PCF50626_DCD2DVMTIM_ADDR 0xA0 + +#define PCF50626_DCUDC1_ADDR 0xA1 +#define PCF50626_DCUDC2_ADDR 0xA2 +#define PCF50626_DCUDC3_ADDR 0xA3 +#define PCF50626_DCUDC4_ADDR 0xA4 +#define PCF50626_DCUDDVMTIM_ADDR 0xA5 + +#define PCF50626_DCULEDC1_ADDR 0xA6 +#define PCF50626_DCULEDC2_ADDR 0xA7 +#define PCF50626_DCULEDC3_ADDR 0xA8 +#define PCF50626_DCULED_DIMMAN_ADDR 0xA9 + +#define PCF50626_ALMCAL_ADDR 0xAA +#define PCF50626_ALMCALMEA_ADDR 0xAB +#define PCF50626_ALMCRV1_ADDR 0xAC +#define PCF50626_ALMCRV2_ADDR 0xAD +#define PCF50626_ALMCRV3_ADDR 0xAE +#define PCF50626_ALMCRV4_ADDR 0xAF + +#define PCF50626_GPIOS_ADDR 0xB0 +#define PCF50626_DREGS1_ADDR 0xB1 +#define PCF50626_DREGS2_ADDR 0xB2 +#define PCF50626_RFREGS_ADDR 0xB3 +#define PCF50626_GREGS_ADDR 0xB4 + +#define PCF50626_GPIO7C1_ADDR 0xB5 +#define PCF50626_GPIO8C1_ADDR 0xB6 + +#define PCF50626_USIMDETC_ADDR 0xB7 + +#define PCF50626_TSINOI_ADDR 0xFE +#define PCF50626_TSIDAT4_ADDR 0xFF + + +/* field defines for register bit ops */ +#define PCF50626_C2_OPMOD_SHIFT 0x05 +#define PCF50626_C2_OPMOD_ON 0xE1 +#define PCF50626_C2_OPMOD_OFF 0x01 +#define PCF50626_C1_OUTPUT_MASK 0x7F + +#define PCF50626_OOCS_ONKEY_SHIFT 0x00 +#define PCF50626_OOCS_ONKEY_MASK 0x01 +#define PCF50626_OOCS_REC1_SHIFT 0x01 +#define PCF50626_OOCS_REC1_MASK 0x01 +#define PCF50626_OOCS_BATOK_SHIFT 0x02 +#define PCF50626_OOCS_BATOK_MASK 0x01 +#define PCF50626_OOCS_MCHGOK_SHIFT 0x04 +#define PCF50626_OOCS_MCHGOK_MASK 0x01 +#define PCF50626_OOCS_UCHGOK_SHIFT 0x05 +#define PCF50626_OOCS_UCHGOK_MASK 0x01 +#define PCF50626_OOCS_TEMPOK_SHIFT 0x06 +#define PCF50626_OOCS_TEMPOK_MASK 0x01 + +#define PCF50626_CBCS1_BATTFUL_SHIFT 0x00 +#define PCF50626_CBCS1_BATTFUL_MASK 0x01 +#define PCF50626_CBCS1_TLIMIT_SHIFT 0x01 +#define PCF50626_CBCS1_TLIMIT_MASK 0x01 +#define PCF50626_CBCS1_WDEXP_SHIFT 0x02 +#define PCF50626_CBCS1_WDEXP_MASK 0x01 +#define PCF50626_CBCS1_ILIMIT_SHIFT 0x03 +#define PCF50626_CBCS1_ILIMIT_MASK 0x01 +#define PCF50626_CBCS1_VLIMIT_SHIFT 0x04 +#define PCF50626_CBCS1_VLIMIT_MASK 0x01 +#define PCF50626_CBCS1_RESSTAT_SHIFT 0x07 +#define PCF50626_CBCS1_RESSTAT_MASK 0x01 +#define PCF50626_CBCS2_NOBAT_SHIFT 0x00 +#define PCF50626_CBCS2_NOBAT_MASK 0x01 +#define PCF50626_CBCS2_USBSUSPSTAT_SHIFT 0x02 +#define PCF50626_CBCS2_USBSUSPSTAT_MASK 0x01 +#define PCF50626_CBCS2_CHGOVP_SHIFT 0x03 +#define PCF50626_CBCS2_CHGOVP_MASK 0x01 + +#define PCF50626_ADCC1_STARTCMD_SHIFT 0x00 +#define PCF50626_ADCC1_STARTCMD_MASK 0x01 +#define PCF50626_ADCC1_STARTCMD_START 0x01 +#define PCF50626_ADCC1_STARTCMD_STOP 0x00 + +#define PCF50626_ADCS3_ADCRDY_SHIFT 0x07 +#define PCF50626_ADCS3_ADCRDY_MASK 0x01 +#define PCF50626_ADCS3_ADCRDY_READY 0x01 + +#define PCF50626_DCULED_DIMMAN_LEDMAN_MASK 0x3F +#define PCF50626_DCULED_DIMMAN_LEDMAN_SHIFT 0x00 + +#define PCF50626_DCULED_DIMMAN_ALMSEL_MASK 0x01 +#define PCF50626_DCULED_DIMMAN_ALMSEL_SHIFT 0x06 +#define PCF50626_DCULED_DIMMAN_ALMSEL_ALM 0x01 +#define PCF50626_DCULED_DIMMAN_ALMSEL_MAN 0x00 + +#define PCF50626_INT1_LOWBATT 0x01 +#define PCF50626_INT1_HIGHTEMP 0x80 +#define PCF50626_INT2_VMAX 0x40 +#define PCF50626_INT3_MCHGINS 0x40 +#define PCF50626_INT3_MCHGRM 0x80 +#define PCF50626_INT4_CHGRES 0x01 +#define PCF50626_INT4_BATFUL 0x08 + +#define PCF50626_CBCC1_CHGENA_SHIFT 0x00 +#define PCF50626_CBCC1_CHGENA_MASK 0x01 +#define PCF50626_CBCC2_SUSPENA_SHIFT 0x02 +#define PCF50626_CBCC2_SUSPENA_MASK 0x01 + +//rail specs +#define PCF50626_DCDXOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_DCDXOUT_VOLTAGE_MIN_MV 625 +#define PCF50626_DCDXOUT_VOLTAGE_STEP_MV 25 +#define PCF50626_DCDXOUT_VOLTAGE_MAX_MV 2700 +#define PCF50626_DCDXOUT_TURNON_TIME_MICROSEC 365 +#define PCF50626_DCDXOUT_SWITCH_TIME_MICROSEC 20 + +#define PCF50626_DCUDOUT_MODE1_VOLTAGE_OFFSET_MV 2675 +#define PCF50626_DCUDOUT_MODE1_VOLTAGE_MIN_MV 3100 +#define PCF50626_DCUDOUT_MODE1_VOLTAGE_STEP_MV 25 +#define PCF50626_DCUDOUT_MODE1_VOLTAGE_MAX_MV 4975 +#define PCF50626_DCUDOUT_TURNON_TIME_MICROSEC 65 +#define PCF50626_DCUDOUT_SWITCH_TIME_MICROSEC 0 + +#define PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_DXREGOUT_VOLTAGE_MIN_MV 1200 +#define PCF50626_DXREGOUT_VOLTAGE_STEP_MV 100 +#define PCF50626_DXREGOUT_VOLTAGE_MAX_MV 3300 +#define PCF50626_DXREGOUT_TURNON_TIME_MICROSEC 85 +#define PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC 0 + +#define PCF50626_RFXREGOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_RFXREGOUT_VOLTAGE_MIN_MV 1200 +#define PCF50626_RFXREGOUT_VOLTAGE_STEP_MV 100 +#define PCF50626_RFXREGOUT_VOLTAGE_MAX_MV 3000 +#define PCF50626_RFXREGOUT_TURNON_TIME_MICROSEC 285 +#define PCF50626_RFXREGOUT_SWITCH_TIME_MICROSEC 0 + +#define PCF50626_HCREGOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_HCREGOUT_VOLTAGE_MIN_MV 1800 +#define PCF50626_HCREGOUT_VOLTAGE_STEP_MV 100 +#define PCF50626_HCREGOUT_VOLTAGE_MAX_MV 3000 +#define PCF50626_HCREGOUT_TURNON_TIME_MICROSEC 85 +#define PCF50626_HCREGOUT_SWITCH_TIME_MICROSEC 0 + +#define PCF50626_IOREGOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_IOREGOUT_VOLTAGE_MIN_MV 1200 +#define PCF50626_IOREGOUT_VOLTAGE_STEP_MV 100 +#define PCF50626_IOREGOUT_VOLTAGE_MAX_MV 3300 +#define PCF50626_IOREGOUT_TURNON_TIME_MICROSEC 85 +#define PCF50626_IOREGOUT_SWITCH_TIME_MICROSEC 0 + +#define PCF50626_USBREGOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_USBREGOUT_VOLTAGE_MIN_MV 1200 +#define PCF50626_USBREGOUT_VOLTAGE_STEP_MV 100 +#define PCF50626_USBREGOUT_VOLTAGE_MAX_MV 3300 +#define PCF50626_USBREGOUT_TURNON_TIME_MICROSEC 85 +#define PCF50626_USBREGOUT_SWITCH_TIME_MICROSEC 0 + +#define PCF50626_USIMREGOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_USIMREGOUT_VOLTAGE_MIN_MV 1800 +#define PCF50626_USIMREGOUT_VOLTAGE_STEP_MV 100 +#define PCF50626_USIMREGOUT_VOLTAGE_MAX_MV 3000 +#define PCF50626_USIMREGOUT_TURNON_TIME_MICROSEC 105 +#define PCF50626_USIMREGOUT_SWITCH_TIME_MICROSEC 0 + +#define PCF50626_LCREGOUT_VOLTAGE_OFFSET_MV 600 +#define PCF50626_LCREGOUT_VOLTAGE_MIN_MV 600 +#define PCF50626_LCREGOUT_VOLTAGE_STEP_MV 50 +#define PCF50626_LCREGOUT_VOLTAGE_MAX_MV 2900 +#define PCF50626_LCREGOUT_VOLTAGE_RESCHANGE_MV 1400 +#define PCF50626_LCREGOUT_TURNON_TIME_MICROSEC 125 +#define PCF50626_LCREGOUT_SWITCH_TIME_MICROSEC 0 + +#if defined(__cplusplus) +} +#endif + + +#endif //PCF50626_VOLTAGE_INFO_TABLE_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_rtc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_rtc.c new file mode 100644 index 000000000000..ca35bab03b2d --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_rtc.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "pcf50626_rtc.h" +#include "pcf50626_i2c.h" +#include "pcf50626_reg.h" + +/* Read RTC count register */ + +static NvBool bRtcNotInitialized = NV_TRUE; + +NvBool +Pcf50626RtcCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count) +{ + if (Pcf50626RtcWasStartUpFromNoPower(hDevice) && bRtcNotInitialized) + { + if (!Pcf50626I2cWrite32 (hDevice, PCF50626_RTC1_ADDR, 0)) + { + return NV_FALSE; + } + bRtcNotInitialized = NV_FALSE; + *Count = 0; + return NV_TRUE; + } else + { + return ( Pcf50626I2cRead32 (hDevice, PCF50626_RTC1_ADDR, Count) ); + } +} + +/* Write RTC count register */ + +NvBool +Pcf50626RtcCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count) +{ + NvBool ret; + + ret = Pcf50626I2cWrite32 (hDevice, PCF50626_RTC1_ADDR, Count); + + if (ret && bRtcNotInitialized) + bRtcNotInitialized = NV_FALSE; + + return ret; +} + +/* Read RTC alarm count register */ + +NvBool +Pcf50626RtcAlarmCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count) +{ + return ( Pcf50626I2cRead32 (hDevice, PCF50626_RTC1A_ADDR, Count) ); +} + +/* Write RTC alarm count register */ + +NvBool +Pcf50626RtcAlarmCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count) +{ + return ( Pcf50626I2cWrite32 (hDevice, PCF50626_RTC1A_ADDR, Count) ); +} + +/* Reads RTC alarm interrupt mask status */ + +NvBool +Pcf50626RtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice) +{ + NvU8 Mask; + + if(Pcf50626I2cRead8 (hDevice, PCF50626_INT1M_ADDR, &Mask)) + { + return ((Mask & 0x8)? NV_FALSE:NV_TRUE); + } + + return NV_FALSE; +} + +/* Enables / Disables the RTC alarm interrupt */ + +NvBool +Pcf50626RtcAlarmIntEnable( + NvOdmPmuDeviceHandle hDevice, + NvBool Enable) +{ + NvBool Status = NV_FALSE; + NvU8 Mask; + + if ((Status = Pcf50626I2cRead8(hDevice, PCF50626_INT1M_ADDR, &Mask)) == NV_TRUE) + { + (Mask = Enable? (Mask & ~0x8):(Mask|0x8)); + Status = Pcf50626I2cWrite8 (hDevice, PCF50626_INT1M_ADDR, Mask); + } + + return Status; +} + +/* Checks if boot was from nopower / powered state */ + +NvBool +Pcf50626RtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice) +{ + NvU8 Data; + + // Check "nopower" bit of the ERROR status register. + // Make sure the backup battery charger is enabled (bbce and vsaveen bits). This is done by + // the bootloader. If this is not done, the "nopower" bit will remain stuck at 0x1. + if ((Pcf50626I2cRead8(hDevice, PCF50626_ERROR_ADDR, &Data)) == NV_TRUE) + { + return ((Data & 0x20)? NV_TRUE : NV_FALSE); + } + + return NV_FALSE; +} + +NvBool +Pcf50626IsRtcInitialized(NvOdmPmuDeviceHandle hDevice) +{ + return ((Pcf50626RtcWasStartUpFromNoPower(hDevice))? NV_FALSE : NV_TRUE); +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_rtc.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_rtc.h new file mode 100644 index 000000000000..f5979cf5e52d --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_rtc.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_PCF50626_RTC_HEADER +#define INCLUDED_PCF50626_RTC_HEADER + +#include "pmu_hal.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Read RTC count register */ + +NvBool +Pcf50626RtcCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count); + +/* Read RTC alarm count register */ + +NvBool +Pcf50626RtcAlarmCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count); + +/* Write RTC count register */ + +NvBool +Pcf50626RtcCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count); + +/* Write RTC alarm count register */ + +NvBool +Pcf50626RtcAlarmCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count); + +/* Reads RTC alarm interrupt mask status */ + +NvBool +Pcf50626RtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice); + +/* Enables / Disables the RTC alarm interrupt */ + +NvBool +Pcf50626RtcAlarmIntEnable( + NvOdmPmuDeviceHandle hDevice, + NvBool Enable); + +/* Checks if boot was from nopower / powered state */ + +NvBool +Pcf50626RtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice); + +NvBool +Pcf50626IsRtcInitialized(NvOdmPmuDeviceHandle hDevice); + + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_PCF50626_RTC_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_supply_info_table.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_supply_info_table.h new file mode 100644 index 000000000000..7064cf6e68c7 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/pcf50626_supply_info_table.h @@ -0,0 +1,615 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef PCF50626_SUPPLY_INFO_TABLE_HEADER +#define PCF50626_SUPPLY_INFO_TABLE_HEADER + +#include "nvodm_pmu_pcf50626_supply_info.h" +#include "pcf50626_reg.h" + + +// defines for the request Voltage. This is board specific and ODM should change this based on +// device. +#define PCF50626_REQUESTVOLTAGE_DCD1_MV 1200 +#define PCF50626_REQUESTVOLTAGE_DCD2_MV 1925 +#define PCF50626_REQUESTVOLTAGE_DCUD_MV 4975 +#define PCF50626_REQUESTVOLTAGE_RF1REG_MV 2800 +#define PCF50626_REQUESTVOLTAGE_RF2REG_MV 2800 +#define PCF50626_REQUESTVOLTAGE_RF3REG_MV 1800 +#define PCF50626_REQUESTVOLTAGE_RF4REG_MV 2800 +#define PCF50626_REQUESTVOLTAGE_D1REG_MV 3300 +#define PCF50626_REQUESTVOLTAGE_D2REG_MV 3300 +#define PCF50626_REQUESTVOLTAGE_D3REG_MV 1200 +#define PCF50626_REQUESTVOLTAGE_D4REG_MV 1200 +#define PCF50626_REQUESTVOLTAGE_D5REG_MV 1800 +#define PCF50626_REQUESTVOLTAGE_D6REG_MV 2800 +#define PCF50626_REQUESTVOLTAGE_D7REG_MV 2800 +#define PCF50626_REQUESTVOLTAGE_D8REG_MV 3100 +#define PCF50626_REQUESTVOLTAGE_HCREG_MV 2800 +#define PCF50626_REQUESTVOLTAGE_IOREG_MV 1800 +#define PCF50626_REQUESTVOLTAGE_USIMREG_MV 3000 +#define PCF50626_REQUESTVOLTAGE_USBREG_MV 2800 +#define PCF50626_REQUESTVOLTAGE_LCREG_MV 1200 + +// defines for the additional load-dependent TurnOn delays. This is board +// specific and ODM should change this based on device. +#define PCF50626_TURNON_DELAY_DCD1_US 0 +#define PCF50626_TURNON_DELAY_DCD2_US 0 +#define PCF50626_TURNON_DELAY_DCUD_US 0 +#define PCF50626_TURNON_DELAY_RF1REG_US 0 +#define PCF50626_TURNON_DELAY_RF2REG_US 0 +#define PCF50626_TURNON_DELAY_RF3REG_US 0 +#define PCF50626_TURNON_DELAY_RF4REG_US 0 +#define PCF50626_TURNON_DELAY_D1REG_US 0 +#define PCF50626_TURNON_DELAY_D2REG_US 0 +#define PCF50626_TURNON_DELAY_D3REG_US 0 +#define PCF50626_TURNON_DELAY_D4REG_US 0 +#define PCF50626_TURNON_DELAY_D5REG_US 2000 +#define PCF50626_TURNON_DELAY_D6REG_US 500 +#define PCF50626_TURNON_DELAY_D7REG_US 0 +#define PCF50626_TURNON_DELAY_D8REG_US 0 +#define PCF50626_TURNON_DELAY_HCREG_US 0 +#define PCF50626_TURNON_DELAY_IOREG_US 0 +#define PCF50626_TURNON_DELAY_USIMREG_US 0 +#define PCF50626_TURNON_DELAY_USBREG_US 0 +#define PCF50626_TURNON_DELAY_LCREG_US 0 + + +const PCF50626PmuSupplyInfo pcf50626SupplyInfoTable[] = +{ + { + PCF50626PmuSupply_Invalid, + PCF50626PmuSupply_Invalid, + 0,0,0,0, + 0,0,0,0, + {NV_TRUE,0,0,0,0}, + 0,0,0 + }, + + // DCD1 + { + PCF50626PmuSupply_DCD1, + PCF50626PmuSupply_VBAT, + + PCF50626_DCD1C1_ADDR, + PCF50626_DCD1C2_ADDR, + PCF50626_DCD1C3_ADDR, + PCF50626_DCD1C4_ADDR, + + PCF50626_DCD1DVM1_ADDR, + PCF50626_DCD1DVM2_ADDR, + PCF50626_DCD1DVM3_ADDR, + PCF50626_DCD1DVMTIM_ADDR, + + { + NV_FALSE, + PCF50626_DCDXOUT_VOLTAGE_MIN_MV, + PCF50626_DCDXOUT_VOLTAGE_STEP_MV, + PCF50626_DCDXOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_DCD1_MV + }, + + PCF50626_DCDXOUT_VOLTAGE_OFFSET_MV, + PCF50626_DCDXOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_DCD1_US, + PCF50626_DCDXOUT_SWITCH_TIME_MICROSEC + }, + + //DCD2 + { + PCF50626PmuSupply_DCD2, + PCF50626PmuSupply_VBAT, + + PCF50626_DCD2C1_ADDR, + PCF50626_DCD2C2_ADDR, + PCF50626_DCD2C3_ADDR, + PCF50626_DCD2C4_ADDR, + + PCF50626_DCD2DVM1_ADDR, + PCF50626_DCD2DVM2_ADDR, + PCF50626_DCD2DVM3_ADDR, + PCF50626_DCD2DVMTIM_ADDR, + + { + NV_FALSE, + PCF50626_DCDXOUT_VOLTAGE_MIN_MV, + PCF50626_DCDXOUT_VOLTAGE_STEP_MV, + PCF50626_DCDXOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_DCD2_MV + }, + + PCF50626_DCDXOUT_VOLTAGE_OFFSET_MV, + PCF50626_DCDXOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_DCD2_US, + PCF50626_DCDXOUT_SWITCH_TIME_MICROSEC + }, + + //DCUD + { + PCF50626PmuSupply_DCUD, + PCF50626PmuSupply_VBAT, + + PCF50626_DCUDC1_ADDR, + PCF50626_DCUDC2_ADDR, + PCF50626_DCUDC3_ADDR, + PCF50626_DCUDC4_ADDR, + 0,0,0, + PCF50626_DCUDDVMTIM_ADDR, + + { + NV_FALSE, + PCF50626_DCUDOUT_MODE1_VOLTAGE_MIN_MV, + PCF50626_DCUDOUT_MODE1_VOLTAGE_STEP_MV, + PCF50626_DCUDOUT_MODE1_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_DCUD_MV + }, + + PCF50626_DCUDOUT_MODE1_VOLTAGE_OFFSET_MV, + PCF50626_DCUDOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_DCUD_US, + PCF50626_DCUDOUT_SWITCH_TIME_MICROSEC + }, + + //DCULED + { + PCF50626PmuSupply_DCULED, + PCF50626PmuSupply_VBAT, + + PCF50626_DCULEDC1_ADDR, + PCF50626_DCULEDC2_ADDR, + PCF50626_DCULEDC3_ADDR, + PCF50626_DCULED_DIMMAN_ADDR, + 0,0,0,0, + {NV_TRUE, 0,0,0, 0}, + 0,87,0 + }, + + //RF1 + { + PCF50626PmuSupply_RF1REG, + PCF50626PmuSupply_VBAT, + + PCF50626_RF1REGC1_ADDR, + PCF50626_RF1REGC2_ADDR, + PCF50626_RF1REGC3_ADDR, + 0, + 0,0,0,0, + { + NV_FALSE, + PCF50626_RFXREGOUT_VOLTAGE_MIN_MV, + PCF50626_RFXREGOUT_VOLTAGE_STEP_MV, + PCF50626_RFXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_RF1REG_MV + }, + + PCF50626_RFXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_RFXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_RF1REG_US, + PCF50626_RFXREGOUT_SWITCH_TIME_MICROSEC + }, + + //RF2 + { + PCF50626PmuSupply_RF2REG, + PCF50626PmuSupply_VBAT, + + PCF50626_RF2REGC1_ADDR, + PCF50626_RF2REGC2_ADDR, + PCF50626_RF2REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_RFXREGOUT_VOLTAGE_MIN_MV, + PCF50626_RFXREGOUT_VOLTAGE_STEP_MV, + PCF50626_RFXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_RF2REG_MV + }, + + PCF50626_RFXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_RFXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_RF2REG_US, + PCF50626_RFXREGOUT_SWITCH_TIME_MICROSEC + }, + + //RF3 + { + PCF50626PmuSupply_RF3REG, + PCF50626PmuSupply_VBAT, + + PCF50626_RF3REGC1_ADDR, + PCF50626_RF3REGC2_ADDR, + PCF50626_RF3REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_RFXREGOUT_VOLTAGE_MIN_MV, + PCF50626_RFXREGOUT_VOLTAGE_STEP_MV, + PCF50626_RFXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_RF3REG_MV + }, + + PCF50626_RFXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_RFXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_RF3REG_US, + PCF50626_RFXREGOUT_SWITCH_TIME_MICROSEC + }, + + //RF4 + { + PCF50626PmuSupply_RF4REG, + PCF50626PmuSupply_VBAT, + + PCF50626_RF4REGC1_ADDR, + PCF50626_RF4REGC2_ADDR, + PCF50626_RF4REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_RFXREGOUT_VOLTAGE_MIN_MV, + PCF50626_RFXREGOUT_VOLTAGE_STEP_MV, + PCF50626_RFXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_RF4REG_MV + }, + + PCF50626_RFXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_RFXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_RF4REG_US, + PCF50626_RFXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D1 + { + PCF50626PmuSupply_D1REG, + PCF50626PmuSupply_DCUD, + + PCF50626_D1REGC1_ADDR, + PCF50626_D1REGC2_ADDR, + PCF50626_D1REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D1REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D1REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D2 + { + PCF50626PmuSupply_D2REG, + PCF50626PmuSupply_DCUD, + PCF50626_D2REGC1_ADDR, + PCF50626_D2REGC2_ADDR, + PCF50626_D2REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D2REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D2REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D3 + { + PCF50626PmuSupply_D3REG, + PCF50626PmuSupply_DCD2, + + PCF50626_D3REGC1_ADDR, + PCF50626_D3REGC2_ADDR, + PCF50626_D3REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D3REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D3REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D4 + { + PCF50626PmuSupply_D4REG, + PCF50626PmuSupply_DCD2, + + PCF50626_D4REGC1_ADDR, + PCF50626_D4REGC2_ADDR, + PCF50626_D4REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D4REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D4REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D5 + { + PCF50626PmuSupply_D5REG, + PCF50626PmuSupply_VBAT, + + PCF50626_D5REGC1_ADDR, + PCF50626_D5REGC2_ADDR, + PCF50626_D5REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D5REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D5REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D6 + { + PCF50626PmuSupply_D6REG, + PCF50626PmuSupply_VBAT, + + PCF50626_D6REGC1_ADDR, + PCF50626_D6REGC2_ADDR, + PCF50626_D6REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D6REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D6REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D7 + { + PCF50626PmuSupply_D7REG, + PCF50626PmuSupply_VBAT, + + PCF50626_D7REGC1_ADDR, + PCF50626_D7REGC2_ADDR, + PCF50626_D7REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D7REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D7REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //D8 + { + PCF50626PmuSupply_D8REG, + PCF50626PmuSupply_VBAT, + + PCF50626_D8REGC1_ADDR, + PCF50626_D8REGC2_ADDR, + PCF50626_D8REGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_DXREGOUT_VOLTAGE_MIN_MV, + PCF50626_DXREGOUT_VOLTAGE_STEP_MV, + PCF50626_DXREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_D8REG_MV + }, + + PCF50626_DXREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_DXREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_D8REG_US, + PCF50626_DXREGOUT_SWITCH_TIME_MICROSEC + }, + + //HCREG + { + PCF50626PmuSupply_HCREG, + PCF50626PmuSupply_VBAT, + + PCF50626_HCREGC1_ADDR, + PCF50626_HCREGC2_ADDR, + PCF50626_HCREGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_HCREGOUT_VOLTAGE_MIN_MV, + PCF50626_HCREGOUT_VOLTAGE_STEP_MV, + PCF50626_HCREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_HCREG_MV + }, + + PCF50626_HCREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_HCREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_HCREG_US, + PCF50626_HCREGOUT_SWITCH_TIME_MICROSEC + }, + + //IO + { + PCF50626PmuSupply_IOREG, + PCF50626PmuSupply_VBAT, + + PCF50626_IOREGC1_ADDR, + PCF50626_IOREGC2_ADDR, + PCF50626_IOREGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_IOREGOUT_VOLTAGE_MIN_MV, + PCF50626_IOREGOUT_VOLTAGE_STEP_MV, + PCF50626_IOREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_IOREG_MV + }, + + PCF50626_IOREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_IOREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_IOREG_US, + PCF50626_IOREGOUT_SWITCH_TIME_MICROSEC + }, + + //USIM + { + PCF50626PmuSupply_USIMREG, + PCF50626PmuSupply_VBAT, + + PCF50626_USIMREGC1_ADDR, + PCF50626_USIMREGC2_ADDR, + PCF50626_USIMREGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_USIMREGOUT_VOLTAGE_MIN_MV, + PCF50626_USIMREGOUT_VOLTAGE_STEP_MV, + PCF50626_USIMREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_USIMREG_MV + }, + + PCF50626_USIMREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_USIMREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_USIMREG_US, + PCF50626_USIMREGOUT_SWITCH_TIME_MICROSEC + }, + + //USB + { + PCF50626PmuSupply_USBREG, + PCF50626PmuSupply_VBAT, + + PCF50626_USBREGC1_ADDR, + PCF50626_USBREGC2_ADDR, + PCF50626_USBREGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_USBREGOUT_VOLTAGE_MIN_MV, + PCF50626_USBREGOUT_VOLTAGE_STEP_MV, + PCF50626_USBREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_USBREG_MV + }, + + PCF50626_USBREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_USBREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_USBREG_US, + PCF50626_USBREGOUT_SWITCH_TIME_MICROSEC + }, + + //LC + { + PCF50626PmuSupply_LCREG, + PCF50626PmuSupply_VBAT, + + PCF50626_LCREGC1_ADDR, + PCF50626_LCREGC2_ADDR, + PCF50626_LCREGC3_ADDR, + 0, + 0,0,0,0, + + { + NV_FALSE, + PCF50626_LCREGOUT_VOLTAGE_MIN_MV, + PCF50626_LCREGOUT_VOLTAGE_STEP_MV, + PCF50626_LCREGOUT_VOLTAGE_MAX_MV, + PCF50626_REQUESTVOLTAGE_LCREG_MV + }, + + PCF50626_LCREGOUT_VOLTAGE_OFFSET_MV, + PCF50626_LCREGOUT_TURNON_TIME_MICROSEC + PCF50626_TURNON_DELAY_LCREG_US, + PCF50626_LCREGOUT_SWITCH_TIME_MICROSEC + }, + + //VBAT + { + PCF50626PmuSupply_VBAT, + PCF50626PmuSupply_Invalid, + + 0,0,0,0, + 0,0,0,0, + + {NV_TRUE,0,0,0,0}, + 0,0,0 + } +}; + +#define PCF50626SUPPLYINFOTABLESIZE NV_ARRAY_SIZE(pcf50626SupplyInfoTable) + +#endif //PCF50626_VOLTAGE_INFO_TABLE_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/platform.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/platform.c new file mode 100644 index 000000000000..dee9641eef7c --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pcf50626/platform.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "pcf50626_batterycharger.h" +#include "pcf50626_adc.h" +#include "pcf50626_i2c.h" +#include "pcf50626_reg.h" +#include "ds2482_bridge.h" +#include "ds2482_i2c.h" +#include "nvodm_query_discovery.h" +#include "nvodm_query.h" + +// implementations of platform related functions. + +#define OWI2CGUID NV_ODM_GUID('o','w','i','2','c','_','d','s') +#define BATTERYGUID NV_ODM_GUID('b','a','t','t','_','m','o','t') + +static NvBool ds2482Presented = NV_FALSE; + +/* Initliase all registers that related to battery charger */ +NvBool +Pcf50626BatteryChargerSetup(NvOdmPmuDeviceHandle hDevice) +{ + + NvOdmIoModule I2cModule = NvOdmIoModule_I2c; + NvU32 I2cInstance = 0; + NvU32 I2cAddress = 0; + const NvOdmPeripheralConnectivity *pConnectivity = + NvOdmPeripheralGetGuid(OWI2CGUID); + NV_ASSERT(hDevice); + + if (pConnectivity != NULL) // OwI2c device is in database + { + NvU32 i = 0; + for (i = 0; i < pConnectivity->NumAddress; i ++) + { + if (pConnectivity->AddressList[i].Interface == NvOdmIoModule_I2c_Pmu) + { + I2cModule = NvOdmIoModule_I2c_Pmu; + I2cInstance = pConnectivity->AddressList[i].Instance; + I2cAddress = pConnectivity->AddressList[i].Address; + break; + } + } + ds2482Presented = NV_TRUE; + } + else + { + ds2482Presented = NV_FALSE; + } + + if (ds2482Presented == NV_TRUE) + { + // init GPIO8 + if (!Pcf50626I2cWrite8(hDevice, PCF50626_GPIO8C1_ADDR, 0x0)) + return NV_FALSE; + + NvOdmOsWaitUS(50000); + + if (!Ds2482Setup(hDevice)) + return NV_FALSE; + + return NV_TRUE; + } + + //TODO: add battery charger setup implementation here, base on HW. + // by default, simply return TRUE if nothing needed. + return NV_TRUE; +} + + +/* check CBC main batt presence */ +NvBool +Pcf50626BatteryChargerCBCMainBatt(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + const NvOdmPeripheralConnectivity *pConnectivity = + NvOdmPeripheralGetGuid(BATTERYGUID); + + NV_ASSERT(hDevice); + + if (pConnectivity != NULL) // battery is in database + { + ///TODO: retrieve data from the database; + //Nothing needed on Concorde for now + } + + if (ds2482Presented == NV_TRUE) + { + if (!Ds2482BatteryPresented(hDevice, status)) + return NV_FALSE; + } + else + { + //TODO: add battery detection impelentation here. by default always return TRUE. + *status = NV_TRUE; + } + + return NV_TRUE; +} + +/* Calculate the battery temperature */ +NvU32 Pcf50626BatteryTemperature(NvU32 VBatSense, NvU32 VBatTemp) +{ + //TODO: implement the temperature algorithm based on the reading of Vbat sense and VBat temp. + // Pending approval. + return 0; +} + + +NvBool +Ds2482BatteryPresented(NvOdmPmuDeviceHandle hDevice, NvBool *BattPresence) +{ + ///TODO: detect battery via ds2482 based on the battery spec. + ///Pending approval + return NV_TRUE; +} + + + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c new file mode 100644 index 000000000000..ec62ac6c4c17 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvcommon.h" +#include "nvodm_pmu.h" +#include "nvodm_query_discovery.h" +#include "pmu_hal.h" +#include "nvodm_services.h" +#include "tps6586x/nvodm_pmu_tps6586x.h" +#include "max8907b/max8907b.h" +#include "max8907b/max8907b_rtc.h" +#include "pcf50626/pcf50626.h" +#include "pcf50626/pcf50626_rtc.h" + +static NvOdmPmuDevice* +GetPmuInstance(NvOdmPmuDeviceHandle hDevice) +{ + static NvOdmPmuDevice Pmu; + static NvBool first = NV_TRUE; + + if (first) + { + NvOdmOsMemset(&Pmu, 0, sizeof(Pmu)); + first = NV_FALSE; + + if (NvOdmPeripheralGetGuid(NV_ODM_GUID('t','p','s','6','5','8','6','x'))) + { + // fill in HAL functions here. + Pmu.Hal = NV_TRUE; + Pmu.pfnSetup = Tps6586xSetup; + Pmu.pfnRelease = Tps6586xRelease; + Pmu.pfnGetCaps = Tps6586xGetCapabilities; + Pmu.pfnGetVoltage = Tps6586xGetVoltage; + Pmu.pfnSetVoltage = Tps6586xSetVoltage; + Pmu.pfnGetAcLineStatus = Tps6586xGetAcLineStatus; + Pmu.pfnGetBatteryStatus = Tps6586xGetBatteryStatus; + Pmu.pfnGetBatteryData = Tps6586xGetBatteryData; + Pmu.pfnGetBatteryFullLifeTime = Tps6586xGetBatteryFullLifeTime; + Pmu.pfnGetBatteryChemistry = Tps6586xGetBatteryChemistry; + Pmu.pfnSetChargingCurrent = Tps6586xSetChargingCurrent; + Pmu.pfnInterruptHandler = Tps6586xInterruptHandler; + Pmu.pfnReadRtc = Tps6586xReadRtc; + Pmu.pfnWriteRtc = Tps6586xWriteRtc; + Pmu.pfnIsRtcInitialized = Tps6586xIsRtcInitialized; + } + else if (NvOdmPeripheralGetGuid(NV_ODM_GUID('p','c','f','_','p','m','u','0'))) + { + + Pmu.pfnSetup = Pcf50626Setup; + Pmu.pfnRelease = Pcf50626Release; + Pmu.pfnGetCaps = Pcf50626GetCapabilities; + Pmu.pfnGetVoltage = Pcf50626GetVoltage; + Pmu.pfnSetVoltage = Pcf50626SetVoltage; + Pmu.pfnGetAcLineStatus = Pcf50626GetAcLineStatus; + Pmu.pfnGetBatteryStatus = Pcf50626GetBatteryStatus; + Pmu.pfnGetBatteryData = Pcf50626GetBatteryData; + Pmu.pfnGetBatteryFullLifeTime = Pcf50626GetBatteryFullLifeTime; + Pmu.pfnGetBatteryChemistry = Pcf50626GetBatteryChemistry; + Pmu.pfnSetChargingCurrent = Pcf50626SetChargingCurrent; + Pmu.pfnInterruptHandler = Pcf50626InterruptHandler; + Pmu.pfnReadRtc = Pcf50626RtcCountRead; + Pmu.pfnWriteRtc = Pcf50626RtcCountWrite; + Pmu.pfnIsRtcInitialized = Pcf50626IsRtcInitialized; + Pmu.pPrivate = NULL; + Pmu.Hal = NV_TRUE; + Pmu.Init = NV_FALSE; + } + else if (NvOdmPeripheralGetGuid(NV_ODM_GUID('m','a','x','8','9','0','7','b'))) + { + + Pmu.pfnSetup = Max8907bSetup; + Pmu.pfnRelease = Max8907bRelease; + Pmu.pfnGetCaps = Max8907bGetCapabilities; + Pmu.pfnGetVoltage = Max8907bGetVoltage; + Pmu.pfnSetVoltage = Max8907bSetVoltage; + Pmu.pfnGetAcLineStatus = Max8907bGetAcLineStatus; + Pmu.pfnGetBatteryStatus = Max8907bGetBatteryStatus; + Pmu.pfnGetBatteryData = Max8907bGetBatteryData; + Pmu.pfnGetBatteryFullLifeTime = Max8907bGetBatteryFullLifeTime; + Pmu.pfnGetBatteryChemistry = Max8907bGetBatteryChemistry; + Pmu.pfnSetChargingCurrent = Max8907bSetChargingCurrent; + Pmu.pfnInterruptHandler = Max8907bInterruptHandler; + Pmu.pfnReadRtc = Max8907bRtcCountRead; + Pmu.pfnWriteRtc = Max8907bRtcCountWrite; + Pmu.pfnIsRtcInitialized = Max8907bIsRtcInitialized; + Pmu.pPrivate = NULL; + Pmu.Hal = NV_TRUE; + Pmu.Init = NV_FALSE; + } + } + + if (hDevice && Pmu.Hal) + return &Pmu; + + return NULL; +} + +NvBool +NvOdmPmuDeviceOpen(NvOdmPmuDeviceHandle *hDevice) +{ + NvOdmPmuDevice *pmu = GetPmuInstance((NvOdmPmuDeviceHandle)1); + + *hDevice = (NvOdmPmuDeviceHandle)0; + + if (!pmu || !pmu->pfnSetup) + return NV_FALSE; + + if (pmu->Init) + { + *hDevice = (NvOdmPmuDeviceHandle)1; + return NV_TRUE; + } + + if (pmu->pfnSetup(pmu)) + { + *hDevice = (NvOdmPmuDeviceHandle)1; + pmu->Init = NV_TRUE; + return NV_TRUE; + } + + return NV_FALSE; +} + +void NvOdmPmuDeviceClose(NvOdmPmuDeviceHandle hDevice) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (!pmu) + return; + + if (pmu->pfnRelease) + pmu->pfnRelease(pmu); + + pmu->Init = NV_FALSE; +} + +void +NvOdmPmuGetCapabilities(NvU32 vddId, + NvOdmPmuVddRailCapabilities* pCapabilities) +{ + // use a manual handle, since this function doesn't takea handle + NvOdmPmuDevice* pmu = GetPmuInstance((NvOdmPmuDeviceHandle)1); + + if (pmu && pmu->pfnGetCaps) + pmu->pfnGetCaps(vddId, pCapabilities); + else if (pCapabilities) + { + NvOdmOsMemset(pCapabilities, 0, sizeof(NvOdmPmuVddRailCapabilities)); + pCapabilities->OdmProtected = NV_TRUE; + } +} + + +NvBool +NvOdmPmuGetVoltage(NvOdmPmuDeviceHandle hDevice, + NvU32 vddId, + NvU32* pMilliVolts) +{ + NvOdmPmuDevice* pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnGetVoltage) + return pmu->pfnGetVoltage(pmu, vddId, pMilliVolts); + + return NV_TRUE; +} + +NvBool +NvOdmPmuSetVoltage(NvOdmPmuDeviceHandle hDevice, + NvU32 VddId, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnSetVoltage) + { + return pmu->pfnSetVoltage(pmu, VddId, MilliVolts, pSettleMicroSeconds); + } + + if (pSettleMicroSeconds) + *pSettleMicroSeconds = 0; + return NV_TRUE; +} + + +NvBool +NvOdmPmuGetAcLineStatus(NvOdmPmuDeviceHandle hDevice, + NvOdmPmuAcLineStatus *pStatus) +{ + NvOdmPmuDevice* pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnGetAcLineStatus) + return pmu->pfnGetAcLineStatus(pmu, pStatus); + + return NV_TRUE; +} + + +NvBool +NvOdmPmuGetBatteryStatus(NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance BatteryInst, + NvU8 *pStatus) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnGetBatteryStatus) + return pmu->pfnGetBatteryStatus(pmu, BatteryInst, pStatus); + + return NV_TRUE; +} + +NvBool +NvOdmPmuGetBatteryData(NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance BatteryInst, + NvOdmPmuBatteryData *pData) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnGetBatteryData) + return pmu->pfnGetBatteryData(pmu, BatteryInst, pData); + + pData->batteryLifePercent = NVODM_BATTERY_DATA_UNKNOWN; + pData->batteryLifeTime = NVODM_BATTERY_DATA_UNKNOWN; + pData->batteryVoltage = NVODM_BATTERY_DATA_UNKNOWN; + pData->batteryCurrent = NVODM_BATTERY_DATA_UNKNOWN; + pData->batteryAverageCurrent = NVODM_BATTERY_DATA_UNKNOWN; + pData->batteryAverageInterval = NVODM_BATTERY_DATA_UNKNOWN; + pData->batteryMahConsumed = NVODM_BATTERY_DATA_UNKNOWN; + pData->batteryTemperature = NVODM_BATTERY_DATA_UNKNOWN; + + return NV_TRUE; +} + + +void +NvOdmPmuGetBatteryFullLifeTime(NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance BatteryInst, + NvU32 *pLifeTime) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnGetBatteryFullLifeTime) + pmu->pfnGetBatteryFullLifeTime(pmu, BatteryInst, pLifeTime); + + else + { + if (pLifeTime) + *pLifeTime = NVODM_BATTERY_DATA_UNKNOWN; + } +} + + +void +NvOdmPmuGetBatteryChemistry(NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance BatteryInst, + NvOdmPmuBatteryChemistry *pChemistry) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnGetBatteryChemistry) + pmu->pfnGetBatteryChemistry(pmu, BatteryInst, pChemistry); + else + { + if (pChemistry) + *pChemistry = NVODM_BATTERY_DATA_UNKNOWN; + } +} + +NvBool +NvOdmPmuSetChargingCurrent(NvOdmPmuDeviceHandle hDevice, + NvOdmPmuChargingPath ChargingPath, + NvU32 ChargingCurrentLimitMa, + NvOdmUsbChargerType ChargerType) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnSetChargingCurrent) + return pmu->pfnSetChargingCurrent(pmu, ChargingPath, ChargingCurrentLimitMa, ChargerType); + + return NV_TRUE; +} + + +void NvOdmPmuInterruptHandler(NvOdmPmuDeviceHandle hDevice) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnInterruptHandler) + pmu->pfnInterruptHandler(pmu); +} + +NvBool NvOdmPmuReadRtc( + NvOdmPmuDeviceHandle hDevice, + NvU32 *Count) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnReadRtc) + return pmu->pfnReadRtc(pmu, Count); + return NV_FALSE; +} + + +NvBool NvOdmPmuWriteRtc( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnWriteRtc) + return pmu->pfnWriteRtc(pmu, Count); + return NV_FALSE; +} + +NvBool +NvOdmPmuIsRtcInitialized(NvOdmPmuDeviceHandle hDevice) +{ + NvOdmPmuDevice *pmu = GetPmuInstance(hDevice); + + if (pmu && pmu->pfnIsRtcInitialized) + return pmu->pfnIsRtcInitialized(pmu); + + return NV_FALSE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h new file mode 100644 index 000000000000..05cdea828a20 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/pmu_hal.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * <b>NVIDIA Tegra ODM Kit: + * Abstraction layer stub for audio codec adaptations</b> + */ + +#ifndef INCLUDED_NVODM_PMU_ADAPTATION_HAL_H +#define INCLUDED_NVODM_PMU_ADAPTATION_HAL_H + +#include "nvcommon.h" +#include "nvodm_pmu.h" +#include "nvodm_services.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef NvBool (*pfnPmuSetup)(NvOdmPmuDeviceHandle); +typedef void (*pfnPmuRelease)(NvOdmPmuDeviceHandle); +typedef void (*pfnPmuGetCaps)(NvU32, NvOdmPmuVddRailCapabilities*); +typedef NvBool (*pfnPmuGetVoltage)(NvOdmPmuDeviceHandle, NvU32, NvU32*); +typedef NvBool (*pfnPmuSetVoltage)(NvOdmPmuDeviceHandle, NvU32, NvU32, NvU32*); +typedef NvBool (*pfnPmuGetAcLineStatus)(NvOdmPmuDeviceHandle, NvOdmPmuAcLineStatus*); +typedef NvBool (*pfnPmuGetBatteryStatus)(NvOdmPmuDeviceHandle, NvOdmPmuBatteryInstance, NvU8*); +typedef NvBool (*pfnPmuGetBatteryData)(NvOdmPmuDeviceHandle, NvOdmPmuBatteryInstance, NvOdmPmuBatteryData*); +typedef void (*pfnPmuGetBatteryFullLifeTime)(NvOdmPmuDeviceHandle, NvOdmPmuBatteryInstance, NvU32*); +typedef void (*pfnPmuGetBatteryChemistry)(NvOdmPmuDeviceHandle, NvOdmPmuBatteryInstance, NvOdmPmuBatteryChemistry*); +typedef NvBool (*pfnPmuSetChargingCurrent)(NvOdmPmuDeviceHandle, NvOdmPmuChargingPath, NvU32, NvOdmUsbChargerType); +typedef void (*pfnPmuInterruptHandler)(NvOdmPmuDeviceHandle); +typedef NvBool (*pfnPmuReadRtc)(NvOdmPmuDeviceHandle, NvU32*); +typedef NvBool (*pfnPmuWriteRtc)(NvOdmPmuDeviceHandle, NvU32); +typedef NvBool (*pfnPmuIsRtcInitialized)(NvOdmPmuDeviceHandle); + +typedef struct NvOdmPmuDeviceRec +{ + pfnPmuSetup pfnSetup; + pfnPmuRelease pfnRelease; + pfnPmuGetCaps pfnGetCaps; + pfnPmuGetVoltage pfnGetVoltage; + pfnPmuSetVoltage pfnSetVoltage; + pfnPmuGetAcLineStatus pfnGetAcLineStatus; + pfnPmuGetBatteryStatus pfnGetBatteryStatus; + pfnPmuGetBatteryData pfnGetBatteryData; + pfnPmuGetBatteryFullLifeTime pfnGetBatteryFullLifeTime; + pfnPmuGetBatteryChemistry pfnGetBatteryChemistry; + pfnPmuSetChargingCurrent pfnSetChargingCurrent; + pfnPmuInterruptHandler pfnInterruptHandler; + pfnPmuReadRtc pfnReadRtc; + pfnPmuWriteRtc pfnWriteRtc; + pfnPmuIsRtcInitialized pfnIsRtcInitialized; + void *pPrivate; + NvBool Hal; + NvBool Init; +} NvOdmPmuDevice; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/Makefile new file mode 100644 index 000000000000..3b4770addf96 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/Makefile @@ -0,0 +1,18 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x + +obj-y += nvodm_pmu_tps6586x.o +obj-y += nvodm_pmu_tps6586x_adc.o +obj-y += nvodm_pmu_tps6586x_batterycharger.o +obj-y += nvodm_pmu_tps6586x_i2c.o +obj-y += nvodm_pmu_tps6586x_interrupt.o +obj-y += nvodm_pmu_tps6586x_rtc.o diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c new file mode 100644 index 000000000000..197a2c227e1d --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.c @@ -0,0 +1,2036 @@ + +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_query_discovery.h" +#include "nvodm_query.h" +#include "nvodm_query_gpio.h" +#include "nvodm_pmu_tps6586x_i2c.h" +#include "nvodm_pmu_tps6586x_interrupt.h" +#include "nvodm_pmu_tps6586x_batterycharger.h" +#include "nvodm_pmu_tps6586x_adc.h" +#include "nvodm_pmu_tps6586x_rtc.h" +#include "pmu_hal.h" + +/************************************************************************** + * NOTE: + * + Please search "FIXME" and then change the code according to your tps6586x fuse + * * each LDO's voltage range and default value + * * each SM's voltage range and default value + * * Interrupt Masks + * + Battery settings + **************************************************************************/ + +/************************************************************************** + * TPS6586x has two sets of power supliers: + * + 3 DC/DC converters: DCD0/1/2 + * + 11 Regulators: LDO0-9 and RTC_OUT + * Besides that, TPS6586x has + * + 2 sets drivers for LED or other open drain outputs + * + 1 dedicated driver for keyboard backlight LED + * + 1 dedicated driver for external vibrator motor + * + 1 dedicated driver for white LED(SM3) + **************************************************************************/ + +NvBool pmuPresented; +NvBool battPresence; +NvBool pmuInterruptSupported; +TPS6586xStatus pmuStatus; +NvOdmPmuDeviceTPS *hPmu; + + +// threshold for battery status. need to fine tune based on battery/system characterisation +#define NVODM_BATTERY_FULL_VOLTAGE_MV 4200 +#define NVODM_BATTERY_HIGH_VOLTAGE_MV 3900 +#define NVODM_BATTERY_LOW_VOLTAGE_MV 3300 +#define NVODM_BATTERY_CRITICAL_VOLTAGE_MV 3100 + +#define DUMB_CHARGER_LIMIT_MA 250 +#define DEDICATED_CHARGER_LIMIT_MA 1000 // 1000mA for dedicated charger + +#define T_START_TIME 210 +#define K_RAMP 7 + +/* + Only 4 options for charger current; Page36 + According to TPS658x spec, the charge current = scaling factor / R_ISET. + From the schematic, R_ISET shows "1K". So the charge current = scaling factor. + Because the min value of the scaling factor is 0.25 and the R_ISET is fixed, + the min charging current = 0.25 / 1 = 0.25 A = 250 mA. + Thus, it will only support 1000mA, 750mA, 500mA, 250mA. + TODO: In future, we need to change to the actual R_IST value +*/ +#define R_IST 1000 +#define MAX_CHARGING_CURRENT 1000000/R_IST +#define L1_CHARGING_CURRENT 750 +#define L2_CHARGING_CURRENT 500 +#define L3_CHARGING_CURRENT 250 + +/* Valtage tables for LDOs */ +/* FIXME: Modify those tables according to your fuse */ +static const NvU32 VLDOx[] = {1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300}; +static const NvU32 VLDO2[] = { 725, 750, 775, 800, 825, 850, 875, 900, + 925, 950, 975, 1000, 1025, 1050, 1075, 1100, + 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, + 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500}; +/* FIXME tps65860 only */ +static const NvU32 VLDO4[] = {1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875, + 1900, 1925, 1950, 1975, 2000, 2000, 2000, 2000, + 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, + 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000}; + +typedef NvU32 (*TPS6586xPmuVoltageFunc)(const NvU32 bits); +typedef NvBool (*TPS6586xPmuRailCtrlFunc)(const NvU32 rail, NvBool enable); + +typedef struct { + NvU8 addr; + NvU8 start; + NvU8 bits; + NvU8 flag; /*!< see each settings */ +} TPS6586xPmuRegisterInfo; + +typedef struct TPS6586xPmuSupplyInfoRec +{ + TPS6586xPmuSupply supply; + + TPS6586xPmuRegisterInfo supplyRegInfo; /*!< Register info to set/get supply voltage */ + TPS6586xPmuRegisterInfo ctrlRegInfo; /*!< Register info to enable/disable supply, flag indicates another addr */ + TPS6586xPmuVoltageFunc getVoltage; /*!< Func to convert register bits to real voltage */ + TPS6586xPmuVoltageFunc setVoltage; /*!< Func to convert real voltage to register bits */ + TPS6586xPmuRailCtrlFunc railControl; /*!< Func to enable/disable output for each rail */ + NvU8 Gpio; /*!< GPIO pin used to enable/disable external supplies */ + + NvOdmPmuVddRailCapabilities cap; + + +} TPS6586xPmuSupplyInfo; + +static NvU32 TPS6586xPmuVoltageGetSM0(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageGetSM1(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageGetSM2(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageGetVLDOx(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageGetVLDO1(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageGetVLDO2(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageGetVLDO4(const NvU32 bits); + +static NvU32 TPS6586xPmuVoltageSetSM0(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageSetSM1(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageSetSM2(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageSetVLDOx(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageSetVLDO1(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageSetVLDO2(const NvU32 bits); +static NvU32 TPS6586xPmuVoltageSetVLDO4(const NvU32 bits); + +/* FIXME: Change getVoltage/setVoltage according to your fuse */ +static const TPS6586xPmuSupplyInfo tps6586xSupplyInfoTable[] = +{ + { + TPS6586xPmuSupply_Invalid, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + {NV_TRUE,0,0,0,0}, + }, + + //DCD0 + { + TPS6586xPmuSupply_DCD0, + + {TPS6586x_R26_SM0V1, 0, 5, 0}, + {TPS6586x_R10_SUPPLYENA, 1, 1, TPS6586x_R11_SUPPLYENB}, + TPS6586xPmuVoltageGetSM0, + TPS6586xPmuVoltageSetSM0, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 625, 25, 2700, 1200 +#else + 900, 25, 1200, 1200 +#endif + }, + }, + + //DCD1 + { + TPS6586xPmuSupply_DCD1, + + {TPS6586x_R23_SM1V1, 0, 5, 0}, + {TPS6586x_R10_SUPPLYENA, 0, 1, TPS6586x_R11_SUPPLYENB}, + TPS6586xPmuVoltageGetSM1, + TPS6586xPmuVoltageSetSM1, + NULL, + TPS6586x_RFF_INVALID, + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 625, 25, 2700, 1000 +#else + 1800, 0, 1800, 1800 +#endif + }, + }, + + //DCD2 + { + TPS6586xPmuSupply_DCD2, + + {TPS6586x_R42_SUPPLYV2, 0, 5, 0}, + {TPS6586x_R12_SUPPLYENC, 7, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetSM2, + TPS6586xPmuVoltageSetSM2, + NULL, + TPS6586x_RFF_INVALID, + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 3000, 50, 4550, 3700 +#else + 3000, 50, 4550, 3250 // fixme +#endif + }, + }, + + // LD00 + { + TPS6586xPmuSupply_LDO0, + + {TPS6586x_R41_SUPPLYV1, 5, 3, 0}, + {TPS6586x_R12_SUPPLYENC, 0, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 3300 +#else + 2800, 0, 2800, 2800 +#endif + }, + }, + + // LD01 - V-1V2 + { + TPS6586xPmuSupply_LDO1, + + {TPS6586x_R41_SUPPLYV1, 0, 5, 0}, + {TPS6586x_R12_SUPPLYENC, 1, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetVLDO1, + TPS6586xPmuVoltageSetVLDO1, + NULL, + TPS6586x_RFF_INVALID, + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 725, 25, 1500, 1100 +#else + 1200, 0, 1200, 1200 +#endif + }, + }, + + //LD02 - V-RTC + { + TPS6586xPmuSupply_LDO2, + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + {TPS6586x_R2F_LDO2BV1, 0, 5, 0}, +#else + {TPS6586x_R29_LDO2AV1, 0, 5, 0}, +#endif + {TPS6586x_R10_SUPPLYENA, 2, 2, TPS6586x_R11_SUPPLYENB}, + TPS6586xPmuVoltageGetVLDO2, + TPS6586xPmuVoltageSetVLDO2, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 725, 25, 1500, 1200 +#else + 900, 25, 1200, 1200 +#endif + }, + }, + + //LDO3 + { + TPS6586xPmuSupply_LDO3, + + {TPS6586x_R44_SUPPLYV4, 0, 3, 0}, + {TPS6586x_R12_SUPPLYENC, 2, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 3300 +#else + 1800, 0, 1800, 1800 +#endif + }, + }, + + //LDO4 + { + TPS6586xPmuSupply_LDO4, + + {TPS6586x_R32_LDO4V1, 0, 5, 0}, + {TPS6586x_R12_SUPPLYENC, 3, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetVLDO4, + TPS6586xPmuVoltageSetVLDO4, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1700, 25, 2000, 1800 +#else + 1800, 0, 1800, 1800 +#endif + }, + }, + + //LDO5 + { + TPS6586xPmuSupply_LDO5, + + {TPS6586x_R46_SUPPLYV6, 0, 3, 0}, + {TPS6586x_R14_SUPPLYENE, 6, 1, TPS6586x_RFF_INVALID}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 2850 +#else + 2800, 0, 2800, 2800 +#endif + }, + }, + + //LDO6 - V-3V3 USB + { + TPS6586xPmuSupply_LDO6, + + {TPS6586x_R43_SUPPLYV3, 0, 3, 0}, + {TPS6586x_R12_SUPPLYENC, 4, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 2850 +#else + 3300, 0, 3300, 3300 +#endif + }, + }, + + //LDO7 - V-SDIO + { + TPS6586xPmuSupply_LDO7, + + {TPS6586x_R43_SUPPLYV3, 3, 3, 0}, + {TPS6586x_R12_SUPPLYENC, 5, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 3300 +#else + 2800, 0, 2800, 2800 +#endif + }, + }, + + //LDO8 - V-2V8 + { + TPS6586xPmuSupply_LDO8, + + {TPS6586x_R42_SUPPLYV2, 5, 3, 0}, + {TPS6586x_R12_SUPPLYENC, 6, 1, TPS6586x_R13_SUPPLYEND}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 1800 +#else + 2800, 0, 2800, 2800 +#endif + }, + }, + + //LDO9 + { + TPS6586xPmuSupply_LDO9, + + {TPS6586x_R46_SUPPLYV6, 3, 3, 0}, + {TPS6586x_R14_SUPPLYENE, 7, 1, TPS6586x_RFF_INVALID}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 2850 +#else + 2500, 0, 2500, 2500, +#endif + }, + }, + + //RTC_OUT + { + TPS6586xPmuSupply_RTC_OUT, + + {TPS6586x_R44_SUPPLYV4, 3, 3, 0}, + {TPS6586x_RFF_INVALID, 0, 0, TPS6586x_RFF_INVALID}, + TPS6586xPmuVoltageGetVLDOx, + TPS6586xPmuVoltageSetVLDOx, + NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + 1250, 25, 3350, 3300 +#else + 2500, 0, 2500, 2500 +#endif + }, + }, + + + //RED1 + { + TPS6586xPmuSupply_RED1, + + {TPS6586x_R51_RGB1RED, 0, 5, 0}, + {TPS6586x_R52_RGB1GREEN, 7, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, + 0, 1, 0x1f, 0 + }, + }, + + //GREEN1 + { + TPS6586xPmuSupply_GREEN1, + + {TPS6586x_R52_RGB1GREEN, 0, 5, 0}, + {TPS6586x_R52_RGB1GREEN, 7, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, + 0, 1, 0x1f, 0 + }, + }, + + //BLUE1 + { + TPS6586xPmuSupply_BLUE1, + + {TPS6586x_R53_RGB1BLUE, 0, 5, 0}, + {TPS6586x_R52_RGB1GREEN, 7, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, + 0, 1, 0x1f, 0 + }, + }, + + //RED2 + { + TPS6586xPmuSupply_RED2, + + {TPS6586x_R54_RGB2RED, 0, 5, 0}, + {TPS6586x_R55_RGB2GREEN, 7, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, + 0, 1, 0x1f, 0 + }, + }, + + //GREEN2 + { + TPS6586xPmuSupply_GREEN2, + + {TPS6586x_R55_RGB2GREEN, 0, 5, 0}, + {TPS6586x_R55_RGB2GREEN, 7, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, + 0, 1, 0x1f, 0 + }, + }, + + //BLUE2 + { + TPS6586xPmuSupply_BLUE2, + + {TPS6586x_R56_RGB2BLUE, 0, 5, 0}, + {TPS6586x_R55_RGB2GREEN, 7, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, + 0, 1, 0x1f, 0 + }, + }, + + //LED_PWM + { + TPS6586xPmuSupply_LED_PWM, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, /* FIXME: how to get the output */ + {TPS6586x_RFF_INVALID, 0, 0, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_TRUE, + 0, 0, 0, 0 + }, + }, + + //PWM + { + TPS6586xPmuSupply_PWM, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, /* FIXME: how to get the output */ + {TPS6586x_RFF_INVALID, 0, 0, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_TRUE, + 0, 0, 0, 0 + }, + }, + + //White LED(SM3) + { + TPS6586xPmuSupply_WHITE_LED, + + {TPS6586x_R58_SM3_SET1, 0, 3, 0}, + {TPS6586x_R57_SM3_SET0, 0, 8, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + + { + NV_FALSE, + 25000, 0, 25000, 0 + }, + }, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + { + TPS6586xPmuSupply_SoC, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_R14_SUPPLYENE, 3, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + {NV_FALSE,0,0,0,0}, + }, + // External Supplies + + { + Ext_TPS62290PmuSupply_BUCK, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + 3, + {NV_FALSE,0,1050,1050,1050}, + }, + + { + Ext_TPS72012PmuSupply_LDO, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + 2, + {NV_FALSE,0,1200,1200,1200}, + }, + + { + Ext_TPS74201PmuSupply_LDO, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + 1, + {NV_FALSE,0,1500,1500,1500}, + }, + { + Ext_TPS2051BPmuSupply_VDDIO_VID, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + {NV_FALSE,0,5000,5000,5000}, + }, + + { + Ext_SWITCHPmuSupply_VDDIO_SD, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + {NV_FALSE,0,3300,3300,3300}, + }, + + { + Ext_SWITCHPmuSupply_VDDIO_SDMMC, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + {NV_FALSE,0,3300,3300,3300}, + }, + { + Ext_SWITCHPmuSupply_VDD_BL, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_RFF_INVALID, 0, 0, 0}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + {NV_FALSE,0,11100,11100,11100}, + }, + + { + Ext_SWITCHPmuSupply_VDD_PNL, + + {TPS6586x_RFF_INVALID, 0, 0, 0}, + {TPS6586x_R14_SUPPLYENE, 3, 1, TPS6586x_RFF_INVALID}, + NULL, NULL, NULL, + TPS6586x_RFF_INVALID, + {NV_FALSE,0,3300,3300,3300}, + } +#endif +}; + +static NvU32 TPS6586xPmuVoltageGetSM0(const NvU32 bits) +{ + NV_ASSERT(bits <= 0x1F); + + return (725 + bits * 25); +} + +static NvU32 TPS6586xPmuVoltageGetSM1(const NvU32 bits) +{ + NV_ASSERT(bits <= 0x1F); + +#if defined (CONFIG_TEGRA_ODM_HARMONY) + return (725 + bits * 25); +#else + return (1450 + bits * 50); +#endif +} + +static NvU32 TPS6586xPmuVoltageGetSM2(const NvU32 bits) +{ + NV_ASSERT(bits <= 0x1F); + + return (3000 + bits * 25); +} + +static NvU32 TPS6586xPmuVoltageGetVLDOx(const NvU32 bits) +{ + NV_ASSERT(bits <= 0x7); + + return VLDOx[bits]; +} + +static NvU32 TPS6586xPmuVoltageGetVLDO1(const NvU32 bits) +{ + /* VLDO1 and VLDO2 use the same table. + * See pp. 64 - 66 of TPS658621 data sheet. + */ + NV_ASSERT(bits <= 0x1F); + + return VLDO2[bits]; +} + +static NvU32 TPS6586xPmuVoltageGetVLDO2(const NvU32 bits) +{ + NV_ASSERT(bits <= 0x1F); + return VLDO2[bits]; +} +static NvU32 TPS6586xPmuVoltageGetVLDO4(const NvU32 bits) +{ + NV_ASSERT(bits <= 0x1F); + return VLDO4[bits]; +} + +#ifndef MIN +#define MIN(a, b) (a) <= (b) ? (a) : (b) +#endif + +static NvU32 TPS6586xPmuVoltageSetSM0(const NvU32 millivolts) +{ + if (millivolts < 725) + return 0; + else + return MIN((millivolts - 725) / 25, 0x1f); +} + +static NvU32 TPS6586xPmuVoltageSetSM1(const NvU32 millivolts) +{ +#if defined(CONFIG_TEGRA_ODM_HARMONY) + if (millivolts < 725) + return 0; + else + return MIN((millivolts - 725) / 25, 0x1f); +#else + if (millivolts < 1450) + return 0; + else + return MIN((millivolts - 1450) / 50, 0x1f); +#endif +} + +static NvU32 TPS6586xPmuVoltageSetSM2(const NvU32 millivolts) +{ + if (millivolts < 3000) + return 0; + else + return MIN((millivolts - 3000) / 25, 0x1f); +} + +#define VOLTAGE_SEARCH(mv, vtbl) \ + const int cnt = sizeof(vtbl)/sizeof(NvU32); \ + int i; \ + for (i=0; i<cnt; i++) \ + { \ + if (mv <= (vtbl)[i]) \ + break; \ + } \ + return MIN(i, cnt-1) + + +static NvU32 TPS6586xPmuVoltageSetVLDOx(const NvU32 millivolts) +{ + VOLTAGE_SEARCH(millivolts, VLDOx); +} + +static NvU32 TPS6586xPmuVoltageSetVLDO1(const NvU32 millivolts) +{ + /* VLDO1 and VLDO2 use the same table. + * See pp. 64 - 66 of TPS658621 data sheet. + */ + VOLTAGE_SEARCH(millivolts, VLDO2); +} + +static NvU32 TPS6586xPmuVoltageSetVLDO2(const NvU32 millivolts) +{ + VOLTAGE_SEARCH(millivolts, VLDO2); +} +static NvU32 TPS6586xPmuVoltageSetVLDO4(const NvU32 millivolts) +{ + VOLTAGE_SEARCH(millivolts, VLDO4); +} + + +void +Tps6586xGetCapabilities( + NvU32 vddRail, + NvOdmPmuVddRailCapabilities* pCapabilities) +{ + NV_ASSERT(pCapabilities); + NV_ASSERT(vddRail < TPS6586xPmuSupply_Num); + + *pCapabilities = tps6586xSupplyInfoTable[vddRail].cap; +} + +#if defined(CONFIG_TEGRA_ODM_HARMONY) +static NvBool g_ExternalSupplyEnabled[TPS6586x_EXTERNAL_SUPPLY_NUM] = { 0 }; + +static NvBool +Tps6586xGetExternalSupply( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + if (g_ExternalSupplyEnabled[vddRail - (NvU32)(Ext_TPS62290PmuSupply_BUCK)] == NV_TRUE) + *pMilliVolts = tps6586xSupplyInfoTable[vddRail].cap.requestMilliVolts; + else + *pMilliVolts = 0; + + return NV_TRUE; +} +#endif + +static NvBool +Tps6586xReadVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + const TPS6586xPmuSupplyInfo *pSupplyInfo = &tps6586xSupplyInfoTable[vddRail]; + NvU32 data = 0; + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + // External supplies are fixed. + if ((vddRail == Ext_TPS62290PmuSupply_BUCK) || + (vddRail == Ext_TPS72012PmuSupply_LDO) || + (vddRail == Ext_TPS74201PmuSupply_LDO) || + (vddRail == Ext_TPS2051BPmuSupply_VDDIO_VID) || + (vddRail == Ext_SWITCHPmuSupply_VDDIO_SD) || + (vddRail == Ext_SWITCHPmuSupply_VDDIO_SDMMC) || + (vddRail == Ext_SWITCHPmuSupply_VDD_BL) || + (vddRail == Ext_SWITCHPmuSupply_VDD_PNL)) + { + if (!Tps6586xGetExternalSupply(hDevice, vddRail, pMilliVolts)) + return NV_FALSE; + else + return NV_TRUE; + } +#endif + + if (pSupplyInfo->supplyRegInfo.addr == TPS6586x_RFF_INVALID) + { + return NV_FALSE; + } + + if (! Tps6586xI2cRead8(hDevice, pSupplyInfo->supplyRegInfo.addr, &data)) + return NV_FALSE; + + if (pSupplyInfo->getVoltage) + *pMilliVolts = pSupplyInfo->getVoltage((data >> pSupplyInfo->supplyRegInfo.start) & ((1<<pSupplyInfo->supplyRegInfo.bits)-1)); + else + *pMilliVolts = data; + + Tps6586xI2cRead8(hDevice, pSupplyInfo->ctrlRegInfo.addr, &data); + data &= (((1<<pSupplyInfo->ctrlRegInfo.bits)-1)<<pSupplyInfo->ctrlRegInfo.start); + if (data == 0) + { + //since Voltage table is {1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300} + //need to fill 0 voltage if needed + *pMilliVolts = data; + } + + + return NV_TRUE; +} + +#if 0 +static NvBool +Tps6586xSupplyCtrl( + const NvU32 vddRail, + NvBool ctrl) +{ + return NV_TRUE; +} +#endif + +#if defined(CONFIG_TEGRA_ODM_HARMONY) +#define NVODM_PORT(x) ((x) - 'a') + +static NvBool +Tps6586xSetExternalSupply( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvBool Enable) +{ + const TPS6586xPmuSupplyInfo* pSupplyInfo = &tps6586xSupplyInfoTable[vddRail]; + NvU32 data = 0; + NvU8 Gpio; + NvU32 GpioPort; + NvU32 GpioPin; + + NV_ASSERT((vddRail > TPS6586xPmuSupply_Invalid) && (vddRail < TPS6586xPmuSupply_Num)); + + // FIXME: Clean this up! This includes embedding more of these settings in + // the supply info table to simplify the code. + + // Switched by PMU GPIO + if ((vddRail == Ext_TPS62290PmuSupply_BUCK)|| + (vddRail == Ext_TPS72012PmuSupply_LDO) || + (vddRail == Ext_TPS74201PmuSupply_LDO)) + { + // Set output mode (TEST: FOR GPIO1 only) + + Gpio = pSupplyInfo->Gpio; + switch (Gpio) + { + case 1: + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5D_GPIOSET1, &data)) + return NV_FALSE; + + // Reset mode field + data &= ~(TPS6586x_R5D_GPIOSET1_GPIO1_MODE_MASK << + TPS6586x_R5D_GPIOSET1_GPIO1_MODE_SHIFT); + // Apply new mode setting (output) + data |= (TPS6586x_R5D_GPIO_MODE_OUTPUT << + TPS6586x_R5D_GPIOSET1_GPIO1_MODE_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5D_GPIOSET1, data)) + return NV_FALSE; + + if (Enable) + { + // Enable output + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5E_GPIOSET2, &data)) + return NV_FALSE; + + data |= (TPS6586x_R5E_GPIOSET2_GPIO1_OUT_MASK << + TPS6586x_R5E_GPIOSET2_GPIO1_OUT_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5E_GPIOSET2, data)) + return NV_FALSE; + } + else + { + // Disable output + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5E_GPIOSET2, &data)) + return NV_FALSE; + + data &= ~(TPS6586x_R5E_GPIOSET2_GPIO1_OUT_MASK << + TPS6586x_R5E_GPIOSET2_GPIO1_OUT_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5E_GPIOSET2, data)) + return NV_FALSE; + } + break; + + case 2: + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5D_GPIOSET1, &data)) + return NV_FALSE; + + // Reset mode field + data &= ~(TPS6586x_R5D_GPIOSET1_GPIO2_MODE_MASK << + TPS6586x_R5D_GPIOSET1_GPIO2_MODE_SHIFT); + // Apply new mode setting (output) + data |= (TPS6586x_R5D_GPIO_MODE_OUTPUT << + TPS6586x_R5D_GPIOSET1_GPIO2_MODE_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5D_GPIOSET1, data)) + return NV_FALSE; + + if (Enable) + { + // Enable output + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5E_GPIOSET2, &data)) + return NV_FALSE; + + data |= (TPS6586x_R5E_GPIOSET2_GPIO2_OUT_MASK << + TPS6586x_R5E_GPIOSET2_GPIO2_OUT_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5E_GPIOSET2, data)) + return NV_FALSE; + } + else + { + // Disable output + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5E_GPIOSET2, &data)) + return NV_FALSE; + + data &= ~(TPS6586x_R5E_GPIOSET2_GPIO2_OUT_MASK << + TPS6586x_R5E_GPIOSET2_GPIO2_OUT_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5E_GPIOSET2, data)) + return NV_FALSE; + } + break; + + case 3: + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5D_GPIOSET1, &data)) + return NV_FALSE; + // Reset mode field + data &= ~(TPS6586x_R5D_GPIOSET1_GPIO3_MODE_MASK << + TPS6586x_R5D_GPIOSET1_GPIO3_MODE_SHIFT); + // Apply new mode setting (output) + data |= (TPS6586x_R5D_GPIO_MODE_OUTPUT << + TPS6586x_R5D_GPIOSET1_GPIO3_MODE_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5D_GPIOSET1, data)) + return NV_FALSE; + + if (Enable) + { + // Enable output + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5E_GPIOSET2, &data)) + return NV_FALSE; + + data |= (TPS6586x_R5E_GPIOSET2_GPIO3_OUT_MASK << + TPS6586x_R5E_GPIOSET2_GPIO3_OUT_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5E_GPIOSET2, data)) + return NV_FALSE; + } + else + { + // Disable output + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R5E_GPIOSET2, &data)) + return NV_FALSE; + + data &= ~(TPS6586x_R5E_GPIOSET2_GPIO3_OUT_MASK << + TPS6586x_R5E_GPIOSET2_GPIO3_OUT_SHIFT); + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5E_GPIOSET2, data)) + return NV_FALSE; + } + break; + + default: + return NV_FALSE; // bad parameter + } + } + // Switched by AP GPIO + else + { + // Open GPIO + if (!hPmu->hGpio) + { + hPmu->hGpio = NvOdmGpioOpen(); + + if (!hPmu->hGpio) + return NV_FALSE; + } + + // Get AP GPIO pin assigned to the respective voltage rail + // FIXME: This should be driven by supply info table. + switch (vddRail) + { + case Ext_TPS2051BPmuSupply_VDDIO_VID: + GpioPort = NVODM_PORT('t'); + GpioPin = 2; + break; + + case Ext_SWITCHPmuSupply_VDDIO_SD: + GpioPort = NVODM_PORT('t'); + GpioPin = 3; + break; + + case Ext_SWITCHPmuSupply_VDDIO_SDMMC: + GpioPort = NVODM_PORT('i'); + GpioPin = 6; + break; + + case Ext_SWITCHPmuSupply_VDD_BL: + GpioPort = NVODM_PORT('w'); + GpioPin = 0; + break; + + case Ext_SWITCHPmuSupply_VDD_PNL: + GpioPort = NVODM_PORT('c'); + GpioPin = 6; + break; + + default: + return NV_FALSE; + } + + NV_ASSERT((NVODM_EXT_AP_GPIO_RAIL(vddRail) >= 0) && + (NVODM_EXT_AP_GPIO_RAIL(vddRail) < TPS6586x_EXTERNAL_SUPPLY_AP_GPIO_NUM)); + + // Acquire Pin Handle + if (!hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)]) + { + hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)] = + NvOdmGpioAcquirePinHandle(hPmu->hGpio, GpioPort, GpioPin); + + if (!hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)]) + return NV_FALSE; + } + + if (Enable) + { + if (vddRail == Ext_TPS2051BPmuSupply_VDDIO_VID) + { + NvOdmGpioConfig(hPmu->hGpio, + hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)], + NvOdmGpioPinMode_Tristate); + } + else + { + NvOdmGpioSetState(hPmu->hGpio, + hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)], + NvOdmGpioPinActiveState_High); + + NvOdmGpioConfig(hPmu->hGpio, + hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)], + NvOdmGpioPinMode_Output); + } + } + else + { + if (vddRail != Ext_TPS2051BPmuSupply_VDDIO_VID) + { + NvOdmGpioSetState(hPmu->hGpio, + hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)], + NvOdmGpioPinActiveState_Low); + NvOdmGpioConfig(hPmu->hGpio, + hPmu->hPin[NVODM_EXT_AP_GPIO_RAIL(vddRail)], + NvOdmGpioPinMode_Output); + } + } + } + + // This isn't thread safe, but it's highly unlikely that will be an issue for these rails. + if (Enable) + { + g_ExternalSupplyEnabled[vddRail - (NvU32)(Ext_TPS62290PmuSupply_BUCK)] = NV_TRUE; + } + else + { + g_ExternalSupplyEnabled[vddRail - (NvU32)(Ext_TPS62290PmuSupply_BUCK)] = NV_FALSE; + } + return NV_TRUE; +} +#endif + +static NvBool +Tps6586xWriteVoltageReg( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + const TPS6586xPmuSupplyInfo* pSupplyInfo = &tps6586xSupplyInfoTable[vddRail]; + //const TPS6586xPmuSupplyInfo* pSupplyInputInfo = &tps6586xSupplyInfoTable[pSupplyInfo->supplyInput]; + NvBool status = NV_FALSE; + NvU32 settleTime = 0; +#if !defined(CONFIG_TEGRA_ODM_HARMONY) + NvU32 volChange = 0; +#endif + + NV_ASSERT(pSupplyInfo->supply == (TPS6586xPmuSupply)vddRail); + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + if ((vddRail != Ext_TPS62290PmuSupply_BUCK) && + (vddRail != Ext_TPS72012PmuSupply_LDO) && + (vddRail != Ext_TPS74201PmuSupply_LDO) && + (vddRail != Ext_TPS2051BPmuSupply_VDDIO_VID) && + (vddRail != Ext_SWITCHPmuSupply_VDDIO_SD) && + (vddRail != Ext_SWITCHPmuSupply_VDDIO_SDMMC) && + (vddRail != Ext_SWITCHPmuSupply_VDD_BL) && + (vddRail != Ext_SWITCHPmuSupply_VDD_PNL)) +#endif + { + if (pSupplyInfo->ctrlRegInfo.addr == TPS6586x_RFF_INVALID) + { + NVODMPMU_PRINTF(("TPS:The required ctrl register address is INVALID...\n")); +#if defined(CONFIG_TEGRA_ODM_HARMONY) + return NV_TRUE; + //return NV_FALSE; +#else + return NV_FALSE; +#endif + } + } + + if (MilliVolts == ODM_VOLTAGE_OFF) + { + NvU32 data = 0; + + // check if the supply can be turned off + //NV_ASSERT(hDevice->supplyRefCntTable[vddRail]); + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + // Disable external supplies + if ((vddRail == Ext_TPS62290PmuSupply_BUCK) || + (vddRail == Ext_TPS72012PmuSupply_LDO) || + (vddRail == Ext_TPS74201PmuSupply_LDO) || + (vddRail == Ext_TPS2051BPmuSupply_VDDIO_VID) || + (vddRail == Ext_SWITCHPmuSupply_VDDIO_SD) || + (vddRail == Ext_SWITCHPmuSupply_VDDIO_SDMMC) || + (vddRail == Ext_SWITCHPmuSupply_VDD_BL) || + (vddRail == Ext_SWITCHPmuSupply_VDD_PNL)) + { + status = Tps6586xSetExternalSupply(hDevice, vddRail, NV_FALSE); + } + else +#endif + if (((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->supplyRefCntTable[vddRail] == 1) + { + /* Disable */ + NvOdmServicesPmuSetSocRailPowerState( + ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->hOdmPmuSevice, pSupplyInfo->supply, NV_FALSE); + Tps6586xI2cRead8(hDevice, pSupplyInfo->ctrlRegInfo.addr, &data); +#if defined(CONFIG_TEGRA_ODM_HARMONY) + if (vddRail == TPS6586xPmuSupply_SoC) + { + // SOC Super power rail don't hold the sleep bit + data |= (((1<<pSupplyInfo->ctrlRegInfo.bits)-1)<<pSupplyInfo->ctrlRegInfo.start); + } + else +#endif + { + data &= ~(((1<<pSupplyInfo->ctrlRegInfo.bits)-1)<<pSupplyInfo->ctrlRegInfo.start); + } + status = Tps6586xI2cWrite8(hDevice, pSupplyInfo->ctrlRegInfo.addr, data); +#if defined(CONFIG_TEGRA_ODM_HARMONY) + if (vddRail == TPS6586xPmuSupply_SoC) + { + // Wait 10 secs for PMU to shutdown + NvOdmOsWaitUS(100000000); + } +#endif + + if (status && (pSupplyInfo->ctrlRegInfo.flag != TPS6586x_RFF_INVALID)) + { + status = Tps6586xI2cRead8(hDevice, pSupplyInfo->ctrlRegInfo.flag, &data); + if (status) + { + data &= ~(((1<<pSupplyInfo->ctrlRegInfo.bits)-1)<<pSupplyInfo->ctrlRegInfo.start); + status = Tps6586xI2cWrite8(hDevice, pSupplyInfo->ctrlRegInfo.flag, data); + } + } + + /* Reset to voltage to 0th */ + MilliVolts = 0; + +#if !defined(CONFIG_TEGRA_ODM_HARMONY) + // Calcuate this voltage change + volChange = ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->curVoltageTable[vddRail]; + + ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->curVoltageTable[vddRail] = 0; + + // DCD0/DCD1/DCD2 + if ((vddRail == TPS6586xPmuSupply_DCD0) || + (vddRail == TPS6586xPmuSupply_DCD1) || + (vddRail == TPS6586xPmuSupply_DCD2)) + { + // delay = Tstart(210) + Voltage change/Kramp + settleTime = T_START_TIME + volChange/K_RAMP; + } + else if ((vddRail == TPS6586xPmuSupply_LDO2) || + (vddRail == TPS6586xPmuSupply_LDO4)) + { + // Voltage change/Kramp + settleTime = volChange/K_RAMP; + } + else + { + settleTime = 0; + } +#endif + } + + if (((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->supplyRefCntTable[vddRail] != 0) + { +#if defined(CONFIG_TEGRA_ODM_HARMONY) + if(--((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->supplyRefCntTable[vddRail] != 0) + { + if (pSettleMicroSeconds) + *pSettleMicroSeconds = 0; + return NV_TRUE; + } +#else + --((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->supplyRefCntTable[vddRail]; +#endif + } + +#if !defined(CONFIG_TEGRA_ODM_HARMONY) + if (pSettleMicroSeconds != NULL) + *pSettleMicroSeconds = settleTime; + else + NvOdmOsWaitUS(settleTime); + + return NV_TRUE; +#endif + } + else + { + NvU32 data = 0; + + if (((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->supplyRefCntTable[vddRail]++ == 0) + { + // Enable external supplies +#if defined(CONFIG_TEGRA_ODM_HARMONY) + if ((vddRail == Ext_TPS62290PmuSupply_BUCK) || + (vddRail == Ext_TPS72012PmuSupply_LDO) || + (vddRail == Ext_TPS74201PmuSupply_LDO) || + (vddRail == Ext_TPS2051BPmuSupply_VDDIO_VID) || + (vddRail == Ext_SWITCHPmuSupply_VDDIO_SD) || + (vddRail == Ext_SWITCHPmuSupply_VDDIO_SDMMC) || + (vddRail == Ext_SWITCHPmuSupply_VDD_BL) || + (vddRail == Ext_SWITCHPmuSupply_VDD_PNL)) + { + status = Tps6586xSetExternalSupply(hDevice, vddRail, NV_TRUE); + } + else +#endif + { +#if !defined(CONFIG_TEGRA_ODM_HARMONY) + NvOdmServicesPmuSetSocRailPowerState( + ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->hOdmPmuSevice, pSupplyInfo->supply, NV_TRUE); +#endif + status = Tps6586xI2cRead8(hDevice, pSupplyInfo->ctrlRegInfo.addr, &data); + if (status && ((data >> pSupplyInfo->ctrlRegInfo.start) & 0x1) == 0) + { +#if defined(CONFIG_TEGRA_ODM_HARMONY) + /* Enable */ + NvOdmServicesPmuSetSocRailPowerState( + ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->hOdmPmuSevice, + pSupplyInfo->supply, NV_TRUE); +#endif + data |= (((1<<pSupplyInfo->ctrlRegInfo.bits)-1)<<pSupplyInfo->ctrlRegInfo.start); + if (NV_FALSE == Tps6586xI2cWrite8(hDevice, pSupplyInfo->ctrlRegInfo.addr, data)) +#if defined(CONFIG_TEGRA_ODM_HARMONY) + return NV_TRUE; +#else + return NV_FALSE; +#endif + } + } + } + + /* Disable Flash mode + * FIXME: please check whether you need to disable flash */ + /* + if (vddRail == TPS6586xPmuSupply_RED1 || + vddRail == TPS6586xPmuSupply_GREEN1 || + vddRail == TPS6586xPmuSupply_BLUE1) + { + if (NV_FALSE == Tps6586xI2cWrite8(hDevice, TPS6586x_R50_RGB1FLASH, 0xFF)) + return NV_FALSE; + } + */ + } + + if (pSupplyInfo->supplyRegInfo.addr == TPS6586x_RFF_INVALID) + { +#if defined(CONFIG_TEGRA_ODM_HARMONY) + return NV_TRUE; +#else + return NV_FALSE; +#endif + } + else + { + const int bits = pSupplyInfo->setVoltage ? pSupplyInfo->setVoltage(MilliVolts) : MilliVolts; + NvU32 data = 0; + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + status = Tps6586xI2cRead8(hDevice, pSupplyInfo->supplyRegInfo.addr, &data); + if (NV_FALSE == status) + NVODMPMU_PRINTF(("TPS:Writing to PMU I2C fails 1... supplyaddress: %d\n", pSupplyInfo->supplyRegInfo.addr)); +#else + if ((vddRail == TPS6586xPmuSupply_DCD0) || + (vddRail == TPS6586xPmuSupply_DCD1) || + (vddRail == TPS6586xPmuSupply_LDO4) || + (vddRail == TPS6586xPmuSupply_LDO2)) + { + status = NV_TRUE; + } + else + { + status = Tps6586xI2cRead8(hDevice, pSupplyInfo->supplyRegInfo.addr, &data); + } +#endif + + if (status) + { + data &= ~(((1<<pSupplyInfo->supplyRegInfo.bits)-1)<<pSupplyInfo->supplyRegInfo.start); + data |= (bits << pSupplyInfo->supplyRegInfo.start); + status = Tps6586xI2cWrite8(hDevice, pSupplyInfo->supplyRegInfo.addr, data); + + /* Trigger a voltage change for SM0/SM1/LDO2/LDO4 */ + if ((vddRail == TPS6586xPmuSupply_DCD0) || + (vddRail == TPS6586xPmuSupply_DCD1) || + (vddRail == TPS6586xPmuSupply_LDO4) || + (vddRail == TPS6586xPmuSupply_LDO2)) + { + data = 0; + switch (vddRail) + { + case TPS6586xPmuSupply_LDO2: + data |= (1<<4); + data &= ~(1<<5); + break; + + case TPS6586xPmuSupply_LDO4: + data |= (1<<6); + data &= ~(1<<7); + break; + + case TPS6586xPmuSupply_DCD0: + data |= (1<<2); + data &= ~(1<<3); + break; + + case TPS6586xPmuSupply_DCD1: + data |= (1<<0); + data &= ~(1<<1); + break; + } + status = Tps6586xI2cWrite8(hDevice, TPS6586x_R20_VCC1, data); + } + +#if !defined(CONFIG_TEGRA_ODM_HARMONY) + // Calcuate this voltage change + if (((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->curVoltageTable[vddRail] < MilliVolts) + volChange = MilliVolts - ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->curVoltageTable[vddRail]; + else + volChange = ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->curVoltageTable[vddRail] - MilliVolts; + + ((NvOdmPmuDeviceTPS *)(hDevice->pPrivate))->curVoltageTable[vddRail] = MilliVolts; + + // DCD0/DCD1/DCD2 + if ((vddRail == TPS6586xPmuSupply_DCD0) || + (vddRail == TPS6586xPmuSupply_DCD1) || + (vddRail == TPS6586xPmuSupply_DCD2)) + { + // delay = Tstart(210) + Voltage change/Kramp + settleTime = T_START_TIME + volChange/K_RAMP; + } + else if ((vddRail == TPS6586xPmuSupply_LDO2) || + (vddRail == TPS6586xPmuSupply_LDO4)) + { + // Voltage change/Kramp + settleTime = volChange/K_RAMP; + } + else + { + settleTime = 0; + } +#else + settleTime = 250; +#endif + + if (pSettleMicroSeconds) + *pSettleMicroSeconds = settleTime; + else + NvOdmOsWaitUS(settleTime); + return status; + } + } + + if (pSupplyInfo->supplyRegInfo.addr == TPS6586x_RFF_INVALID) + { +#if defined(CONFIG_TEGRA_ODM_HARMONY) + return NV_TRUE; +#else + return NV_FALSE; +#endif + } + + if (pSettleMicroSeconds) +#if defined(CONFIG_TEGRA_ODM_HARMONY) + *pSettleMicroSeconds = 250; + else + NvOdmOsWaitUS(250); +#else + *pSettleMicroSeconds = 0; +#endif + + return NV_TRUE; +} + +NvBool +Tps6586xGetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32* pMilliVolts) +{ + NV_ASSERT(hDevice); + NV_ASSERT(pMilliVolts); + NV_ASSERT(vddRail < TPS6586xPmuSupply_Num); + + if(! Tps6586xReadVoltageReg(hDevice, vddRail,pMilliVolts)) + return NV_FALSE; + + return NV_TRUE; +} + +NvBool +Tps6586xSetVoltage( + NvOdmPmuDeviceHandle hDevice, + NvU32 vddRail, + NvU32 MilliVolts, + NvU32* pSettleMicroSeconds) +{ + NV_ASSERT(hDevice); + NV_ASSERT(vddRail < TPS6586xPmuSupply_Num); + + if (pSettleMicroSeconds) + *pSettleMicroSeconds = 0; + + if (tps6586xSupplyInfoTable[vddRail].cap.OdmProtected == NV_TRUE) + { + NVODMPMU_PRINTF(("The voltage is protected and can not be set.\n")); + return NV_TRUE; + } + + if ((MilliVolts == ODM_VOLTAGE_OFF) || + ((MilliVolts <= tps6586xSupplyInfoTable[vddRail].cap.MaxMilliVolts) && + (MilliVolts >= tps6586xSupplyInfoTable[vddRail].cap.MinMilliVolts))) + { + if (! Tps6586xWriteVoltageReg(hDevice, vddRail, MilliVolts, pSettleMicroSeconds)) + return NV_FALSE; + } + else + { + NVODMPMU_PRINTF(("The required voltage is not supported..\n")); +#if defined(CONFIG_TEGRA_ODM_HARMONY) + return NV_TRUE; + //return NV_FALSE; +#else + return NV_FALSE; +#endif + } + + return NV_TRUE; +} + +#if 0 +void DumpTps6586x(NvOdmPmuDeviceHandle hDevice) +{ + int i; + NvU32 data; + for (i=0; i<0xFF; i++) + { + data = 0; + Tps6586xI2cRead8(hDevice, i, &data); + NVODMPMU_PRINTF(("Register 0x%x = 0x%x\n", i, data)); + } +} +#endif + +NvBool Tps6586xSetup(NvOdmPmuDeviceHandle hDevice) +{ + NvOdmIoModule I2cModule = NvOdmIoModule_I2c; + NvU32 I2cInstance = 0; + NvU32 I2cAddress = 0; + NvBool status = NV_FALSE; + NvU32 data = 0; +// static TPS6586xDevice s_tps6586x = {0}; + + const NvOdmPeripheralConnectivity *pConnectivity = + NvOdmPeripheralGetGuid(PMUGUID); + + NV_ASSERT(hDevice); + + hPmu = (NvOdmPmuDeviceTPS *)NvOdmOsAlloc(sizeof(NvOdmPmuDeviceTPS)); + if (hPmu == NULL) + { + NVODMPMU_PRINTF(("Error Allocating NvOdmPmuDeviceTPS. \n")); + return NV_FALSE; + } + NvOdmOsMemset(hPmu, 0, sizeof(NvOdmPmuDeviceTPS)); + + hDevice->pPrivate = hPmu; + + if (pConnectivity != NULL) // PMU is in database + { + NvU32 i = 0; + pmuPresented = NV_TRUE; + + for (i = 0; i < pConnectivity->NumAddress; i ++) + { + if (pConnectivity->AddressList[i].Interface == NvOdmIoModule_I2c_Pmu) + { + I2cModule = NvOdmIoModule_I2c_Pmu; + I2cInstance = pConnectivity->AddressList[i].Instance; + I2cAddress = pConnectivity->AddressList[i].Address; + break; + } + } + + NV_ASSERT(I2cModule == NvOdmIoModule_I2c_Pmu); + NV_ASSERT(I2cAddress != 0); + + hPmu->hOdmI2C = NvOdmI2cOpen(I2cModule, I2cInstance); + if (!hPmu->hOdmI2C) + { + NVODMPMU_PRINTF(("[NVODM PMU]Tps6586xSetup: Error Open I2C device. \n")); + NVODMPMU_PRINTF(("[NVODM PMU]Please check PMU device I2C settings. \n")); + goto OPEN_FAILED; + } + hPmu->DeviceAddr = I2cAddress; + hPmu->hOdmPmuSevice = NvOdmServicesPmuOpen(); +#if defined(CONFIG_TEGRA_ODM_HARMONY) + //if (NV_FALSE == Tps6586xWriteVoltageReg(hDevice, TPS6586xPmuSupply_LDO5, 3300, NULL)) + if (NV_FALSE == Tps6586xWriteVoltageReg(hDevice, TPS6586xPmuSupply_LDO5, 2850, NULL)) + NVODMPMU_PRINTF(("TPS: Fail to set the NVDDIO_NAND to 2.85V\n")); + else + NVODMPMU_PRINTF(("TPS: set the NVDDIO_NAND to 2.85V\n")); +#endif + } + else + { + // if PMU is not presented in the database, then the platform is PMU-less. + NVODMPMU_PRINTF(("[NVODM PMU]Tps6586xSetup: The system did not doscover PMU fromthe data base. \n")); + NVODMPMU_PRINTF(("[NVODM PMU]Tps6586xSetup: If this is not intended, please check the peripheral database for PMU settings. \n")); + + //uncomment below line if you really need to run pmu adaptation on pmu-less system. + // the system will run in pmu-less mode. + //pmuPresented = NV_FALSE; + + goto OPEN_FAILED; + } + + //hDevice->priv = &s_tps6586x; + + /* Check Chip Device ID to verify it */ +#if 0 + I2cInstance = 0; + if (!Tps6586xI2cRead8(hDevice, TPS6586x_RCD_VERSIONID, &I2cInstance) || I2cInstance != 0x60) + { + NV_ASSERT(!"did not find TSP6586x"); + goto OPEN_FAILED; + } +#endif + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + /* Initialize the refcont of the rails which are ON by default */ + hPmu->supplyRefCntTable[TPS6586xPmuSupply_SoC] = 1; +#endif + +#if !defined(CONFIG_TEGRA_ODM_HARMONY) + // If your project doesn't use this GPIO, please delete them! + // Enable GPIO3 to HIGH + // Set GPIO Configure to output + data = 0x10; + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5D_GPIOSET1, data)) + return NV_FALSE; + + // Set GPIO to HI, NON-Inverting + data = 0x04; + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R5E_GPIOSET2, data)) + return NV_FALSE; +#endif + + //NvOdmOsMemset(&s_tps6586x, 0, sizeof(s_tps6586x)); + //s_tps6586x.pmuPresented = NV_TRUE; + pmuPresented = NV_TRUE; + +#if NV_DEBUG + //DumpTps6586x(hDevice); +#endif + + if (!Tps6586xBatteryChargerSetup(hDevice)) + return NV_FALSE; + + // The interrupt assumes not supported until tps6586xInterruptHandler() is called. + pmuInterruptSupported = NV_FALSE; + + // setup the interrupt any way. + if (!Tps6586xSetupInterrupt(hDevice, &pmuStatus)) + return NV_FALSE; + + //Check battery presence + if (!Tps6586xBatteryChargerCBCMainBatt(hDevice, &battPresence)) + return NV_FALSE; + + // Check battery Fullness + if (battPresence == NV_TRUE) + { + if (!Tps6586xBatteryChargerCBCBattFul(hDevice, &status)) + return NV_FALSE; + pmuStatus.batFull = status; + } + else + { + pmuStatus.batFull = NV_FALSE; + } + + return NV_TRUE; + +OPEN_FAILED: + Tps6586xRelease(hDevice); + return NV_FALSE; +} + +void Tps6586xRelease(NvOdmPmuDeviceHandle hDevice) +{ +#if defined(CONFIG_TEGRA_ODM_HARMONY) + NvU32 i; +#endif + if (hDevice != NULL && hPmu->hOdmI2C) + { + NvOdmServicesPmuClose(hPmu->hOdmPmuSevice); + hPmu->hOdmPmuSevice = NULL; + NvOdmI2cClose(hPmu->hOdmI2C); + hPmu->hOdmI2C = NULL; + NvOdmOsFree(hPmu); + hPmu = NULL; + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + + // Release & Close the GPIOs + for (i=0; i<(TPS6586x_EXTERNAL_SUPPLY_AP_GPIO_NUM); i++) + { + NvOdmGpioReleasePinHandle(hPmu->hGpio, hPmu->hPin[i]); + } + NvOdmGpioClose(hPmu->hGpio); +#endif + } +} + +NvBool +Tps6586xGetAcLineStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuAcLineStatus *pStatus) +{ + NvBool acLineStatus = NV_FALSE; + + NV_ASSERT(hDevice); + NV_ASSERT(pStatus); + + // check if charger presents + if (battPresence == NV_FALSE) + { + *pStatus = NvOdmPmuAcLine_Online; + return NV_TRUE; + } + + if (pmuInterruptSupported == NV_TRUE) + { + if ( pmuStatus.mChgPresent == NV_TRUE ) + { + *pStatus = NvOdmPmuAcLine_Online; + acLineStatus = NV_TRUE; + } + else + { + *pStatus = NvOdmPmuAcLine_Offline; + acLineStatus = NV_FALSE; + } + } + else + { + // battery is present, now check if charger presents + if (!Tps6586xBatteryChargerMainChgPresent(hDevice, &acLineStatus)) + { + NVODMPMU_PRINTF(("Error in checking main charger presence.\n")); + return NV_FALSE; + } + + if (acLineStatus == NV_TRUE) + *pStatus = NvOdmPmuAcLine_Online; + else + *pStatus = NvOdmPmuAcLine_Offline; + } + return NV_TRUE; +} + +NvBool +Tps6586xGetBatteryStatus( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU8 *pStatus) +{ + NvU8 status = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pStatus); + NV_ASSERT(batteryInst <= NvOdmPmuBatteryInst_Num); + + if (batteryInst == NvOdmPmuBatteryInst_Main) + { + if (battPresence == NV_TRUE) + { + NvOdmPmuAcLineStatus stat = NvOdmPmuAcLine_Offline; + NvU32 VBatSense = 0; + if (!Tps6586xGetAcLineStatus(hDevice, &stat)) + return NV_FALSE; + + if (stat == NvOdmPmuAcLine_Online) + { + if (pmuInterruptSupported == NV_TRUE) + { + if (pmuStatus.batFull == NV_FALSE) + status = NVODM_BATTERY_STATUS_CHARGING; + } + else + { + NvBool batFull = NV_FALSE; + if (!Tps6586xBatteryChargerCBCBattFul(hDevice, &batFull)) + return NV_FALSE; + if (batFull == NV_FALSE) + status = NVODM_BATTERY_STATUS_CHARGING; + } + } + + // Get VBatSense + if (!Tps6586xAdcVBatSenseRead(hDevice, &VBatSense)) + return NV_FALSE; + + if (VBatSense > NVODM_BATTERY_HIGH_VOLTAGE_MV) // maybe modify these parameters + status |= NVODM_BATTERY_STATUS_HIGH; + else if ((VBatSense < NVODM_BATTERY_LOW_VOLTAGE_MV)&& + (VBatSense > NVODM_BATTERY_CRITICAL_VOLTAGE_MV)) + status |= NVODM_BATTERY_STATUS_LOW; + else if (VBatSense <= NVODM_BATTERY_CRITICAL_VOLTAGE_MV) + status |= NVODM_BATTERY_STATUS_CRITICAL; + + } + else + { + /* Battery is actually not present */ + status = NVODM_BATTERY_STATUS_NO_BATTERY; + } + + *pStatus = status; + } + else + { + *pStatus = NVODM_BATTERY_STATUS_UNKNOWN; + } + + return NV_TRUE; +} + +NvBool +Tps6586xGetBatteryData( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryData *pData) +{ + NvOdmPmuBatteryData batteryData; + + batteryData.batteryLifePercent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryLifeTime = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryVoltage = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryCurrent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryAverageCurrent = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryAverageInterval = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryMahConsumed = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryTemperature = NVODM_BATTERY_DATA_UNKNOWN; + batteryData.batteryVoltage = NVODM_BATTERY_DATA_UNKNOWN; + + NV_ASSERT(hDevice); + NV_ASSERT(pData); + NV_ASSERT(batteryInst <= NvOdmPmuBatteryInst_Num); + + if (batteryInst == NvOdmPmuBatteryInst_Main) + { + NvU32 VBatSense = 0; + NvU32 VBatTemp = 0; + + if (battPresence == NV_TRUE) + { + /* retrieve Battery voltage and temperature */ + + // Get VBatSense + if (!Tps6586xAdcVBatSenseRead(hDevice, &VBatSense)) + { + NVODMPMU_PRINTF(("Error reading VBATSense. \n")); + return NV_FALSE; + } + + // Get VBatTemp + if (!Tps6586xAdcVBatTempRead(hDevice, &VBatTemp)) + { + NVODMPMU_PRINTF(("Error reading VBATSense. \n")); + return NV_FALSE; + } + + batteryData.batteryVoltage = VBatSense; + batteryData.batteryTemperature = Tps6586xBatteryTemperature(VBatSense, VBatTemp); + } + + *pData = batteryData; + } + else + { + *pData = batteryData; + } + + return NV_TRUE; +} + +void +Tps6586xGetBatteryFullLifeTime( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvU32 *pLifeTime) +{ + *pLifeTime = NVODM_BATTERY_DATA_UNKNOWN; +} + +void +Tps6586xGetBatteryChemistry( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuBatteryInstance batteryInst, + NvOdmPmuBatteryChemistry *pChemistry) +{ + *pChemistry = NvOdmPmuBatteryChemistry_LION; +} + + +NvBool +Tps6586xSetChargingCurrent( + NvOdmPmuDeviceHandle hDevice, + NvOdmPmuChargingPath chargingPath, + NvU32 chargingCurrentLimitMa, + NvOdmUsbChargerType ChargerType) +{ + NvU32 data = 0; + NV_ASSERT(hDevice); + + // if no battery, then do nothing + if (battPresence == NV_FALSE) + return NV_TRUE; + + if (chargingCurrentLimitMa > DEDICATED_CHARGER_LIMIT_MA) + chargingCurrentLimitMa = DEDICATED_CHARGER_LIMIT_MA; + + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R49_CHG1, &data)) + return NV_FALSE; + + if (chargingPath == NvOdmPmuChargingPath_UsbBus) + { + switch (ChargerType) + { + case NvOdmUsbChargerType_SJ: + chargingCurrentLimitMa = DEDICATED_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_SK: + chargingCurrentLimitMa = DEDICATED_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_SE1: + chargingCurrentLimitMa = DEDICATED_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_SE0: + chargingCurrentLimitMa = DEDICATED_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_Dummy: + chargingCurrentLimitMa = DUMB_CHARGER_LIMIT_MA; + break; + case NvOdmUsbChargerType_UsbHost: + default: + // USB Host based charging, nothing to do. Just pass current limit to PMU. + break; + } + } + + if (chargingCurrentLimitMa >= MAX_CHARGING_CURRENT) + { + data = data & 0xf3; + data = data | 0xC; + } + else if (chargingCurrentLimitMa >= L2_CHARGING_CURRENT) + { + data = data & 0xf3; + data = data | 0x4; + } + else if (chargingCurrentLimitMa >= L3_CHARGING_CURRENT) + { + data = data & 0xf3; + data = data | 0x0; + } + // 0 mA + else + { + chargingCurrentLimitMa = 0; + } + + //data = (NvU8)((( chargingCurrentLimitMa << 8 ) - chargingCurrentLimitMa ) + // / CHARGER_CONSTANT_CURRENT_SET_MA ); + + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R49_CHG1, data)) + return NV_FALSE; + + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R4A_CHG2, &data)) + return NV_FALSE; + + if (chargingCurrentLimitMa == 0) + { + data = data & 0xfd; // Disable charging! + } + else + { + data = data | 0x02; // Enable Charging! + } + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R4A_CHG2, data)) + return NV_FALSE; + + return NV_TRUE; +} + +void Tps6586xInterruptHandler( NvOdmPmuDeviceHandle hDevice) +{ + //TPS6586xHandle tps6586x = hDevice->priv; + //tps6586x->pmuStatus.batFull = NV_FALSE; + + // If the interrupt handle is called, the interrupt is supported. + pmuInterruptSupported = NV_TRUE; + + Tps6586xInterruptHandler_int(hDevice, &pmuStatus); +} + +NvBool Tps6586xReadRtc( NvOdmPmuDeviceHandle hDevice, NvU32 *Count) +{ + *Count = 0; + return (Tps6586xRtcCountRead(hDevice, Count)); +} + +NvBool Tps6586xWriteRtc( NvOdmPmuDeviceHandle hDevice, NvU32 Count) +{ + return (Tps6586xRtcCountWrite(hDevice, Count)); +} + +NvBool Tps6586xIsRtcInitialized( NvOdmPmuDeviceHandle hDevice) +{ + return ((Tps6586xRtcWasStartUpFromNoPower(hDevice))? NV_FALSE: NV_TRUE); +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h new file mode 100644 index 000000000000..0c1f4fb2b9af --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NVODM_PMU_TPS6586X_H_HH +#define NVODM_PMU_TPS6586X_H_HH + +#include "nvodm_pmu.h" +#include "nvodm_services.h" +#include "nvodm_pmu_tps6586x_supply_info_table.h" +#include "tps6586x_reg.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if (NV_DEBUG) +#define NVODMPMU_PRINTF(x) NvOdmOsDebugPrintf x +#else +#define NVODMPMU_PRINTF(x) +#endif + +typedef struct NvOdmPmuDeviceTPSRec +{ + /* The handle to the I2C */ + NvOdmServicesI2cHandle hOdmI2C; + + /* The odm pmu service handle */ + NvOdmServicesPmuHandle hOdmPmuSevice; + /* the PMU I2C device Address */ + NvU32 DeviceAddr; + + /* Device's private data */ + void *priv; + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + /* Gpio Handles (for external supplies) */ + NvOdmServicesGpioHandle hGpio; + NvOdmGpioPinHandle hPin[TPS6586x_EXTERNAL_SUPPLY_AP_GPIO_NUM]; +#else + /* The current voltage */ + NvU32 curVoltageTable[VRAILCOUNT]; +#endif + + /* The ref cnt table of the power supplies */ +#if defined(CONFIG_TEGRA_ODM_HARMONY) + NvU32 supplyRefCntTable[TPS6586xPmuSupply_Num]; +#else + NvU32 supplyRefCntTable[VRAILCOUNT]; +#endif + +} NvOdmPmuDeviceTPS; + +void Tps6586xGetCapabilities( NvU32 vddRail, NvOdmPmuVddRailCapabilities* pCapabilities); +NvBool Tps6586xGetVoltage( NvOdmPmuDeviceHandle hDevice, NvU32 vddRail, NvU32* pMilliVolts); +NvBool Tps6586xSetVoltage( NvOdmPmuDeviceHandle hDevice, NvU32 vddRail, NvU32 MilliVolts, NvU32* pSettleMicroSeconds); +NvBool Tps6586xSetup(NvOdmPmuDeviceHandle hDevice); +void Tps6586xRelease(NvOdmPmuDeviceHandle hDevice); +NvBool Tps6586xGetAcLineStatus( NvOdmPmuDeviceHandle hDevice, NvOdmPmuAcLineStatus *pStatus); +NvBool Tps6586xGetBatteryStatus( NvOdmPmuDeviceHandle hDevice, NvOdmPmuBatteryInstance batteryInst, NvU8 *pStatus); +NvBool Tps6586xGetBatteryData( NvOdmPmuDeviceHandle hDevice, NvOdmPmuBatteryInstance batteryInst, NvOdmPmuBatteryData *pData); +void Tps6586xGetBatteryFullLifeTime( NvOdmPmuDeviceHandle hDevice, NvOdmPmuBatteryInstance batteryInst, NvU32 *pLifeTime); +void Tps6586xGetBatteryChemistry( NvOdmPmuDeviceHandle hDevice, NvOdmPmuBatteryInstance batteryInst, NvOdmPmuBatteryChemistry *pChemistry); +NvBool Tps6586xSetChargingCurrent( NvOdmPmuDeviceHandle hDevice, NvOdmPmuChargingPath chargingPath, NvU32 chargingCurrentLimitMa, NvOdmUsbChargerType ChargerType); +void Tps6586xInterruptHandler( NvOdmPmuDeviceHandle hDevice); +NvBool Tps6586xReadRtc( NvOdmPmuDeviceHandle hDevice, NvU32 *Count); +NvBool Tps6586xWriteRtc( NvOdmPmuDeviceHandle hDevice, NvU32 Count); +NvBool Tps6586xIsRtcInitialized( NvOdmPmuDeviceHandle hDevice); + +#if defined(__cplusplus) +} +#endif + +#endif /* NVODM_PMU_TPS6586X_H_HH */ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_adc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_adc.c new file mode 100644 index 000000000000..7f2fcb0dd54c --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_adc.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_pmu_tps6586x_adc.h" +#include "nvodm_pmu_tps6586x_i2c.h" +#include "tps6586x_reg.h" +#include "nvodm_pmu_tps6586x_supply_info_table.h" + +#define ADC_CONVERSION_DELAY_USEC 70 +#define ADC_CONVERSION_TIMEOUT_USEC 500 +#define ADC_CONVERSION_VOLTAGE_RANGE 2000 +#define ADC_CONVERSION_DIVIDOR 3 +#define ADC_CONVERSION_PRECISION 10 +#define ADC_CONVERSION_SUB_OFFSET 2250 +#define ADC_FULL_SCALE_READING_MV_BAT 4622 +#define ADC_FULL_SCALE_READING_MV_TS 2600 +#define ADC_CONVERSION_PREWAIT_MS 26 + +/* read voltage from ADC CH10(battery) */ +NvBool +Tps6586xAdcVBatSenseRead(NvOdmPmuDeviceHandle hDevice, NvU32 *volt) +{ + NvU32 timeout = 0; + NvU32 dataS1 = 0; + NvU32 dataH = 0; + NvU32 dataL = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(volt); + + *volt = 0; // Default is 0mV. + // Configuring the adc conversion cycle + // ADC0_WAIT register(0x62) + // Reset all ADC engines and return them to the idle state; ADC0_RESET: 1 + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R62_ADC0_WAIT, 0x80)) + return NV_FALSE; + + // ADC0_SET register(0x61) + // ADC0_EN: 0(Don't start conversion); Number of Readings: 16; CHANNEL: CH10(battery) + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R61_ADC0_SET, 0x19)) + return NV_FALSE; + + // ADC0_WAIT register(0x62) + // REF_EN: 0; AUTO_REF: 1; Wait time: 0.062ms + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R62_ADC0_WAIT, 0x21)) + return NV_FALSE; + + // Start conversion!! + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R61_ADC0_SET, 0x99)) + return NV_FALSE; + + // Wait for conversion + //NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + NvOdmOsSleepMS(ADC_CONVERSION_PREWAIT_MS); + + // Make sure the conversion is completed - check for ADC error. + while (1) + { + // Read ADC status register + if(! Tps6586xI2cRead8(hDevice, TPS6586x_R9A_ADC0_INT, &dataS1)) + return NV_FALSE; + + // Conversion is done! + if (dataS1 & 0x80) + break; + + // ADC error! + if (dataS1 & 0x40) + { + NVODMPMU_PRINTF(("ADC conversion error.\n")); + return NV_FALSE; + } + + NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + timeout += ADC_CONVERSION_DELAY_USEC; + if (timeout >= ADC_CONVERSION_TIMEOUT_USEC) + return NV_FALSE; + } + + // Read the ADC conversion Average (SUM). + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R94_ADC0_SUM2, &dataH)) + return NV_FALSE; + + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R95_ADC0_SUM1, &dataL)) + return NV_FALSE; + + // Get a result value with mV. + *volt = (((dataH << 8) | dataL) * ADC_FULL_SCALE_READING_MV_BAT) / 1023 / 16; + + return NV_TRUE; +} + +/* read voltage from ADC CH5(temperature) */ +NvBool +Tps6586xAdcVBatTempRead(NvOdmPmuDeviceHandle hDevice, NvU32 *volt) +{ + NvU32 timeout = 0; + NvU32 dataS1 = 0; + NvU32 dataH = 0; + NvU32 dataL = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(volt); + + *volt = 0; // Default is 0'C. + + // Configuring the adc conversion cycle + // ADC0_WAIT register(0x62) + // Reset all ADC engines and return them to the idle state; ADC0_RESET: 1 + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R62_ADC0_WAIT, 0x80)) + return NV_FALSE; + // ADC0_SET register(0x61) + // ADC0_EN: 0(Don't start conversion); Number of Readings: 16; CHANNEL: CH5(temperature) + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R61_ADC0_SET, 0x14)) + return NV_FALSE; + + // ADC0_WAIT register(0x62) + // REF_EN: 0; AUTO_REF: 1; Wait time: 0.062ms + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R62_ADC0_WAIT, 0x21)) + return NV_FALSE; + + // Start conversion!! + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_R61_ADC0_SET, 0x94)) + return NV_FALSE; + + // Wait for conversion + // NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + NvOdmOsSleepMS(ADC_CONVERSION_PREWAIT_MS); + + // make sure the conversion is completed, or adc error. + while (1) + { + // Read ADC status register + if(! Tps6586xI2cRead8(hDevice, TPS6586x_R9A_ADC0_INT, &dataS1)) + return NV_FALSE; + + // Conversion is done! + if (dataS1 & 0x80) + break; + + // ADC error! + if (dataS1 & 0x40) + { + NVODMPMU_PRINTF(("ADC conversion error.\n")); + return NV_FALSE; + } + + NvOdmOsWaitUS(ADC_CONVERSION_DELAY_USEC); + timeout += ADC_CONVERSION_DELAY_USEC; + if (timeout >= ADC_CONVERSION_TIMEOUT_USEC) + return NV_FALSE; + } + + // Read the ADC conversion Average (SUM). + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R94_ADC0_SUM2, &dataH)) + return NV_FALSE; + + if (!Tps6586xI2cRead8(hDevice, TPS6586x_R95_ADC0_SUM1, &dataL)) + return NV_FALSE; + + // Get a result value with mV. + *volt = (((dataH << 8) | dataL) * ADC_FULL_SCALE_READING_MV_TS) / 1023 / 16; + + return NV_TRUE; +} + +/* Calculate the battery temperature */ +NvU32 Tps6586xBatteryTemperature(NvU32 VBatSense, NvU32 VBatTemp) +{ + return 0; +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_adc.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_adc.h new file mode 100644 index 000000000000..803a62856a9b --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_adc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_TPS6586X_ADC_HEADER +#define INCLUDED_TPS6586X_ADC_HEADER + +/* the ADC is used for battery voltage conversion */ +#include "nvodm_pmu_tps6586x.h" + + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* read voltage from adc */ +NvBool +Tps6586xAdcVBatSenseRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt); + +/* read bat temperature voltage from ADC */ +NvBool +Tps6586xAdcVBatTempRead( + NvOdmPmuDeviceHandle hDevice, + NvU32 *volt); + +/* Calculate the battery temperature */ +NvU32 +Tps6586xBatteryTemperature( + NvU32 VBatSense, + NvU32 VBatTemp); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_TPS6586X_ADC_HEADER diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_batterycharger.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_batterycharger.c new file mode 100644 index 000000000000..8a4573922adf --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_batterycharger.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_pmu_tps6586x_i2c.h" +#include "nvodm_pmu_tps6586x_batterycharger.h" + +NvBool Tps6586xBatteryChargerSetup(NvOdmPmuDeviceHandle hDevice) +{ + NvU32 data = 0; + // Configure CHARGER RAM registers + // CHG1: Charge safety timer value is 4 Hrs; Charge current scaling facotr: 1.0; + data = 0x0c; + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R49_CHG1, data)) + return NV_FALSE; + + // CHG2: CHARGE SAFETY TIMER: ON; CHARGE VOLTAGE: 4.2V; CHARGER: ON; + data = 0x1a; + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R4A_CHG2, data)) + return NV_FALSE; + + // CHG3: + data = 0x0; + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R4B_CHG3, data)) + return NV_FALSE; + + // RAM Control BITS: CHARGE VOLTAGE RANGE: 3.95 - 4.2; USB Input current limit: 500mA; + // Auto mode enabled; AC input current limit: 2A + data = 0x05; + if (!Tps6586xI2cWrite8(hDevice, TPS6586x_R4C_PPATH2, data)) + return NV_FALSE; + + return NV_TRUE; +} + +/* check CBC main batt presence */ +NvBool +Tps6586xBatteryChargerCBCMainBatt(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU32 data = 0; + + if (!Tps6586xI2cRead8(hDevice, TPS6586x_RB9_STAT1, &data)) + return NV_FALSE; + + // bit 0 show if battery exists or not + data = data & 0x01; + + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + + return NV_TRUE; +} + +/* check batt_ful status */ +NvBool +Tps6586xBatteryChargerCBCBattFul(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU32 data = 0; + + if(! Tps6586xI2cRead8(hDevice, TPS6586x_RBA_STAT2, &data)) + return NV_FALSE; + + data = data & 0x2; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + + return NV_TRUE; +} + +/* check main charger status */ +NvBool +Tps6586xBatteryChargerMainChgPresent(NvOdmPmuDeviceHandle hDevice, NvBool *status) +{ + NvU32 data = 0; + + if(! Tps6586xI2cRead8(hDevice, TPS6586x_RBB_STAT3, &data)) + return NV_FALSE; + + data = data & 0xc; + *status = (data == 0 ? NV_FALSE : NV_TRUE ); + + return NV_TRUE; +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_batterycharger.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_batterycharger.h new file mode 100644 index 000000000000..83b538792334 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_batterycharger.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_TPS6586X_BATTERYCHARGER_HEADER +#define INCLUDED_TPS6586X_BATTERYCHARGER_HEADER + + + +#include "nvodm_pmu_tps6586x.h" + +/* the battery charger functions */ +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Initliase all registers that related to battery charger */ +NvBool +Tps6586xBatteryChargerSetup(NvOdmPmuDeviceHandle hDevice); + +/* check CBC main batt presence */ +NvBool +Tps6586xBatteryChargerCBCMainBatt(NvOdmPmuDeviceHandle hDevice, NvBool *status); + +/* check batt_ful status */ +NvBool +Tps6586xBatteryChargerCBCBattFul(NvOdmPmuDeviceHandle hDevice, NvBool *status); + +/* check main charger status */ +NvBool +Tps6586xBatteryChargerMainChgPresent(NvOdmPmuDeviceHandle hDevice, NvBool *status); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_TPS6586X_BATTERYCHARGER_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_i2c.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_i2c.c new file mode 100644 index 000000000000..94e806101b10 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_i2c.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nvodm_pmu_tps6586x_i2c.h" +#include "nvodm_pmu_tps6586x.h" +#include "pmu_hal.h" + +NvBool +Tps6586xI2cWrite8( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 Data) +{ + NvU8 WriteBuffer[2]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + NvOdmI2cTransactionInfo TransactionInfo = {0}; + + WriteBuffer[0] = Addr & 0xFF; // PMU offset + WriteBuffer[1] = Data & 0xFF; // written data + + TransactionInfo.Address = ((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->DeviceAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->hOdmI2C, &TransactionInfo, 1, + TPS6586x_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + +NvBool +Tps6586xI2cRead8( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 *Data) +{ + NvU8 ReadBuffer=0; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + // Write the PMU offset + ReadBuffer = Addr & 0xFF; + + TransactionInfo[0].Address = ((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->DeviceAddr; + TransactionInfo[0].Buf = &ReadBuffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + TransactionInfo[1].Address = (((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->DeviceAddr | 0x1); + TransactionInfo[1].Buf = &ReadBuffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + // Read data from PMU at the specified offset + status = NvOdmI2cTransaction(((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->hOdmI2C, &TransactionInfo[0], 2, + TPS6586x_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + *Data = ReadBuffer; + return NV_TRUE; +} + +NvBool Tps6586xI2cWrite32( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 Data) +{ + NvU8 WriteBuffer[5]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + NvOdmI2cTransactionInfo TransactionInfo = {0}; + + WriteBuffer[0] = (NvU8)(Addr & 0xFF); + WriteBuffer[1] = (NvU8)((Data >> 24) & 0xFF); + WriteBuffer[2] = (NvU8)((Data >> 16) & 0xFF); + WriteBuffer[3] = (NvU8)((Data >> 8) & 0xFF); + WriteBuffer[4] = (NvU8)(Data & 0xFF); + + TransactionInfo.Address = ((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->DeviceAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 5; + + status = NvOdmI2cTransaction(((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->hOdmI2C, &TransactionInfo, 1, + TPS6586x_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status == NvOdmI2cStatus_Success) + { + return NV_TRUE; + } + else + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cWrite8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } +} + +NvBool Tps6586xI2cRead32( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 *Data) +{ + NvU8 ReadBuffer[5]; + NvOdmI2cStatus status = NvOdmI2cStatus_Success; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + // Write the PMU offset + ReadBuffer[0] = Addr & 0xFF; + + TransactionInfo[0].Address = ((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->DeviceAddr; + TransactionInfo[0].Buf = &ReadBuffer[0]; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + + TransactionInfo[1].Address = (((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->DeviceAddr | 0x1); + TransactionInfo[1].Buf = &ReadBuffer[0]; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 4; + + // Read data from PMU at the specified offset + status = NvOdmI2cTransaction(((NvOdmPmuDeviceTPS *)(hPmu->pPrivate))->hOdmI2C, &TransactionInfo[0], 2, + TPS6586x_I2C_SPEED_KHZ, NV_WAIT_INFINITE); + if (status != NvOdmI2cStatus_Success) + { + switch (status) + { + case NvOdmI2cStatus_Timeout: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: Timeout\n")); + break; + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODMPMU_PRINTF(("NvOdmPmuI2cRead8 Failed: SlaveNotFound\n")); + break; + } + return NV_FALSE; + } + + *Data = (ReadBuffer[0] << 24) | (ReadBuffer[1] << 16) | + (ReadBuffer[2] << 8) | ReadBuffer[3]; + return NV_TRUE; +} + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_i2c.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_i2c.h new file mode 100644 index 000000000000..df17ff6c2cf0 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_i2c.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_PMU_TPS6856X_I2C_H +#define INCLUDED_NVODM_PMU_TPS6856X_I2C_H + +#include "nvodm_pmu_tps6586x.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// Constant definition +#define TPS6586x_I2C_SPEED_KHZ 100 + +// Function declaration +NvBool Tps6586xI2cWrite8( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 Data); + +NvBool Tps6586xI2cRead8( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 *Data); + +NvBool Tps6586xI2cWrite32( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 Data); + +NvBool Tps6586xI2cRead32( + NvOdmPmuDeviceHandle hPmu, + NvU32 Addr, + NvU32 *Data); + + +#if defined(__cplusplus) +} +#endif + +/** @} */ + +#endif // INCLUDED_NVODM_PMU_TPS6856X_I2C_H diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c new file mode 100644 index 000000000000..b3ac0b954a4e --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "nvodm_pmu_tps6586x_interrupt.h" +#include "nvodm_pmu_tps6586x_i2c.h" +#include "nvodm_pmu_tps6586x_supply_info_table.h" +#include "nvodm_services.h" +#include "nvodm_pmu_tps6586x_batterycharger.h" + +#define TPS6586X_INT_BATT_INST 0x01 +#define TPS6586X_INT_PACK_COLD_DET 0x02 +#define TPS6586X_INT_PACK_HOT_DET 0x04 + +#define TPS6586X_INT_USB_DETECTION 0x04 +#define TPS6586X_INT_AC_DETECTION 0x08 +#define TPS6586X_INT_LOWSYS_DETECTION 0x40 + +NvBool Tps6586xSetupInterrupt(NvOdmPmuDeviceHandle hDevice, + TPS6586xStatus *pmuStatus) +{ + NvBool status = NV_FALSE; + NvU32 data = 0; + + NV_ASSERT(hDevice); + NV_ASSERT(pmuStatus); + + /* Init Pmu Status */ + pmuStatus->lowBatt = NV_FALSE; + pmuStatus->highTemp = NV_FALSE; + + if (!Tps6586xBatteryChargerMainChgPresent(hDevice,&status)) + return NV_FALSE; + pmuStatus->mChgPresent = status; + + /* Set up Interrupt Mask */ + /* Mask1 */ + data = 0xFF; + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_RB0_INT_MASK1, data )) + return NV_FALSE; + + /* Mask2 */ + data = 0xFF; + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_RB1_INT_MASK2, data )) + return NV_FALSE; + + /* Mask3: Battery detction, etc */ + data = 0; + data = (NvU32)~(TPS6586X_INT_BATT_INST|TPS6586X_INT_PACK_COLD_DET|TPS6586X_INT_PACK_HOT_DET); + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_RB2_INT_MASK3, data )) + return NV_FALSE; + + /* Mask4 */ + data = 0xFF; + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_RB3_INT_MASK4, data )) + return NV_FALSE; + + /* Mask5: USB Detection; AC Detection; Low System detection; */ + data = 0; + data = (NvU32) ~(TPS6586X_INT_USB_DETECTION|TPS6586X_INT_AC_DETECTION|TPS6586X_INT_LOWSYS_DETECTION); + if(! Tps6586xI2cWrite8(hDevice, TPS6586x_RB4_INT_MASK5, data )) + return NV_FALSE; + + return NV_TRUE; +} + +void Tps6586xInterruptHandler_int(NvOdmPmuDeviceHandle hDevice, + TPS6586xStatus *pmuStatus) +{ + NvU32 data = 0; + + /* INT_ACK1 */ + if (!Tps6586xI2cRead8(hDevice, TPS6586x_RB5_INT_ACK1, &data)) + { + return; + } + pmuStatus->powerGood = (data & 0xFF); + + + /* INT_ACK2 */ + if (!Tps6586xI2cRead8(hDevice, TPS6586x_RB6_INT_ACK2, &data)) + { + return; + } + pmuStatus->powerGood |= ((data & 0xFF)<<8); + + /* INT_ACK3 */ + /* LOW SYS */ + if (!Tps6586xI2cRead8(hDevice, TPS6586x_RB7_INT_ACK3, &data)) + { + return; + } + if (data != 0) + { + if (data&0x40) + { + pmuStatus->highTemp = NV_TRUE; + } + if (data&0xc0) + { + pmuStatus->mChgPresent = NV_TRUE; +#if !defined(CONFIG_TEGRA_ODM_HARMONY) + NvOdmEnableOtgCircuitry(NV_TRUE); +#endif + } + } + + /* INT_ACK4 */ + /* CHG TEMP */ + if (!Tps6586xI2cRead8(hDevice, TPS6586x_RB8_INT_ACK4, &data)) + { + return; + } + if (data != 0) + { + if (data&0x02) + { + pmuStatus->lowBatt = NV_TRUE; + } + } +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.h new file mode 100644 index 000000000000..8e9ff0464135 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_interrupt.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_TPS6586X_INTERRUPT_HEADER +#define INCLUDED_TPS6586X_INTERRUPT_HEADER + +#include "nvodm_pmu_tps6586x.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct TPS6586xStatusRef +{ + /* Low Battery voltage detected by BVM */ + NvBool lowBatt; + + /* PMU high temperature */ + NvBool highTemp; + + /* Main charger Presents */ + NvBool mChgPresent; + + /* battery Full */ + NvBool batFull; + + /* Porwer In type*/ + NvU32 powerType; /* Bit meanings: + 0: AC_DET, + 1: USB_DET, + 2: BAT_DET */ + NvU32 powerGood; /* Bit meanings: + 0-7: LDO0 to LDO7 + 10-11: LDO8 and LDO9, + 12-15: SMO0 to SM11 */ +}TPS6586xStatus; + +#if 0 +typedef struct { + NvBool pmuInterruptSupported; + NvBool pmuPresented; + NvBool battPresence; + TPS6586xStatus pmuStatus; +} TPS6586xDevice, *TPS6586xHandle; +#endif + +NvBool +Tps6586xSetupInterrupt( + NvOdmPmuDeviceHandle hDevice, + TPS6586xStatus *pmuStatus); + + + +void +Tps6586xInterruptHandler_int( + NvOdmPmuDeviceHandle hDevice, + TPS6586xStatus *pmuStatus); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_TPS6586X_INTERRUPT_HEADER diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c new file mode 100644 index 000000000000..889cf2bbc6ff --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <linux/time.h> +#include "nvodm_pmu_tps6586x_rtc.h" +#include "nvodm_pmu_tps6586x_i2c.h" +#include "tps6586x_reg.h" + +// macro OFFSET_BASE_YEAR if 1, uses epoch as reference year instead of 1970 +// This is because RTC in PMU TPS6586x can store duration of 34 years, +// else we cannot retain date beyond 2004 +#define OFFSET_BASE_YEAR 1 +#if OFFSET_BASE_YEAR +static unsigned long epoch = 2009; +static unsigned long epoch_sec = 0; +#endif + +static NvBool bRtcNotInitialized = NV_TRUE; + +/* Read RTC count register */ +NvBool +Tps6586xRtcCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count) +{ + NvU32 ReadBuffer[2]; + + // 1) The I2C address pointer must not be left pointing in the range 0xC6 to 0xCA + // 2) The maximum time for the address pointer to be in this range is 1ms + // 3) Always read RTC_ALARM2 in the following order to prevent the address pointer + // from stopping at 0xC6: RTC_ALARM2_LO, then RTC_ALARM2_HI + + if (Tps6586xRtcWasStartUpFromNoPower(hDevice) && bRtcNotInitialized) + { + Tps6586xRtcCountWrite(hDevice, 0); + *Count = 0; + } + else + { + // The unit of the RTC count is second!!! 1024 tick = 1s. + // Read all 40 bit and right move 10 = Read the hightest 32bit and right move 2 + Tps6586xI2cRead32(hDevice, TPS6586x_RC6_RTC_COUNT4, &ReadBuffer[0]); + + Tps6586xI2cRead8(hDevice, TPS6586x_RCA_RTC_COUNT0, &ReadBuffer[1]); + + Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer[1]); + + // return second + *Count = ReadBuffer[0]>>2; + } +#if OFFSET_BASE_YEAR + // calculate epoch_sec once + if (!epoch_sec) + epoch_sec = mktime(epoch,1,1,0,0,0); + *Count += epoch_sec; +#endif + + return NV_TRUE; +} + +/* Write RTC count register */ + +NvBool +Tps6586xRtcCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count) +{ + NvU32 ReadBuffer = 0; +#if OFFSET_BASE_YEAR + // calculate epoch_sec once + if (!epoch_sec) + epoch_sec = mktime(epoch,1,1,0,0,0); + if (Count < (NvU32)epoch_sec) + { + // prevent setting date earlier than 'epoch' + pr_warning("\n Date being set cannot be earlier than least " + "year=%d. Setting as least year. ", (int)epoch); + // base year seconds count is 0 + Count = 0; + } + else + Count -= (NvU32)epoch_sec; +#endif + + // Switch to 32KHz crystal oscillator + // POR_SRC_SEL=1 and OSC_SRC_SEL=1 + Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer); + ReadBuffer = ReadBuffer | 0xC0; + Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer); + + // To enable incrementing of the RTC_COUNT[39:0] from an initial value set by the host, + // the RTC_ENABLE bit should be written to 1 only after the RTC_OUT voltage reaches + // the operating range + + // Clear RTC_ENABLE before writing RTC_COUNT + Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer); + ReadBuffer = ReadBuffer & 0xDF; + Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer); + + Tps6586xI2cWrite32(hDevice, TPS6586x_RC6_RTC_COUNT4, (Count<<2)); + Tps6586xI2cWrite8(hDevice, TPS6586x_RCA_RTC_COUNT0, 0); + + // Set RTC_ENABLE after writing RTC_COUNT + Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &ReadBuffer); + ReadBuffer = ReadBuffer | 0x20; + Tps6586xI2cWrite8(hDevice, TPS6586x_RC0_RTC_CTRL, ReadBuffer); + + if (bRtcNotInitialized) + bRtcNotInitialized = NV_FALSE; + + return NV_TRUE; +} + +/* Read RTC alarm count register */ + +NvBool +Tps6586xRtcAlarmCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count) +{ + return NV_FALSE; +} + +/* Write RTC alarm count register */ + +NvBool +Tps6586xRtcAlarmCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count) +{ + return NV_FALSE; +} + +/* Reads RTC alarm interrupt mask status */ + +NvBool +Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice) +{ + return NV_FALSE; +} + +/* Enables / Disables the RTC alarm interrupt */ + +NvBool +Tps6586xRtcAlarmIntEnable( + NvOdmPmuDeviceHandle hDevice, + NvBool Enable) +{ + return NV_FALSE; +} + +/* Checks if boot was from nopower / powered state */ + +NvBool +Tps6586xRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice) +{ + NvU32 Data = 0; + + if ((Tps6586xI2cRead8(hDevice, TPS6586x_RC0_RTC_CTRL, &Data)) == NV_TRUE) + { + return ((Data & 0x20)? NV_FALSE : NV_TRUE); + } + return NV_FALSE; +} diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.h new file mode 100644 index 000000000000..8137c95e1702 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_rtc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_TPS6586X_RTC_HEADER +#define INCLUDED_TPS6586X_RTC_HEADER + +#include "nvodm_pmu_tps6586x.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Read RTC count register */ + +NvBool +Tps6586xRtcCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count); + +/* Read RTC alarm count register */ + +NvBool +Tps6586xRtcAlarmCountRead( + NvOdmPmuDeviceHandle hDevice, + NvU32* Count); + +/* Write RTC count register */ + +NvBool +Tps6586xRtcCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count); + +/* Write RTC alarm count register */ + +NvBool +Tps6586xRtcAlarmCountWrite( + NvOdmPmuDeviceHandle hDevice, + NvU32 Count); + +/* Reads RTC alarm interrupt mask status */ + +NvBool +Tps6586xRtcIsAlarmIntEnabled(NvOdmPmuDeviceHandle hDevice); + +/* Enables / Disables the RTC alarm interrupt */ + +NvBool +Tps6586xRtcAlarmIntEnable( + NvOdmPmuDeviceHandle hDevice, + NvBool Enable); + +/* Checks if boot was from nopower / powered state */ + +NvBool +Tps6586xRtcWasStartUpFromNoPower(NvOdmPmuDeviceHandle hDevice); + +#if defined(__cplusplus) +} +#endif + +#endif // INCLUDED_TPS6586X_RTC_HEADER + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_supply_info_table.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_supply_info_table.h new file mode 100644 index 000000000000..fe34d3a02ca1 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/nvodm_pmu_tps6586x_supply_info_table.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TPS6586x_SUPPLY_INFO_TABLE_H_ +#define TPS6586x_SUPPLY_INFO_TABLE_H_ + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define PMUGUID NV_ODM_GUID('t','p','s','6','5','8','6','x') + +#if defined(CONFIG_TEGRA_ODM_HARMONY) + +/// The total number of external supplies (which use both AP and PMU GPIOs) +#define TPS6586x_EXTERNAL_SUPPLY_NUM \ + (NvU32)(TPS6586xPmuSupply_Num - Ext_TPS62290PmuSupply_BUCK) + +/// Macro for converting a vddRail to AP GPIO pin index. +#define NVODM_EXT_AP_GPIO_RAIL(x) ((x) - Ext_TPS2051BPmuSupply_VDDIO_VID) + +/// The total number of external supplies which use AP GPIO pins for enable +#define TPS6586x_EXTERNAL_SUPPLY_AP_GPIO_NUM \ + (NvU32)NVODM_EXT_AP_GPIO_RAIL(TPS6586xPmuSupply_Num) + +#else + +/* FIXME: modify this table according to your schematics */ +#define V_CORE TPS6586xPmuSupply_DCD0 +#define V_1V8 TPS6586xPmuSupply_DCD1 +#define LCD_2V8 TPS6586xPmuSupply_LDO0 +#define V_1V2 TPS6586xPmuSupply_LDO1 +#define V_RTC TPS6586xPmuSupply_LDO2 +#define V_CAM_1V8 TPS6586xPmuSupply_LDO3 +#define V_CODEC_1V8 TPS6586xPmuSupply_LDO4 +#define V_CAM_2V8 TPS6586xPmuSupply_LDO5 +#define V_3V3 TPS6586xPmuSupply_LDO6 +#define V_SDIO TPS6586xPmuSupply_LDO7 +#define V_2V8 TPS6586xPmuSupply_LDO8 +#define V_2V5 TPS6586xPmuSupply_LDO9 +#define V_25V TPS6586xPmuSupply_WHITE_LED +#define V_CHARGE TPS6586xPmuSupply_DCD2 +#define V_MODEM V_1V8 /* Alias for V_1V8 */ +#define V_GND TPS6586xPmuSupply_Invalid +#define V_INVALID TPS6586xPmuSupply_Invalid +#define VRAILCOUNT TPS6586xPmuSupply_Num +#endif + +typedef enum +{ + TPS6586xPmuSupply_Invalid = 0x0, + + //DCD0 + TPS6586xPmuSupply_DCD0, + + //DCD1 + TPS6586xPmuSupply_DCD1, + + //DCD2 + TPS6586xPmuSupply_DCD2, + + + //LDO0 + TPS6586xPmuSupply_LDO0, + + //LDO1 + TPS6586xPmuSupply_LDO1, + + //LDO2 + TPS6586xPmuSupply_LDO2, + + //LDO3 + TPS6586xPmuSupply_LDO3, + + //LDO4 + TPS6586xPmuSupply_LDO4, + + //LDO5 + TPS6586xPmuSupply_LDO5, + + //LDO6 + TPS6586xPmuSupply_LDO6, + + //LDO7 + TPS6586xPmuSupply_LDO7, + + //LDO8 + TPS6586xPmuSupply_LDO8, + + //LDO9 + TPS6586xPmuSupply_LDO9, + + //RTC_OUT + TPS6586xPmuSupply_RTC_OUT, + + //RED1 + TPS6586xPmuSupply_RED1, + + //GREEN1 + TPS6586xPmuSupply_GREEN1, + + //BLUE1 + TPS6586xPmuSupply_BLUE1, + + //RED2 + TPS6586xPmuSupply_RED2, + + //GREEN2 + TPS6586xPmuSupply_GREEN2, + + //BLUE2 + TPS6586xPmuSupply_BLUE2, + + //LED_PWM + TPS6586xPmuSupply_LED_PWM, + + //PWM + TPS6586xPmuSupply_PWM, + + //White LED(SW3) + TPS6586xPmuSupply_WHITE_LED, +#if defined(CONFIG_TEGRA_ODM_HARMONY) + //SOC + TPS6586xPmuSupply_SoC, + + /*--- Secondary/External PMU Rails ---*/ + + // PMU GPIO-3: VDD_1V05 + Ext_TPS62290PmuSupply_BUCK, + + // PMU GPIO-2: VDD_1V2 + Ext_TPS72012PmuSupply_LDO, + + // PMU GPIO-1: VDD_1V5 + Ext_TPS74201PmuSupply_LDO, + + // AP GPIO(T,2): VDDIO_HDMI, VDDIO_VGA (5V @ 500ma) + Ext_TPS2051BPmuSupply_VDDIO_VID, + + // AP GPIO(T,3): VDDIO_SD + Ext_SWITCHPmuSupply_VDDIO_SD, + + // AP GPIO(I,6): VDDIO_SDMMC + Ext_SWITCHPmuSupply_VDDIO_SDMMC, + + // AP GPIO(W,0): VDD_BL + // FIXME: This is already supplied by nvodm_query_gpio in the display GPIO settings. + Ext_SWITCHPmuSupply_VDD_BL, + + // AP GPIO(C,6): VDD_PNL + // FIXME: This is already supplied by nvodm_query_gpio in the display GPIO settings. + Ext_SWITCHPmuSupply_VDD_PNL, +#endif + + TPS6586xPmuSupply_Num, + TPS6586xPmuSupply_Force32 = 0x7FFFFFFF +} TPS6586xPmuSupply; + +#if defined(__cplusplus) +} +#endif + +#endif /* TPS6586x_SUPPLY_INFO_TABLE_H_ */ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/tps6586x_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/tps6586x_reg.h new file mode 100644 index 000000000000..c22cc43854ae --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/pmu/tps6586x/tps6586x_reg.h @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef TPS6586X_REG_HEADER +#define TPS6586X_REG_HEADER + +#if defined(__cplusplus) +extern "C" +{ +#endif + + + +/* TPS6586x registers */ + +/* Supply Control and Voltage Settings */ +#define TPS6586x_R10_SUPPLYENA 0x10 +#define TPS6586x_R11_SUPPLYENB 0x11 +#define TPS6586x_R12_SUPPLYENC 0x12 +#define TPS6586x_R13_SUPPLYEND 0x13 +#define TPS6586x_R14_SUPPLYENE 0x14 +#define TPS6586x_R20_VCC1 0x20 +#define TPS6586x_R21_VCC2 0x21 +#define TPS6586x_R23_SM1V1 0x23 +#define TPS6586x_R24_SM1V2 0x24 +#define TPS6586x_R25_SM1SL 0x25 +#define TPS6586x_R26_SM0V1 0x26 +#define TPS6586x_R27_SM0V2 0x27 +#define TPS6586x_R28_SM0SL 0x28 +#define TPS6586x_R29_LDO2AV1 0x29 +#define TPS6586x_R2A_LDO2AV2 0x2A +#define TPS6586x_R2F_LDO2BV1 0x2F +#define TPS6586x_R30_LDO2BV2 0x30 +#define TPS6586x_R32_LDO4V1 0x32 +#define TPS6586x_R33_LDO4V2 0x33 + +/* Converter Settings */ +#define TPS6586x_R41_SUPPLYV1 0x41 +#define TPS6586x_R42_SUPPLYV2 0x42 +#define TPS6586x_R43_SUPPLYV3 0x43 +#define TPS6586x_R44_SUPPLYV4 0x44 +#define TPS6586x_R45_SUPPLYV5 0x45 +#define TPS6586x_R46_SUPPLYV6 0x46 +#define TPS6586x_R47_SMODE1 0x47 +#define TPS6586x_R48_SMODE2 0x48 + +/* Charger Setup */ +#define TPS6586x_R49_CHG1 0x49 +#define TPS6586x_R4A_CHG2 0x4A +#define TPS6586x_R4B_CHG3 0x4B + +/* Power Path Setup */ +#define TPS6586x_R4C_PPATH2 0x4C + +/* Sequencing */ +#define TPS6586x_R4D_PGFLTMSK1 0x4D +#define TPS6586x_R4E_PGFLTMSK2 0x4E + +/* Peripheral Control */ +#define TPS6586x_R50_RGB1FLASH 0x50 +#define TPS6586x_R51_RGB1RED 0x51 +#define TPS6586x_R52_RGB1GREEN 0x52 +#define TPS6586x_R53_RGB1BLUE 0x53 +#define TPS6586x_R54_RGB2RED 0x54 +#define TPS6586x_R55_RGB2GREEN 0x55 +#define TPS6586x_R56_RGB2BLUE 0x56 +#define TPS6586x_R57_SM3_SET0 0x57 +#define TPS6586x_R58_SM3_SET1 0x58 +#define TPS6586x_R59_LED_PWM 0x59 +#define TPS6586x_R5A_DIG_PWM 0x5A +#define TPS6586x_R5B_PWM 0x5B +#define TPS6586x_R5C_DIG_PWM1 0x5C +#define TPS6586x_R5D_GPIOSET1 0x5D +#define TPS6586x_R5E_GPIOSET2 0x5E + +#if defined(CONFIG_TEGRA_ODM_HARMONY) +/*-- GPIO Register Bit Shifts/Masks --*/ +// GPIO1 +#define TPS6586x_R5D_GPIOSET1_GPIO1_MODE_SHIFT 0x0 +#define TPS6586x_R5D_GPIOSET1_GPIO1_MODE_MASK 0x3 +#define TPS6586x_R5E_GPIOSET2_GPIO1_OUT_SHIFT 0x0 +#define TPS6586x_R5E_GPIOSET2_GPIO1_OUT_MASK 0x1 +#define TPS6586x_R5E_GPIOSET2_GPIO1_INV_SHIFT 0x4 +#define TPS6586x_R5E_GPIOSET2_GPIO1_INV_MASK 0x1 + +// GPIO2 +#define TPS6586x_R5D_GPIOSET1_GPIO2_MODE_SHIFT 0x2 +#define TPS6586x_R5D_GPIOSET1_GPIO2_MODE_MASK 0x3 +#define TPS6586x_R5E_GPIOSET2_GPIO2_OUT_SHIFT 0x1 +#define TPS6586x_R5E_GPIOSET2_GPIO2_OUT_MASK 0x1 +#define TPS6586x_R5E_GPIOSET2_GPIO2_INV_SHIFT 0x5 +#define TPS6586x_R5E_GPIOSET2_GPIO2_INV_MASK 0x1 + +// GPIO3 +#define TPS6586x_R5D_GPIOSET1_GPIO3_MODE_SHIFT 0x4 +#define TPS6586x_R5D_GPIOSET1_GPIO3_MODE_MASK 0x3 +#define TPS6586x_R5E_GPIOSET2_GPIO3_OUT_SHIFT 0x2 +#define TPS6586x_R5E_GPIOSET2_GPIO3_OUT_MASK 0x1 +#define TPS6586x_R5E_GPIOSET2_GPIO3_INV_SHIFT 0x6 +#define TPS6586x_R5E_GPIOSET2_GPIO3_INV_MASK 0x1 + +// GPIO4 +#define TPS6586x_R5D_GPIOSET1_GPIO4_MODE_SHIFT 0x6 +#define TPS6586x_R5D_GPIOSET1_GPIO4_MODE_MASK 0x3 +#define TPS6586x_R5E_GPIOSET2_GPIO4_OUT_SHIFT 0x3 +#define TPS6586x_R5E_GPIOSET2_GPIO4_OUT_MASK 0x1 +#define TPS6586x_R5E_GPIOSET2_GPIO4_INV_SHIFT 0x7 +#define TPS6586x_R5E_GPIOSET2_GPIO4_INV_MASK 0x1 + +#define TPS6586x_R5D_GPIO_MODE_NOT_CONFIG 0x0 +#define TPS6586x_R5D_GPIO_MODE_OUTPUT 0x1 +#define TPS6586x_R5D_GPIO_MODE_INPUT_ADC 0x2 +#define TPS6586x_R5D_GPIO_MODE_INPUT_LDO 0x3 +#endif + +/* ADC0 Engine Setup */ +#define TPS6586x_R60_ADCANLG 0x60 + /* Not finish yet */ + +/* ADC0 Engine Data */ +#define TPS6586x_R61_ADC0_SET 0x61 +#define TPS6586x_R62_ADC0_WAIT 0x62 +#define TPS6586x_R94_ADC0_SUM2 0x94 +#define TPS6586x_R95_ADC0_SUM1 0x95 +#define TPS6586x_R9A_ADC0_INT 0x9A + +/* Interrupt Control */ +#define TPS6586x_RB0_INT_MASK1 0xB0 +#define TPS6586x_RB1_INT_MASK2 0xB1 +#define TPS6586x_RB2_INT_MASK3 0xB2 +#define TPS6586x_RB3_INT_MASK4 0xB3 +#define TPS6586x_RB4_INT_MASK5 0xB4 +#define TPS6586x_RB5_INT_ACK1 0xB5 +#define TPS6586x_RB6_INT_ACK2 0xB6 +#define TPS6586x_RB7_INT_ACK3 0xB7 +#define TPS6586x_RB8_INT_ACK4 0xB8 + +/* System Status */ +#define TPS6586x_RB9_STAT1 0xB9 +#define TPS6586x_RBA_STAT2 0xBA +#define TPS6586x_RBB_STAT3 0xBB +#define TPS6586x_RBC_STAT4 0xBC + +/* RTC */ +#define TPS6586x_RC0_RTC_CTRL 0xC0 +#define TPS6586x_RC1_RTC_ALARM1_HI 0xC1 +#define TPS6586x_RC2_RTC_ALARM1_MID 0xC2 +#define TPS6586x_RC3_RTC_ALARM1_LO 0xC3 +#define TPS6586x_RC4_RTC_ALARM2_HI 0xC4 +#define TPS6586x_RC5_RTC_ALARM2_LO 0xC5 +#define TPS6586x_RC6_RTC_COUNT4 0xC6 +#define TPS6586x_RC7_RTC_COUNT3 0xC7 +#define TPS6586x_RC8_RTC_COUNT2 0xC8 +#define TPS6586x_RC9_RTC_COUNT1 0xC9 +#define TPS6586x_RCA_RTC_COUNT0 0xCA + +/* Device ID */ +#define TPS6586x_RCD_VERSIONID 0xCD + +#define TPS6586x_RFF_INVALID 0xFF + +/* RTC */ + /* Not finish yet */ + + +#if defined(__cplusplus) +} +#endif + + +#endif //TPS6586X_REG_HEADER diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile new file mode 100644 index 000000000000..d2245a6505fa --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/Makefile @@ -0,0 +1,11 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +obj-y += tmon_hal.o +obj-y += adt7461/ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile new file mode 100644 index 000000000000..03f222cbeee4 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/Makefile @@ -0,0 +1,13 @@ +ccflags-y += -DNV_IS_AVP=0 +ccflags-y += -DNV_OAL=0 +ccflags-y += -DNV_USE_FUSE_CLOCK_ENABLE=0 +ifeq ($(CONFIG_MACH_TEGRA_GENERIC_DEBUG),y) +ccflags-y += -DNV_DEBUG=1 +else +ccflags-y += -DNV_DEBUG=0 +endif + +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/tmon +ccflags-y += -Iarch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461 + +obj-y += nvodm_tmon_adt7461.o diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c new file mode 100644 index 000000000000..dc76869f6dec --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.c @@ -0,0 +1,934 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#include "nvodm_tmon_adt7461.h" +#include "tmon_hal.h" + +// TODO: Always Disable before check-in +// Always debug module: 0=disable, 1=enable +#define NV_ADT7461_DEBUG (0) + +#if (NV_DEBUG || NV_ADT7461_DEBUG) +#define NVODM_ADT7461_PRINTF(x) NvOdmOsDebugPrintf x +#else +#define NVODM_ADT7461_PRINTF(x) +#endif + +#define ADT7461_ALERT_DEBOUNCE (1) + +// ADT7461 Descrriptor +static const ADT7461Info s_Adt7461Info = +{ + // TMON device conversion channels + { + // Invalid channel + {0}, + + // Local channel + { + ADT7461ChannelID_Local, + { + ADT7461_ODM_LOCAL_RATE_PROTECTED, + ADT7461_ODM_LOCAL_INTR_LIMITS_PROTECTED, + ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_PROTECTED + }, + { + ADT7461_LOCAL_INTR_LIMIT_HIGH_RD_ADDR, + ADT7461_LOCAL_INTR_LIMIT_HIGH_WR_ADDR, + }, + { + ADT7461_LOCAL_INTR_LIMIT_LOW_RD_ADDR, + ADT7461_LOCAL_INTR_LIMIT_LOW_WR_ADDR, + }, + { + ADT7461_LOCAL_COMPARATOR_LIMIT_ADDR, + ADT7461_LOCAL_COMPARATOR_LIMIT_ADDR, + }, + { + ADT7461_INVALID_ADDR, // Local offset does not exist + ADT7461_INVALID_ADDR, + }, + { + ADT7461_LOCAL_TDATA_RD_ADDR, + ADT7461_INVALID_ADDR, + }, + }, + + // Remote channel + { + ADT7461ChannelID_Remote, + { + ADT7461_ODM_REMOTE_RATE_PROTECTED, + ADT7461_ODM_REMOTE_INTR_LIMITS_PROTECTED, + ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_PROTECTED + }, + { + ADT7461_REMOTE_INTR_LIMIT_HIGH_RD_ADDR, + ADT7461_REMOTE_INTR_LIMIT_HIGH_WR_ADDR, + }, + { + ADT7461_REMOTE_INTR_LIMIT_LOW_RD_ADDR, + ADT7461_REMOTE_INTR_LIMIT_LOW_WR_ADDR, + }, + { + ADT7461_REMOTE_COMPARATOR_LIMIT_ADDR, + ADT7461_REMOTE_COMPARATOR_LIMIT_ADDR, + }, + { + ADT7461_REMOTE_TOFFSET_ADDR, + ADT7461_REMOTE_TOFFSET_ADDR, + }, + { + ADT7461_REMOTE_TDATA_RD_ADDR, + ADT7461_INVALID_ADDR, + }, + } + }, + + // TMON device common status/control registers + { + ADT7461_STATUS_RD_ADDR, + ADT7461_INVALID_ADDR, + }, + { + ADT7461_CONFIG_RD_ADDR, + ADT7461_CONFIG_WR_ADDR, + }, + { + ADT7461_RATE_RD_ADDR, + ADT7461_RATE_WR_ADDR, + }, + { + ADT7461_INVALID_ADDR, + ADT7461_ONE_SHOT_WR_ADDR, + }, + { + ADT7461_COMPARATOR_HYSTERESIS_ADDR, + ADT7461_COMPARATOR_HYSTERESIS_ADDR, + }, + { + ADT7461_INTR_CNT_DELAY_ADDR, + ADT7461_INTR_CNT_DELAY_ADDR, + }, +}; + +// ADT7461 sample intervals +static const NvS32 s_Adt7461SampleIntervalsMS[] = +{ + ADT7461_SAMPLE_INTERVALS_MS +}; + +// ADT7461 converison times +static const NvS32 s_Adt7461ConversionTimesMS[] = +{ + ADT7461_CONVERSION_TIME_MS +}; + +NV_CT_ASSERT(NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS) == + NV_ARRAY_SIZE(s_Adt7461ConversionTimesMS)); + +/*****************************************************************************/ + +#define ADT7461_T_DATA_TO_VALUE(ExtRange, data) \ + ( (ExtRange) ? \ + ((NvS32)((NvU32)(data) - ADT7461_RANGE_EXTENDED_DATA_OFFSET)) : \ + ((NvS32)((NvS8)data)) \ + ) + +#define ADT7461_T_VALUE_TO_DATA(ExtRange, val) \ + ( (ExtRange) ? \ + ((NvU8)((NvU32)(val) + ADT7461_RANGE_EXTENDED_DATA_OFFSET)) : \ + ((NvU8)(val)) \ + ) + +#define ADT7461_T_RANGE_LIMIT_HIGH(ExtRange) \ + ( (ExtRange) ? \ + ADT7461_RANGE_EXTENDED_LIMIT_HIGH : \ + ADT7461_RANGE_STANDARD_LIMIT_HIGH \ + ) + +#define ADT7461_T_RANGE_LIMIT_LOW(ExtRange) \ + ( (ExtRange) ? \ + ADT7461_RANGE_EXTENDED_LIMIT_LOW : \ + ADT7461_RANGE_STANDARD_LIMIT_LOW \ + ) + +/*****************************************************************************/ + +static NvBool +Adt7461WriteReg( + ADT7461PrivData* pPrivData, + const ADT7461RegisterInfo* pReg, + NvU8 Data) +{ + NvU32 i; + NvU8 WriteBuffer[2]; + NvOdmI2cStatus status; + NvOdmI2cTransactionInfo TransactionInfo; + + NV_ASSERT(pPrivData && pReg); + NV_ASSERT(pReg->WrAddr != ADT7461_INVALID_ADDR); + + for (i = 0; i < ADT7461_I2C_RETRY_CNT; i++) + { + WriteBuffer[0] = pReg->WrAddr; + WriteBuffer[1] = Data; + + TransactionInfo.Address = pPrivData->DeviceI2cAddr; + TransactionInfo.Buf = &WriteBuffer[0]; + TransactionInfo.Flags = NVODM_I2C_IS_WRITE; + TransactionInfo.NumBytes = 2; + + status = NvOdmI2cTransaction(pPrivData->hOdmI2C, &TransactionInfo, 1, + ADT7461_I2C_SPEED_KHZ, ADT7461_I2C_TIMEOUT_MS); + if (status == NvOdmI2cStatus_Success) + break; + } + + switch (status) + { + case NvOdmI2cStatus_Success: + pPrivData->ShadowRegPtr = pReg->WrAddr; + return NV_TRUE; + + case NvOdmI2cStatus_Timeout: + NVODM_ADT7461_PRINTF(("ADT7461: WriteReg Timeout\n")); + return NV_FALSE; + + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODM_ADT7461_PRINTF(("ADT7461: WriteReg SlaveNotFound\n")); + return NV_FALSE; + } +} + +static NvBool +Adt7461ReadReg( + ADT7461PrivData* pPrivData, + const ADT7461RegisterInfo* pReg, + NvU8* pData) +{ + NvU32 i; + NvU8 Buffer = 0; + NvOdmI2cStatus status; + NvOdmI2cTransactionInfo TransactionInfo[2]; + + NV_ASSERT(pPrivData && pReg && pData); + NV_ASSERT(pReg->RdAddr != ADT7461_INVALID_ADDR); + + // TODO: possible optimization - is shadow pointer matches register + // address, just send one read transaction (can be done only if Read/Wr + // Reg routines are serialized). + + for (i = 0; i < ADT7461_I2C_RETRY_CNT; i++) + { + Buffer = pReg->RdAddr; + + TransactionInfo[0].Address = pPrivData->DeviceI2cAddr; + TransactionInfo[0].Buf = &Buffer; + TransactionInfo[0].Flags = NVODM_I2C_IS_WRITE; + TransactionInfo[0].NumBytes = 1; + + TransactionInfo[1].Address = (pPrivData->DeviceI2cAddr | 0x1); + TransactionInfo[1].Buf = &Buffer; + TransactionInfo[1].Flags = 0; + TransactionInfo[1].NumBytes = 1; + + status = NvOdmI2cTransaction(pPrivData->hOdmI2C, &TransactionInfo[0], 2, + ADT7461_I2C_SPEED_KHZ, ADT7461_I2C_TIMEOUT_MS); + if (status == NvOdmI2cStatus_Success) + break; + } + + switch (status) + { + case NvOdmI2cStatus_Success: + pPrivData->ShadowRegPtr = pReg->RdAddr; + *pData = Buffer; + return NV_TRUE; + + case NvOdmI2cStatus_Timeout: + NVODM_ADT7461_PRINTF(("ADT7461: ReadReg Timeout\n")); + return NV_FALSE; + + case NvOdmI2cStatus_SlaveNotFound: + default: + NVODM_ADT7461_PRINTF(("ADT7461: ReadReg SlaveNotFound\n")); + return NV_FALSE; + } +} + +static void Adt7461ReadAra(ADT7461PrivData* pPrivData) +{ + NvU32 i; + NvU8 Buffer = 0; + NvOdmI2cStatus status; + NvOdmI2cTransactionInfo TransactionInfo; + + NV_ASSERT(pPrivData); + + for (i = 0; i < ADT7461_ARA_RETRY_CNT; i++) + { + TransactionInfo.Address = (ADT7461_ARA | 0x1); + TransactionInfo.Buf = &Buffer; + TransactionInfo.Flags = 0; + TransactionInfo.NumBytes = 1; + + status = NvOdmI2cTransaction(pPrivData->hOdmI2C, &TransactionInfo, 1, + ADT7461_I2C_SPEED_KHZ, ADT7461_I2C_TIMEOUT_MS); + if ((status == NvOdmI2cStatus_SlaveNotFound) || // False alarm + ((status == NvOdmI2cStatus_Success) && + ((Buffer & 0xFE) == (NvU8)pPrivData->DeviceI2cAddr)) // Cleared ARA + ) + break; + } +} + +static NvBool +Adt7461ConfigureSampleInterval( + ADT7461PrivData* pPrivData, + NvBool OdmProtected, + NvS32* pTargetMs) +{ + NvU8 i; + NvS32 Delta; + const ADT7461RegisterInfo* pReg = &pPrivData->pDeviceInfo->Rate; + + if (OdmProtected || + ((*pTargetMs) == ODM_TMON_PARAMETER_UNSPECIFIED)) + { + // Read ADT7461 rate register (fail the call if returned data + // does not make sense) + if(!Adt7461ReadReg(pPrivData, pReg, &i)) + return NV_FALSE; + if (i >= NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS)) + return NV_FALSE; + } + else + { + // Find and set the best floor approximation of the target sample + // interval. Note the descending order of sample intervals array. + for (i = 0; i < NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS); i++) + { + Delta = (*pTargetMs) - s_Adt7461SampleIntervalsMS[i]; + if(Delta >= 0) + break; + } + if (i == NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS)) + i--; // min interval is the best we can do + + if(!Adt7461WriteReg(pPrivData, pReg, i)) + return NV_FALSE; + pPrivData->ShadowRate = i; + } + *pTargetMs = s_Adt7461SampleIntervalsMS[i]; + return NV_TRUE; +} + +/*****************************************************************************/ + +static void Adt7461Isr(void* arg) +{ + NvU8 Data; + ADT7461PrivData* pPrivData = (ADT7461PrivData*)arg; + NvOdmInterruptHandler volatile Callback = pPrivData->Callback; + void* volatile CallbackArg = pPrivData->CallbackArg; + const ADT7461RegisterInfo* pReg = NULL; + + if (Callback && CallbackArg) + { + Callback(CallbackArg); + } +#if ADT7461_ALERT_DEBOUNCE + // New range limits set by callback are not guaranteed to take effect + // before the next temperature conversion is completed, and interrupt + // can not be cleared until then. Hence, the debounce delay below. + NvOdmOsSleepMS(s_Adt7461SampleIntervalsMS[pPrivData->ShadowRate] + + s_Adt7461ConversionTimesMS[pPrivData->ShadowRate] + 1); +#endif + // Read status and ARA to finish clearing interrupt after callback + pReg = &pPrivData->pDeviceInfo->Status; + (void)Adt7461ReadReg(pPrivData, pReg, &Data); + Adt7461ReadAra(pPrivData); + + // Re-enable interrupt + if (pPrivData->hGpioIntr) + NvOdmGpioInterruptDone(pPrivData->hGpioIntr); +} + +static void Adt7461FreePrivData(ADT7461PrivData* pPrivData) +{ + if (pPrivData) + { + if (pPrivData->hGpioIntr) + { + NvOdmGpioInterruptUnregister( + pPrivData->hGpio, pPrivData->hGpioPin, pPrivData->hGpioIntr); + } + NvOdmI2cClose(pPrivData->hOdmI2C); + NvOdmGpioReleasePinHandle(pPrivData->hGpio, pPrivData->hGpioPin); + NvOdmGpioClose(pPrivData->hGpio); + NvOdmServicesPmuClose(pPrivData->hOdmPmuSevice); + NvOdmOsFree(pPrivData); + } +} + +/*****************************************************************************/ + +NvBool Adt7461Init(NvOdmTmonDeviceHandle hTmon) +{ + NvU8 Data; + NvBool ExtRange; + NvU32 i = 0; + NvU32 I2cInstance = 0; + NvOdmIoModule I2cModule = NvOdmIoModule_Num; // Inavlid module + const ADT7461RegisterInfo* pReg = NULL; + ADT7461PrivData* pPrivData = NULL; + + NV_ASSERT(hTmon && hTmon->pConn && hTmon->pConn->AddressList); + + // Allocate and clear priavte data + pPrivData = (ADT7461PrivData*) NvOdmOsAlloc(sizeof(ADT7461PrivData)); + if (pPrivData == NULL) + { + NVODM_ADT7461_PRINTF(("ADT7461: Error Allocating PrivData. \n")); + return NV_FALSE; + } + NvOdmOsMemset(pPrivData, 0, sizeof(ADT7461PrivData)); + hTmon->pPrivate = pPrivData; + + // Register for PMU services + pPrivData->hOdmPmuSevice = NvOdmServicesPmuOpen(); + if (pPrivData->hOdmPmuSevice == NULL) + { + NVODM_ADT7461_PRINTF(("ADT7461: Error Open PMU service. \n")); + goto fail; + } + + // Register for GPIO services + pPrivData->hGpio = NvOdmGpioOpen(); + if (pPrivData->hOdmPmuSevice == NULL) + { + NVODM_ADT7461_PRINTF(("ADT7461: Error Open GPIO service. \n")); + goto fail; + } + + /* + * Parse connectivity data: turn On power to the device, acquire I2C + * interface and GPIO interrupt (optional); map device channels to + * thermal zones + */ + for (i = 0; i < hTmon->pConn->NumAddress; i ++) + { + const NvOdmIoAddress* pIoAddress = &hTmon->pConn->AddressList[i]; + if (pIoAddress->Interface == NvOdmIoModule_I2c_Pmu) + { + I2cModule = NvOdmIoModule_I2c_Pmu; + I2cInstance = pIoAddress->Instance; + NV_ASSERT(pIoAddress->Address != 0); + pPrivData->DeviceI2cAddr = pIoAddress->Address; + } + else if (pIoAddress->Interface == NvOdmIoModule_Tsense) + { + NV_ASSERT(pIoAddress->Instance < NvOdmTmonZoneID_Num); + NV_ASSERT(pIoAddress->Address < ADT7461ChannelID_Num); + pPrivData->ConnectivityMap[pIoAddress->Instance] = + pIoAddress->Address; + } + else if (pIoAddress->Interface == NvOdmIoModule_Vdd) + { + NvU32 usec = 0; + NvU32 RailAddress = pIoAddress->Address; + NvOdmServicesPmuVddRailCapabilities RailCapabilities = {0}; + NvOdmServicesPmuGetCapabilities( + pPrivData->hOdmPmuSevice, RailAddress, &RailCapabilities); + NvOdmServicesPmuSetVoltage(pPrivData->hOdmPmuSevice, RailAddress, + RailCapabilities.requestMilliVolts, &usec); + NvOdmOsWaitUS(usec + (ADT7461_POWERUP_DELAY_MS * 1000)); + } + else if (pIoAddress->Interface == NvOdmIoModule_Gpio) + { + NvU32 port = pIoAddress->Instance; + NvU32 pin = pIoAddress->Address; + pPrivData->hGpioPin = NvOdmGpioAcquirePinHandle( + pPrivData->hGpio, port, pin); + } + + } + NV_ASSERT(I2cModule == NvOdmIoModule_I2c_Pmu); + pPrivData->hOdmI2C = NvOdmI2cOpen(I2cModule, I2cInstance); + if (pPrivData->hOdmI2C == NULL) + { + NVODM_ADT7461_PRINTF(("ADT7461: Error Open I2C device. \n")); + goto fail; + } + + /* + * Initialize device info and configuration. Force standby mode to avoid + * glitch on shutdown comparator output when temperature range and/or + * comparator limit is changing during initialization. The Adt7461Run() + * call from the hal that follows initialization will switch device to + * run mode and re-start temperature monitoring (note that out of limit + * interrupt is always masked during and after initialization) + */ + pPrivData->pDeviceInfo = &s_Adt7461Info; + pPrivData->ShadowRegPtr = ADT7461_INVALID_ADDR; + + pReg = &pPrivData->pDeviceInfo->Config; + if (!Adt7461ReadReg(pPrivData, pReg, &Data)) + goto fail; + if ((Data & ADT7461ConfigBits_ExtendedRange) != + (ADT7461_INITIAL_CONFIG & ADT7461ConfigBits_ExtendedRange)) + { + // Only switch from standard to extended range is supported + NV_ASSERT((Data & ADT7461ConfigBits_ExtendedRange) == 0); + Data |= ADT7461ConfigBits_Standby; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + } + Data = ADT7461_INITIAL_CONFIG | ADT7461ConfigBits_Standby; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + pPrivData->ShadowConfig = Data; + ExtRange = ((Data & ADT7461ConfigBits_ExtendedRange) != 0); + + // Program shutdown comparators settings + Data = ADT7461_T_VALUE_TO_DATA( + ExtRange, ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_VALUE); + pReg = &pPrivData->pDeviceInfo->Channels[ + ADT7461ChannelID_Local].ComparatorLimit; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + + Data = ADT7461_T_VALUE_TO_DATA( + ExtRange, ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_VALUE); + pReg = &pPrivData->pDeviceInfo->Channels[ + ADT7461ChannelID_Remote].ComparatorLimit; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + + // Set interrupt limits to the range boundaries to prevent out of limit + // interrupt + Data = ADT7461_T_VALUE_TO_DATA( + ExtRange, ADT7461_T_RANGE_LIMIT_HIGH(ExtRange)); + pReg = &pPrivData->pDeviceInfo->Channels[ + ADT7461ChannelID_Local].IntrLimitHigh; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + pReg = &pPrivData->pDeviceInfo->Channels[ + ADT7461ChannelID_Remote].IntrLimitHigh; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + + Data = ADT7461_T_VALUE_TO_DATA( + ExtRange, ADT7461_T_RANGE_LIMIT_LOW(ExtRange)); + pReg = &pPrivData->pDeviceInfo->Channels[ + ADT7461ChannelID_Local].IntrLimitLow; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + pReg = &pPrivData->pDeviceInfo->Channels[ + ADT7461ChannelID_Remote].IntrLimitLow; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + + // Set initial rate + Data = ADT7461_INITIAL_RATE_SETTING; + pReg = &pPrivData->pDeviceInfo->Rate; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + pPrivData->ShadowRate = Data; + + // Set remote channel offset (8-bit 2's complement value for any range) + Data = ((NvU8)ADT7461_ODM_REMOTE_OFFSET_VALUE); + pReg = &pPrivData->pDeviceInfo->Channels[ + ADT7461ChannelID_Remote].Toffset; + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + goto fail; + + // Read ADT7461 status and ARA (clear pending Alert interrupt, if any) + pReg = &pPrivData->pDeviceInfo->Status; + if (!Adt7461ReadReg(pPrivData, pReg, &Data)) + goto fail; + // TODO: check open remote circuit error + + Adt7461ReadAra(pPrivData); + return NV_TRUE; + +fail: + Adt7461FreePrivData(pPrivData); + hTmon->pPrivate = NULL; + return NV_FALSE; +} + +void Adt7461Deinit(NvOdmTmonDeviceHandle hTmon) +{ + if (hTmon && hTmon->pPrivate) + { + ADT7461PrivData* pPrivData = hTmon->pPrivate; + (void)Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, + ADT7461_INITIAL_CONFIG); //leave device in default configuration + // with power rail ON (forever) + Adt7461FreePrivData(pPrivData); + hTmon->pPrivate = NULL; + } +} + +/*****************************************************************************/ + +NvBool Adt7461Run(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId) +{ + NvU8 Data; + NvBool IsRunning; + ADT7461PrivData* pPrivData; + + NV_ASSERT(hTmon && hTmon->pPrivate); + pPrivData = hTmon->pPrivate; + IsRunning = (pPrivData->ShadowConfig & ADT7461ConfigBits_Standby) == 0; + + if (!IsRunning) + { + Data = pPrivData->ShadowConfig & (~ADT7461ConfigBits_Standby); + if(!Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + return NV_FALSE; + pPrivData->ShadowConfig = Data; + } + pPrivData->RunRefCount++; + return NV_TRUE; +} + +NvBool Adt7461Stop(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId) +{ + NvU8 Data; + NvBool IsRunning; + ADT7461PrivData* pPrivData; + + NV_ASSERT(hTmon && hTmon->pPrivate); + pPrivData = hTmon->pPrivate; + IsRunning = (pPrivData->ShadowConfig & ADT7461ConfigBits_Standby) == 0; + + if (ADT7461_ODM_STANDBY_ENABLED && + IsRunning && (pPrivData->RunRefCount == 1)) + { + Data = pPrivData->ShadowConfig | ADT7461ConfigBits_Standby; + if(!Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + return NV_FALSE; + pPrivData->ShadowConfig = Data; + } + if (pPrivData->RunRefCount != 0) + { + pPrivData->RunRefCount--; + return NV_TRUE; + } + NV_ASSERT(!"RunRefCount balance failed"); + NVODM_ADT7461_PRINTF(("ADT7461: RunRefCount balance failed. \n")); + return NV_FALSE; +} + +/*****************************************************************************/ +// ADT7461 aborts and restarts conversion cycle when temperature is read +// (actually on any I2C access for that matter, but other accesses are rare). +// TODO: add time stamps and implement refresh policy to make sure that +// frequent temperature reads would not stall the conversion forever. + +NvBool +Adt7461TemperatureGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvS32* pDegreesC) +{ + NvU8 Data; + NvBool ExtRange; + ADT7461ChannelID ChannelId; + ADT7461PrivData* pPrivData; + const ADT7461RegisterInfo* pReg; + + NV_ASSERT(hTmon && hTmon->pPrivate && pDegreesC); + pPrivData = hTmon->pPrivate; + ExtRange = ((pPrivData->ShadowConfig & + ADT7461ConfigBits_ExtendedRange) != 0); + ChannelId = pPrivData->ConnectivityMap[ZoneId]; + pReg = &pPrivData->pDeviceInfo->Channels[ChannelId].Tdata; + + if(!Adt7461ReadReg(pPrivData, pReg, &Data)) + return NV_FALSE; + + *pDegreesC = ADT7461_T_DATA_TO_VALUE(ExtRange, Data); + return NV_TRUE; +} + +/*****************************************************************************/ + +void +Adt7461CapabilitiesGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonCapabilities* pCaps) +{ + NvBool ExtRange; + ADT7461PrivData* pPrivData; + + NV_ASSERT(hTmon && hTmon->pPrivate && pCaps); + pPrivData = hTmon->pPrivate; + ExtRange = ((pPrivData->ShadowConfig & + ADT7461ConfigBits_ExtendedRange) != 0); + + pCaps->Tmax = ADT7461_T_RANGE_LIMIT_HIGH(ExtRange); + pCaps->Tmin = ADT7461_T_RANGE_LIMIT_LOW(ExtRange); + pCaps->IntrSupported = NV_TRUE; + pCaps->HwCriticalSupported = NV_TRUE; + pCaps->HwCoolingSupported = NV_FALSE; +} + +void +Adt7461ParameterCapsGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonConfigParam ParamId, + NvOdmTmonParameterCaps* pCaps) +{ + NvBool ExtRange; + ADT7461PrivData* pPrivData; + const ADT7461ChannelInfo* pChannel; + + NV_ASSERT(hTmon && hTmon->pPrivate && pCaps); + pPrivData = hTmon->pPrivate; + ExtRange = ((pPrivData->ShadowConfig & + ADT7461ConfigBits_ExtendedRange) != 0); + pChannel = &pPrivData->pDeviceInfo->Channels[( + pPrivData->ConnectivityMap[ZoneId])]; + + switch (ParamId) + { + case NvOdmTmonConfigParam_IntrLimitHigh: + case NvOdmTmonConfigParam_IntrLimitLow: + pCaps->OdmProtected = + pChannel->ChannelPolicy.IntrLimitsOdmProtected; + break; + + case NvOdmTmonConfigParam_HwLimitCrit: + pCaps->OdmProtected = + pChannel->ChannelPolicy.HwLimitCritOdmProtected; + break; + + case NvOdmTmonConfigParam_SampleMs: + // smaple intervals in descending order + pCaps->MaxValue = s_Adt7461SampleIntervalsMS[0]; + pCaps->MinValue = s_Adt7461SampleIntervalsMS[( + NV_ARRAY_SIZE(s_Adt7461SampleIntervalsMS) - 1)]; + pCaps->OdmProtected = pChannel->ChannelPolicy.RateOdmProtected; + return; + + default: // unsupported parameter + pCaps->MaxValue = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->MinValue = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->OdmProtected = NV_TRUE; + return; + } + + // Common range for limits + pCaps->MaxValue = ADT7461_T_RANGE_LIMIT_HIGH(ExtRange); + pCaps->MinValue = ADT7461_T_RANGE_LIMIT_LOW(ExtRange); +} + +NvBool +Adt7461ParameterConfig( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonConfigParam ParamId, + NvS32* pSetting) +{ + NvU8 Data; + NvBool ExtRange, OdmProtected; + ADT7461PrivData* pPrivData; + const ADT7461RegisterInfo* pReg; + const ADT7461ChannelInfo* pChannel; + + NV_ASSERT(hTmon && hTmon->pPrivate && pSetting); + pPrivData = hTmon->pPrivate; + ExtRange = ((pPrivData->ShadowConfig & + ADT7461ConfigBits_ExtendedRange) != 0); + pChannel = &pPrivData->pDeviceInfo->Channels[( + pPrivData->ConnectivityMap[ZoneId])]; + + switch (ParamId) + { + case NvOdmTmonConfigParam_IntrLimitHigh: + pReg = &pChannel->IntrLimitHigh; + OdmProtected = pChannel->ChannelPolicy.IntrLimitsOdmProtected; + break; + + case NvOdmTmonConfigParam_IntrLimitLow: + pReg = &pChannel->IntrLimitLow; + OdmProtected = pChannel->ChannelPolicy.IntrLimitsOdmProtected; + break; + + case NvOdmTmonConfigParam_HwLimitCrit: + pReg = &pChannel->ComparatorLimit; + OdmProtected = pChannel->ChannelPolicy.HwLimitCritOdmProtected; + break; + + case NvOdmTmonConfigParam_SampleMs: + OdmProtected = pChannel->ChannelPolicy.RateOdmProtected; + return Adt7461ConfigureSampleInterval( + pPrivData, OdmProtected, pSetting); + + default: // unsupported parameter + *pSetting = ODM_TMON_PARAMETER_UNSPECIFIED; + return NV_TRUE; + } + + // Common processing for temperature limits configuration + if ((OdmProtected) || + ((*pSetting) == ODM_TMON_PARAMETER_UNSPECIFIED)) + { + // Read ADT7461 register and convert data to current parameter value + if(!Adt7461ReadReg(pPrivData, pReg, &Data)) + return NV_FALSE; + + *pSetting = ADT7461_T_DATA_TO_VALUE(ExtRange, Data); + } + else + { + // Clip target setting to temperature range + if ((*pSetting) > ADT7461_T_RANGE_LIMIT_HIGH(ExtRange)) + *pSetting = ADT7461_T_RANGE_LIMIT_HIGH(ExtRange); + else if ((*pSetting) < ADT7461_T_RANGE_LIMIT_LOW(ExtRange)) + *pSetting = ADT7461_T_RANGE_LIMIT_LOW(ExtRange); + + // Convert new configuration setting and write to ADT7461 register + Data = ADT7461_T_VALUE_TO_DATA(ExtRange, *pSetting); + if(!Adt7461WriteReg(pPrivData, pReg, Data)) + return NV_FALSE; + } + return NV_TRUE; +} + +/*****************************************************************************/ + +NvOdmTmonIntrHandle +Adt7461IntrRegister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmInterruptHandler Callback, + void* CallbackArg) +{ + NvU8 Data; + ADT7461PrivData* pPrivData; + const ADT7461ChannelInfo* pChannel; + NvOdmServicesGpioIntrHandle hGpioIntr = NULL; + + NV_ASSERT(hTmon && hTmon->pPrivate && Callback && CallbackArg); + pPrivData = hTmon->pPrivate; + + // No registration, if no GPIO pin available or interrupt already registred + if (!pPrivData->hGpioPin || pPrivData->hGpioIntr) + return NULL; + + // No registration for other than remote channel + pChannel = &pPrivData->pDeviceInfo->Channels[( + pPrivData->ConnectivityMap[ZoneId])]; + if (pChannel->ChannelId != ADT7461ChannelID_Remote) + return NULL; + + // Register GPIO interrupt (will be enabled at SoC IC, but still disabled + // at ADT7461 device) + pPrivData->Callback = Callback; + pPrivData->CallbackArg = CallbackArg; + if (!NvOdmGpioInterruptRegister( + pPrivData->hGpio, &hGpioIntr, pPrivData->hGpioPin, + ADT7461_ODM_INTR_POLARITY, Adt7461Isr, (void *)pPrivData, 0)) + { + pPrivData->Callback = NULL; + pPrivData->CallbackArg = NULL; + return NULL; + } + NV_ASSERT(hGpioIntr); + pPrivData->hGpioIntr = hGpioIntr; + + // Finally enable ADT7461 device interrupt output (interrupt may or may + // not be generated depending on temperature and limt settings). + Data = pPrivData->ShadowConfig & (~ADT7461ConfigBits_IntrDisabled); + if(!Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + { + NvOdmGpioInterruptUnregister( + pPrivData->hGpio, pPrivData->hGpioPin, hGpioIntr); + pPrivData->Callback = NULL; + pPrivData->CallbackArg = NULL; + pPrivData->hGpioIntr = NULL; + return NULL; + } + pPrivData->ShadowConfig = Data; + + return (NvOdmTmonIntrHandle)hGpioIntr; +} + +void +Adt7461IntrUnregister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonIntrHandle hIntr) +{ + NvU8 Data; + ADT7461PrivData* pPrivData; + const ADT7461ChannelInfo* pChannel; + + // Ignore invalid handles + if(!hIntr || !hTmon || !hTmon->pPrivate) + return; + + pPrivData = hTmon->pPrivate; + if (hIntr != ((NvOdmTmonIntrHandle)pPrivData->hGpioIntr)) + return; + + // Ignore any channel other than remote + pChannel = &pPrivData->pDeviceInfo->Channels[( + pPrivData->ConnectivityMap[ZoneId])]; + if (pChannel->ChannelId != ADT7461ChannelID_Remote) + return; + + // Disable ADT7461 interrupt output + Data = pPrivData->ShadowConfig | ADT7461ConfigBits_IntrDisabled; + if(Adt7461WriteReg(pPrivData, &pPrivData->pDeviceInfo->Config, Data)) + pPrivData->ShadowConfig = Data; + + // Unregister GPIO interrupt, clear callbacks and handle + NvOdmGpioInterruptUnregister( + pPrivData->hGpio, pPrivData->hGpioPin, pPrivData->hGpioIntr); + + pPrivData->Callback = NULL; + pPrivData->CallbackArg = NULL; + pPrivData->hGpioIntr = NULL; +} + +/*****************************************************************************/ + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h new file mode 100644 index 000000000000..ffe4bf15dbec --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_TMON_ADT7461_H +#define INCLUDED_NVODM_TMON_ADT7461_H + +#include "nvodm_tmon.h" +#include "nvodm_tmon_adt7461_reg.h" +#include "nvodm_tmon_adt7461_channel.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct ADT7461RegisterInfoRec +{ + NvU8 RdAddr; // Invalid if WO + NvU8 WrAddr; // Invalid if RO +} ADT7461RegisterInfo; + +typedef struct ADT7461ChannelOdmPolicyRec +{ + NvBool RateOdmProtected; + NvBool IntrLimitsOdmProtected; + NvBool HwLimitCritOdmProtected; +} ADT7461ChannelOdmPolicy; + +typedef struct ADT7461ChannelInfoRec +{ + // TMON device conversion channel ID + ADT7461ChannelID ChannelId; + + // ODM channel policy + ADT7461ChannelOdmPolicy ChannelPolicy; + + // Alert Interrupt limits registers + ADT7461RegisterInfo IntrLimitHigh; + ADT7461RegisterInfo IntrLimitLow; + + // Thermal comparator limit register + ADT7461RegisterInfo ComparatorLimit; + + // Temperature measurement offset + ADT7461RegisterInfo Toffset; + + // Temperature Data register + ADT7461RegisterInfo Tdata; +} ADT7461ChannelInfo; + +typedef struct ADT7461InfoRec +{ + // TMON device conversion channels + ADT7461ChannelInfo Channels[ADT7461ChannelID_Num]; + + // Chip status register + ADT7461RegisterInfo Status; + + // Common configration controls + ADT7461RegisterInfo Config; + + // Common conversion rate + ADT7461RegisterInfo Rate; + + // One-shot trigger register + ADT7461RegisterInfo OneShot; + + // Common comparator hysteresis + ADT7461RegisterInfo ComparatorHysteresis; + + // Number of consecutive limit violation before + // interrupt is generated + ADT7461RegisterInfo IntrCntDelay; +} ADT7461Info; + +typedef struct ADT7461PrivDataRec +{ + // ADT7461 device registers descriptors + const ADT7461Info* pDeviceInfo; + + // ADT7461 I2C device Address + NvU32 DeviceI2cAddr; + + // The handle to the I2C controller + NvOdmServicesI2cHandle hOdmI2C; + + // The odm pmu service handle + NvOdmServicesPmuHandle hOdmPmuSevice; + + // Zone => Channel map + ADT7461ChannelID ConnectivityMap[NvOdmTmonZoneID_Num]; + + // ADR7461 run mode reference count + NvU32 RunRefCount; + + // Shadow of ADT7461 internal configuration register + NvU8 ShadowConfig; + + // Shadow of ADT7461 internal rate settings + NvU8 ShadowRate; + + // Shadow of ADT7461 internal address pointer + NvU8 ShadowRegPtr; + + // The odm GPIO service handle + NvOdmServicesGpioHandle hGpio; + + // SoC GPIO dedicated for ADT7461 out of limit interrupt + NvOdmGpioPinHandle hGpioPin; + + // The ADT7461 interrupt handle + NvOdmServicesGpioIntrHandle hGpioIntr; + + // The ADT7461 interrupt callback + NvOdmInterruptHandler Callback; + + // The ADT7461 interrupt callback context + void* CallbackArg; +} ADT7461PrivData; + +NvBool Adt7461Init(NvOdmTmonDeviceHandle hTmon); +void Adt7461Deinit(NvOdmTmonDeviceHandle hTmon); +NvBool Adt7461Run(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId); +NvBool Adt7461Stop(NvOdmTmonDeviceHandle hTmon, NvOdmTmonZoneID ZoneId); + +NvBool +Adt7461TemperatureGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvS32* pDegreesC); + +void +Adt7461CapabilitiesGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonCapabilities* pCaps); + +void +Adt7461ParameterCapsGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonConfigParam ParamId, + NvOdmTmonParameterCaps* pCaps); + +NvBool +Adt7461ParameterConfig( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonConfigParam ParamId, + NvS32* pSetting); + +NvOdmTmonIntrHandle +Adt7461IntrRegister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmInterruptHandler Callback, + void* arg); + +void +Adt7461IntrUnregister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonZoneID ZoneId, + NvOdmTmonIntrHandle hIntr); + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADT7461_H + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h new file mode 100644 index 000000000000..8d9f9bb22d95 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_channel.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_TMON_ADT7461_CHANNEL_H +#define INCLUDED_NVODM_TMON_ADT7461_CHANNEL_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef enum +{ + // Local sensor + ADT7461ChannelID_Local = 1, + + // Remote sensor + ADT7461ChannelID_Remote, + + ADT7461ChannelID_Num, + ADT7461ChannelID_Force32 = 0x7FFFFFFFUL +} ADT7461ChannelID; + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADT7461_CHANNEL_H + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h new file mode 100644 index 000000000000..e0e930e79fe7 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/adt7461/nvodm_tmon_adt7461_reg.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef INCLUDED_NVODM_TMON_ADT7461_REG_H +#define INCLUDED_NVODM_TMON_ADT7461_REG_H + +#include "nvodm_tmon_adt7461.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +// ODM policy: use ADT7461 extended=1 (standard=0) range +#define ADT7461_ODM_EXTENDED_RANGE (1) + +// ODM policy: enable=1 (disable=0) ADT7461 standby mode +#define ADT7461_ODM_STANDBY_ENABLED (0) + +// ODM policy: protect=1 (not=0) thermal limits from being overwritten by API +#define ADT7461_ODM_LOCAL_INTR_LIMITS_PROTECTED (1) +#define ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_PROTECTED (1) + +#define ADT7461_ODM_REMOTE_INTR_LIMITS_PROTECTED (0) +#define ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_PROTECTED (1) + +// ODM policy: protect=1 (not=0) sample rate from being overwritten by API +#define ADT7461_ODM_LOCAL_RATE_PROTECTED (1) +#define ADT7461_ODM_REMOTE_RATE_PROTECTED (0) + +// ODM policy: comparator limit values for critical shutdown (in degrees C) +#define ADT7461_ODM_LOCAL_COMPARATOR_LIMIT_VALUE (120L) +#define ADT7461_ODM_REMOTE_COMPARATOR_LIMIT_VALUE (115L) + +// ODM ADT7461 remote channel measurement offset +#define ADT7461_ODM_REMOTE_OFFSET_VALUE (6L) + +// ODM ADT7461 interrupt polarity +#define ADT7461_ODM_INTR_POLARITY (NvOdmGpioPinMode_InputInterruptLow) + +// ADT7461 Register POR settings +#define ADT7461_LOCAL_TDATA_POR (0x00) +#define ADT7461_REMOTE_TDATA_POR (0x00) +// #define ADT7461_STATUS_POR unknown +#define ADT7461_CONFIG_POR (0x00) +#define ADT7461_RATE_POR (0x08) +#define ADT7461_LOCAL_INTR_LIMIT_HIGH_POR (0x55) +#define ADT7461_LOCAL_INTR_LIMIT_LOW_POR (0x00) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_POR (0x55) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_POR (0x00) +// #define ADT7461_ONE_SHOT_POR unknown +#define ADT7461_REMOTE_TDATA_FRACTION_POR (0x00) +#define ADT7461_REMOTE_TOFFSET_POR (0x00) +#define ADT7461_REMOTE_TOFFSET_FRACTION_POR (0x00) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_FRACTION_POR (0x00) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_FRACTION_POR (0x00) +#define ADT7461_REMOTE_COMPARATOR_LIMIT_POR (0x55) +#define ADT7461_LOCAL_COMPARATOR_LIMIT_POR (0x55) +#define ADT7461_COMPARATOR_HYSTERESIS_POR (0x0A) +#define ADT7461_INTR_CNT_DELAY_POR (0x01) +#define ADT7461_CHIP_ID_POR (0x41) +#define ADT7461_CHIP_REV_POR (0x51) + + +// ADT7461 Register Addresses +#define ADT7461_LOCAL_TDATA_RD_ADDR (0x00) +#define ADT7461_REMOTE_TDATA_RD_ADDR (0x01) + +#define ADT7461_STATUS_RD_ADDR (0x02) +#define ADT7461_CONFIG_RD_ADDR (0x03) +#define ADT7461_CONFIG_WR_ADDR (0x09) +#define ADT7461_RATE_RD_ADDR (0x04) +#define ADT7461_RATE_WR_ADDR (0x0A) + +#define ADT7461_LOCAL_INTR_LIMIT_HIGH_RD_ADDR (0x05) +#define ADT7461_LOCAL_INTR_LIMIT_HIGH_WR_ADDR (0x0B) +#define ADT7461_LOCAL_INTR_LIMIT_LOW_RD_ADDR (0x06) +#define ADT7461_LOCAL_INTR_LIMIT_LOW_WR_ADDR (0x0C) + +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_RD_ADDR (0x07) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_WR_ADDR (0x0D) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_RD_ADDR (0x08) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_WR_ADDR (0x0E) + +#define ADT7461_ONE_SHOT_WR_ADDR (0x0F) + +#define ADT7461_REMOTE_TDATA_FRACTION_RD_ADDR (0x10) +#define ADT7461_REMOTE_TOFFSET_ADDR (0x11) +#define ADT7461_REMOTE_TOFFSET_FRACTION_ADDR (0x12) +#define ADT7461_REMOTE_INTR_LIMIT_HIGH_FRACTION_ADDR (0x13) +#define ADT7461_REMOTE_INTR_LIMIT_LOW_FRACTION_ADDR (0x14) + +#define ADT7461_REMOTE_COMPARATOR_LIMIT_ADDR (0x19) +#define ADT7461_LOCAL_COMPARATOR_LIMIT_ADDR (0x20) +#define ADT7461_COMPARATOR_HYSTERESIS_ADDR (0x21) + +#define ADT7461_INTR_CNT_DELAY_ADDR (0x22) +#define ADT7461_CHIP_ID_RD_ADDR (0xFE) +#define ADT7461_CHIP_REV_RD_ADDR (0xFF) + +#define ADT7461_INVALID_ADDR (0xF0) + + +// ADT7461 conversion range (signed values) +#define ADT7461_RANGE_STANDARD_LIMIT_HIGH (127L) +#define ADT7461_RANGE_STANDARD_LIMIT_LOW (0L) +#define ADT7461_RANGE_EXTENDED_LIMIT_HIGH (150L) +#define ADT7461_RANGE_EXTENDED_LIMIT_LOW (-64L) + +// ADT7461 data reading offsets (unsigned data) +#define ADT7461_RANGE_STANDARD_DATA_OFFSET (0UL) +#define ADT7461_RANGE_EXTENDED_DATA_OFFSET (64UL) + + +// ADT7461 Configuration Register bitfields +typedef enum +{ + // If set - extended temperature range (-55C to 150C); data offset 64C + // If cleared - stnadard temperature range (0C to 127C); data offset 0 + ADT7461ConfigBits_ExtendedRange = (0x1 << 2), + + // If set - interrupt output works as second auto cleared comparator + // If cleared - interrupt output works as level out of limit interrupt, + // cleared by (a) reading status and (b) alert response protocol over I2C + ADT7461ConfigBits_IntrAutoClear = (0x1 << 5), + + // If set - put device in stanby mode + // If cleared - put device in running mode + ADT7461ConfigBits_Standby = (0x1 << 6), + + // If set - interrupt from device is disabled + // If cleared - interrupt from device is enabled + ADT7461ConfigBits_IntrDisabled = (0x1 << 7), +} ADT7461ConfigBits; + +// ADT7461 initial configuration set by adaptation: +// ADT7461 THERM1 output is dedicated for critical h/w shutdown, and ADT7461 +// ALERT/THERM2 output is always configured as out of limit ALERT interrupt. +// Monitor is in running mode, in the range selected per ODM policy. +#define ADT7461_INITIAL_CONFIG \ + ((ADT7461ConfigBits_IntrDisabled) | \ + (ADT7461_ODM_EXTENDED_RANGE ? ADT7461ConfigBits_ExtendedRange : 0)) + + +// ADT7461 sample intervals and conversion time limits rounded to the nearest +// milliseconds, in descending order indexed by rate register DATA settings + +// RATE: 1/16 1/8 1/4 1/2 1 2 4 8 16 32 64 (1/s) +// DATA: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A +#define ADT7461_SAMPLE_INTERVALS_MS \ + 16000, 8000, 4000, 2000, 1000, 500, 250, 125, 63, 31, 16 +#define ADT7461_CONVERSION_TIME_MS \ + 115, 115, 115, 115, 115, 115, 115, 115, 13, 13, 13 + +#define ADT7461_INITIAL_RATE_SETTING (0x0A) + + +// ADT7461 I2C (SMBus) clock speed, bus timeout, retries, and fixed +// Alert Response Address (ARA). +#define ADT7461_I2C_SPEED_KHZ (400) +#define ADT7461_I2C_TIMEOUT_MS (500) +#define ADT7461_I2C_RETRY_CNT (2) +#define ADT7461_ARA_RETRY_CNT (4) +#define ADT7461_ARA (0x18) + +// ADT7461 power up delay (TODO: get spec for delay from vendor) +#define ADT7461_POWERUP_DELAY_MS (5) + +#if defined(__cplusplus) +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADT7461_REG_H + diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c new file mode 100644 index 000000000000..acabf8492c35 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "tmon_hal.h" +#include "adt7461/nvodm_tmon_adt7461.h" + +/* + * TMON adaptation is a singleton linked directly with NVRM only. + * Thread safety for TMON APIs is provided by NVRM as well. + */ + + +// Temperature Monitors suported under hal +#define TMON_ADT7461_ID (NV_ODM_GUID('a','d','t','7','4','6','1',' ')) + +#define TMON_ZONE_PSEUDOHANDLE(h, z) \ + ( (NvOdmTmonDeviceHandle)((((NvU32)(h)) << 16) | (z)) ) +#define TMON_PSEUDOHANDLE_ZONE(h) ( ((NvU32)(h)) & 0xFFFF ) + +/*****************************************************************************/ + +static NvOdmTmonDevice* +TmonGetInstance(NvOdmTmonZoneID ZoneId) +{ + static NvOdmTmonDevice s_TmonArray[NvOdmTmonZoneID_Num]; + static NvOdmTmonDevice* s_TmonMap[NvOdmTmonZoneID_Num]; + static NvBool s_Initialized = NV_FALSE; + + NvU32 i, j; + NvOdmTmonDevice* pTmon = NULL; + const NvOdmPeripheralConnectivity* pConn = NULL; + + // Check for invalid zone + if (ZoneId == 0) + return NULL; + + if (!s_Initialized) + { + NvOdmOsMemset(s_TmonArray, 0, sizeof(s_TmonArray)); + NvOdmOsMemset(s_TmonMap, 0, sizeof(s_TmonMap)); + s_Initialized = NV_TRUE; + i = 0; // allocation index + + pConn = NvOdmPeripheralGetGuid(TMON_ADT7461_ID); + if (pConn) + { + pTmon = &s_TmonArray[i++]; + pTmon->pfnInit = Adt7461Init; + pTmon->pfnDeinit = Adt7461Deinit; + pTmon->pfnTemperatureGet = Adt7461TemperatureGet; + pTmon->pfnCapabilitiesGet = Adt7461CapabilitiesGet; + pTmon->pfnParameterCapsGet = Adt7461ParameterCapsGet; + pTmon->pfnParameterConfig = Adt7461ParameterConfig; + pTmon->pfnRun = Adt7461Run; + pTmon->pfnStop = Adt7461Stop; + pTmon->pfnIntrRegister = Adt7461IntrRegister; + pTmon->pfnIntrUnregister = Adt7461IntrUnregister; + pTmon->pConn = pConn; + pTmon->RefCount = 0; + pTmon->pPrivate = NULL; + + // Fill in Zones => TMON devices map + NV_ASSERT(pConn->AddressList); + for (j = 0; j < pConn->NumAddress; j++) + { + if (pConn->AddressList[j].Interface == NvOdmIoModule_Tsense) + s_TmonMap[pConn->AddressList[j].Instance] = pTmon; + } + } + } + // Find TMON instance for the given zone + if(ZoneId < NvOdmTmonZoneID_Num) + { + pTmon = s_TmonMap[ZoneId]; + if (pTmon && pTmon->pConn) + return pTmon; + } + return NULL; +} + +/*****************************************************************************/ + +NvOdmTmonDeviceHandle +NvOdmTmonDeviceOpen(NvOdmTmonZoneID ZoneId) +{ + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon) + { + NV_ASSERT(pTmon->pfnInit && pTmon->pfnRun); + // Init TMON device on the 1st open + if (pTmon->RefCount == 0) + { + if (!pTmon->pfnInit(pTmon)) + return NULL; + } + // Make sure targeted zone is monitored + if (pTmon->pfnRun(pTmon, ZoneId)) + { + pTmon->RefCount++; + return TMON_ZONE_PSEUDOHANDLE(pTmon, ZoneId); + } + } + return NULL; +} + +void NvOdmTmonDeviceClose(NvOdmTmonDeviceHandle hTmon) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon) + { + NV_ASSERT(pTmon->pfnDeinit && pTmon->pfnStop); + (void)pTmon->pfnStop(pTmon, ZoneId); + if (pTmon->RefCount == 1) + pTmon->pfnDeinit(pTmon); + + if (pTmon->RefCount) + { + pTmon->RefCount--; + return; + } + NV_ASSERT(!"RefCount balance failed"); + } +} + +NvBool NvOdmTmonSuspend(NvOdmTmonDeviceHandle hTmon) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnStop); + if (pTmon->pfnStop(pTmon, ZoneId)) + return NV_TRUE; + } + return NV_FALSE; +} + +NvBool NvOdmTmonResume(NvOdmTmonDeviceHandle hTmon) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnRun); + if (pTmon->pfnRun(pTmon, ZoneId)) + return NV_TRUE; + } + return NV_FALSE; +} + +/*****************************************************************************/ + +NvBool +NvOdmTmonTemperatureGet( + NvOdmTmonDeviceHandle hTmon, + NvS32* pDegreesC) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnTemperatureGet); + if (pTmon->pfnTemperatureGet(pTmon, ZoneId, pDegreesC)) + return NV_TRUE; + } + return NV_FALSE; +} + +/*****************************************************************************/ + +void +NvOdmTmonCapabilitiesGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonCapabilities* pCaps) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnCapabilitiesGet); + pTmon->pfnCapabilitiesGet(pTmon, ZoneId, pCaps); + } + else if (pCaps) + { + NvOdmOsMemset(pCaps, 0, sizeof(NvOdmTmonCapabilities)); + pCaps->Tmax = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->Tmin = ODM_TMON_PARAMETER_UNSPECIFIED; + } +} + +void +NvOdmTmonParameterCapsGet( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonConfigParam ParamId, + NvOdmTmonParameterCaps* pCaps) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnParameterCapsGet); + pTmon->pfnParameterCapsGet(pTmon, ZoneId, ParamId, pCaps); + } + else if (pCaps) + { + NvOdmOsMemset(pCaps, 0, sizeof(NvOdmTmonParameterCaps)); + pCaps->MaxValue = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->MinValue = ODM_TMON_PARAMETER_UNSPECIFIED; + pCaps->OdmProtected = NV_TRUE; + } +} + +NvBool +NvOdmTmonParameterConfig( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonConfigParam ParamId, + NvS32* pSetting) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnParameterConfig); + if (pTmon->pfnParameterConfig(pTmon, ZoneId, ParamId, pSetting)) + return NV_TRUE; + } + return NV_FALSE; +} + +/*****************************************************************************/ + +NvOdmTmonIntrHandle +NvOdmTmonIntrRegister( + NvOdmTmonDeviceHandle hTmon, + NvOdmInterruptHandler Callback, + void* CallbackArg) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + NvOdmTmonIntrHandle hIntr = NULL; + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnIntrRegister); + hIntr = pTmon->pfnIntrRegister( + pTmon, ZoneId, Callback, CallbackArg); + } + return hIntr; +} + +void +NvOdmTmonIntrUnregister( + NvOdmTmonDeviceHandle hTmon, + NvOdmTmonIntrHandle hIntr) +{ + NvOdmTmonZoneID ZoneId = TMON_PSEUDOHANDLE_ZONE(hTmon); + NvOdmTmonDevice* pTmon = TmonGetInstance(ZoneId); + + if (pTmon && pTmon->RefCount) + { + NV_ASSERT(pTmon->pfnIntrUnregister); + pTmon->pfnIntrUnregister(pTmon, ZoneId, hIntr); + } +} + +/*****************************************************************************/ diff --git a/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h new file mode 100644 index 000000000000..5e5e1141c584 --- /dev/null +++ b/arch/arm/mach-tegra/odm_kit/adaptations/tmon/tmon_hal.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2009 NVIDIA Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NVIDIA Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * <b>NVIDIA Tegra ODM Kit: + * Abstraction layer stub for Temperature Monitor adaptations</b> + */ + +#ifndef INCLUDED_NVODM_TMON_ADAPTATION_HAL_H +#define INCLUDED_NVODM_TMON_ADAPTATION_HAL_H + +#include "nvcommon.h" +#include "nvodm_tmon.h" +#include "nvodm_query_discovery.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef NvBool (*pfnTmonInit)(NvOdmTmonDeviceHandle); +typedef void (*pfnTmonDeinit)(NvOdmTmonDeviceHandle); +typedef NvBool (*pfnTmonTemperatureGet)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvS32*); +typedef void (*pfnTmonCapabilitiesGet)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonCapabilities*); +typedef void (*pfnTmonParameterCapsGet) + (NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonConfigParam, NvOdmTmonParameterCaps*); +typedef NvBool (*pfnTmonParameterConfig)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonConfigParam, NvS32*); +typedef NvBool (*pfnTmonRun)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID); +typedef NvBool (*pfnTmonStop)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID); +typedef NvOdmTmonIntrHandle + (*pfnTmonIntrRegister)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmInterruptHandler, void*); +typedef void (*pfnTmonIntrUnregister)(NvOdmTmonDeviceHandle, NvOdmTmonZoneID, NvOdmTmonIntrHandle); + +typedef struct NvOdmTmonDeviceRec +{ + pfnTmonInit pfnInit; + pfnTmonDeinit pfnDeinit; + pfnTmonTemperatureGet pfnTemperatureGet; + pfnTmonCapabilitiesGet pfnCapabilitiesGet; + pfnTmonParameterCapsGet pfnParameterCapsGet; + pfnTmonParameterConfig pfnParameterConfig; + pfnTmonRun pfnRun; + pfnTmonStop pfnStop; + pfnTmonIntrRegister pfnIntrRegister; + pfnTmonIntrUnregister pfnIntrUnregister; + + const NvOdmPeripheralConnectivity* pConn; + NvU32 RefCount; + void *pPrivate; +} NvOdmTmonDevice; + +#ifdef __cplusplus +} +#endif + +#endif //INCLUDED_NVODM_TMON_ADAPTATION_HAL_H |