M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
@@ -0,0 +1,442 @@
/* Copyright (c) 2009-2012, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <stdint.h>
#include <debug.h>
#include <reg.h>
#include <kernel/thread.h>
#include <platform/iomap.h>
#include <platform/clock.h>
#include <platform/scm-io.h>
#include <uart_dm.h>
#include <gsbi.h>
#include <mmc.h>
/* Read, modify, then write-back a register. */
static void rmwreg(uint32_t val, uint32_t reg, uint32_t mask)
{
uint32_t regval = readl(reg);
regval &= ~mask;
regval |= val;
writel(regval, reg);
}
/* Enable/disable for non-shared NT PLLs. */
int nt_pll_enable(uint8_t src, uint8_t enable)
{
static const struct {
uint32_t const mode_reg;
uint32_t const status_reg;
} pll_reg[] = {
[PLL_1] = {
MM_PLL0_MODE_REG, MM_PLL0_STATUS_REG},[PLL_2] = {
MM_PLL1_MODE_REG, MM_PLL1_STATUS_REG},[PLL_3] = {
MM_PLL2_MODE_REG, MM_PLL2_STATUS_REG},};
uint32_t pll_mode;
pll_mode = secure_readl(pll_reg[src].mode_reg);
if (enable) {
/* Disable PLL bypass mode. */
pll_mode |= (1 << 1);
secure_writel(pll_mode, pll_reg[src].mode_reg);
/* H/W requires a 5us delay between disabling the bypass and
* de-asserting the reset. Delay 10us just to be safe. */
udelay(10);
/* De-assert active-low PLL reset. */
pll_mode |= (1 << 2);
secure_writel(pll_mode, pll_reg[src].mode_reg);
/* Enable PLL output. */
pll_mode |= (1 << 0);
secure_writel(pll_mode, pll_reg[src].mode_reg);
/* Wait until PLL is enabled. */
while (!secure_readl(pll_reg[src].status_reg)) ;
} else {
/* Disable the PLL output, disable test mode, enable
* the bypass mode, and assert the reset. */
pll_mode &= 0xFFFFFFF0;
secure_writel(pll_mode, pll_reg[src].mode_reg);
}
return 0;
}
/* Write the M,N,D values and enable the MDP Core Clock */
void config_mdp_clk(uint32_t ns,
uint32_t md,
uint32_t cc,
uint32_t ns_addr, uint32_t md_addr, uint32_t cc_addr)
{
unsigned int val = 0;
/* MN counter reset */
val = 1 << 31;
secure_writel(val, ns_addr);
/* Write the MD and CC register values */
secure_writel(md, md_addr);
secure_writel(cc, cc_addr);
/* Reset the clk control, and Write ns val */
val = 1 << 31;
val |= ns;
secure_writel(val, ns_addr);
/* Clear MN counter reset */
val = 1 << 31;
val = ~val;
val = val & secure_readl(ns_addr);
secure_writel(val, ns_addr);
/* Enable MND counter */
val = 1 << 8;
val = val | secure_readl(cc_addr);
secure_writel(val, cc_addr);
/* Enable the root of the clock tree */
val = 1 << 2;
val = val | secure_readl(cc_addr);
secure_writel(val, cc_addr);
/* Enable the MDP Clock */
val = 1 << 0;
val = val | secure_readl(cc_addr);
secure_writel(val, cc_addr);
}
/* Write the M,N,D values and enable the Pixel Core Clock */
void config_pixel_clk(uint32_t ns,
uint32_t md,
uint32_t cc,
uint32_t ns_addr, uint32_t md_addr, uint32_t cc_addr)
{
unsigned int val = 0;
/* Activate the reset for the M/N Counter */
val = 1 << 7;
secure_writel(val, ns_addr);
/* Write the MD and CC register values */
secure_writel(md, md_addr);
secure_writel(cc, cc_addr);
/* Write the ns value, and active reset for M/N Counter, again */
val = 1 << 7;
val |= ns;
secure_writel(val, ns_addr);
/* De-activate the reset for M/N Counter */
val = 1 << 7;
val = ~val;
val = val & secure_readl(ns_addr);
secure_writel(val, ns_addr);
/* Enable MND counter */
val = 1 << 5;
val = val | secure_readl(cc_addr);
secure_writel(val, cc_addr);
/* Enable the root of the clock tree */
val = 1 << 2;
val = val | secure_readl(cc_addr);
secure_writel(val, cc_addr);
/* Enable the MDP Clock */
val = 1 << 0;
val = val | secure_readl(cc_addr);
secure_writel(val, cc_addr);
/* Enable the LCDC Clock */
val = 1 << 8;
val = val | secure_readl(cc_addr);
secure_writel(val, cc_addr);
}
/* Set rate and enable the clock */
void clock_config(uint32_t ns, uint32_t md, uint32_t ns_addr, uint32_t md_addr)
{
unsigned int val = 0;
/* Activate the reset for the M/N Counter */
val = 1 << 7;
writel(val, ns_addr);
/* Write the MD value into the MD register */
writel(md, md_addr);
/* Write the ns value, and active reset for M/N Counter, again */
val = 1 << 7;
val |= ns;
writel(val, ns_addr);
/* De-activate the reset for M/N Counter */
val = 1 << 7;
val = ~val;
val = val & readl(ns_addr);
writel(val, ns_addr);
/* Enable the M/N Counter */
val = 1 << 8;
val = val | readl(ns_addr);
writel(val, ns_addr);
/* Enable the Clock Root */
val = 1 << 11;
val = val | readl(ns_addr);
writel(val, ns_addr);
/* Enable the Clock Branch */
val = 1 << 9;
val = val | readl(ns_addr);
writel(val, ns_addr);
}
void pll8_enable(void)
{
/* Currently both UART and USB depend on this PLL8 clock initialization. */
unsigned int curr_value = 0;
/* Vote for PLL8 to be enabled */
curr_value = readl(MSM_BOOT_PLL_ENABLE_SC0);
curr_value |= (1 << 8);
writel(curr_value, MSM_BOOT_PLL_ENABLE_SC0);
/* Proceed only after PLL is enabled */
while (!(readl(MSM_BOOT_PLL8_STATUS) & (1 << 16))) ;
}
void uart_clock_init(void)
{
/* Enable PLL8 */
pll8_enable();
}
void hsusb_clock_init(void)
{
int val;
/* Enable PLL8 */
pll8_enable();
//Set 7th bit in NS Register
val = 1 << 7;
writel(val, USB_HS1_XCVR_FS_CLK_NS);
//Set rate specific value in MD
writel(0x000500DF, USB_HS1_XCVR_FS_CLK_MD);
//Set value in NS register
val = 1 << 7;
val |= 0x00E400C3;
writel(val, USB_HS1_XCVR_FS_CLK_NS);
// Clear 7th bit
val = 1 << 7;
val = ~val;
val = val & readl(USB_HS1_XCVR_FS_CLK_NS);
writel(val, USB_HS1_XCVR_FS_CLK_NS);
//set 11th bit
val = 1 << 11;
val |= readl(USB_HS1_XCVR_FS_CLK_NS);
writel(val, USB_HS1_XCVR_FS_CLK_NS);
//set 9th bit
val = 1 << 9;
val |= readl(USB_HS1_XCVR_FS_CLK_NS);
writel(val, USB_HS1_XCVR_FS_CLK_NS);
//set 8th bit
val = 1 << 8;
val |= readl(USB_HS1_XCVR_FS_CLK_NS);
writel(val, USB_HS1_XCVR_FS_CLK_NS);
}
void ce_clock_init(void)
{
/* Enable clock branch for CE2 */
writel((1 << 4), CE2_HCLK_CTL);
return;
}
/* Configure UART clock - based on the gsbi id */
void clock_config_uart_dm(uint8_t id)
{
uint32_t ns = UART_DM_CLK_NS_115200;
uint32_t md = UART_DM_CLK_MD_115200;
/* Enable PLL8 */
pll8_enable();
/* Enable gsbi_uart_clk */
clock_config(ns, md, GSBIn_UART_APPS_NS(id), GSBIn_UART_APPS_MD(id));
/* Enable the GSBI HCLK */
writel(GSBI_HCLK_CTL_CLK_ENA << GSBI_HCLK_CTL_S, GSBIn_HCLK_CTL(id));
}
/* Configure i2c clock */
void clock_config_i2c(uint8_t id, uint32_t freq)
{
uint32_t ns;
uint32_t md;
switch (freq) {
case 24000000:
ns = I2C_CLK_NS_24MHz;
md = I2C_CLK_MD_24MHz;
break;
default:
ASSERT(0);
}
clock_config(ns, md, GSBIn_QUP_APPS_NS(id), GSBIn_QUP_APPS_MD(id));
/* Enable the GSBI HCLK */
writel(GSBI_HCLK_CTL_CLK_ENA << GSBI_HCLK_CTL_S, GSBIn_HCLK_CTL(id));
}
/* Intialize MMC clock */
void clock_init_mmc(uint32_t interface)
{
/* Nothing to be done. */
}
/* Configure MMC clock */
void clock_config_mmc(uint32_t interface, uint32_t freq)
{
uint32_t reg = 0;
switch (freq) {
case MMC_CLK_400KHZ:
clock_config(SDC_CLK_NS_400KHZ,
SDC_CLK_MD_400KHZ,
SDC_NS(interface), SDC_MD(interface));
break;
case MMC_CLK_48MHZ:
case MMC_CLK_50MHZ: /* Max supported is 48MHZ */
clock_config(SDC_CLK_NS_48MHZ,
SDC_CLK_MD_48MHZ,
SDC_NS(interface), SDC_MD(interface));
break;
default:
ASSERT(0);
}
reg |= MMC_BOOT_MCI_CLK_ENABLE;
reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
writel(reg, MMC_BOOT_MCI_CLK);
/* Wait for the MMC_BOOT_MCI_CLK write to go through. */
mmc_mclk_reg_wr_delay();
/* Wait 1 ms to provide the free running SD CLK to the card. */
mdelay(1);
}
void mdp_clock_init(void)
{
/* Turn on the PLL2, to ramp up the MDP clock to max (200MHz) */
nt_pll_enable(PLL_2, 1);
config_mdp_clk(MDP_NS_VAL, MDP_MD_VAL,
MDP_CC_VAL, MDP_NS_REG, MDP_MD_REG, MDP_CC_REG);
}
void mmss_pixel_clock_configure(uint32_t pclk_id)
{
if (pclk_id == PIXEL_CLK_INDEX_25M) {
config_pixel_clk(PIXEL_NS_VAL_25M, PIXEL_MD_VAL_25M,
PIXEL_CC_VAL_25M, MMSS_PIXEL_NS_REG,
MMSS_PIXEL_MD_REG, MMSS_PIXEL_CC_REG);
} else {
config_pixel_clk(PIXEL_NS_VAL, PIXEL_MD_VAL,
PIXEL_CC_VAL, MMSS_PIXEL_NS_REG,
MMSS_PIXEL_MD_REG, MMSS_PIXEL_CC_REG);
}
}
void configure_dsicore_dsiclk()
{
unsigned char mnd_mode, root_en, clk_en;
unsigned long src_sel = 0x3; // dsi_phy_pll0_src
unsigned long pre_div_func = 0x00; // predivide by 1
unsigned long pmxo_sel;
secure_writel(pre_div_func << 14 | src_sel, DSI_NS_REG);
mnd_mode = 0; // Bypass MND
root_en = 1;
clk_en = 1;
pmxo_sel = 0;
secure_writel((pmxo_sel << 8) | (mnd_mode << 6), DSI_CC_REG);
secure_writel(secure_readl(DSI_CC_REG) | root_en << 2, DSI_CC_REG);
secure_writel(secure_readl(DSI_CC_REG) | clk_en, DSI_CC_REG);
}
void configure_dsicore_byteclk(void)
{
secure_writel(0x00400401, MISC_CC2_REG); // select pxo
}
void configure_dsicore_pclk(void)
{
unsigned char mnd_mode, root_en, clk_en;
unsigned long src_sel = 0x3; // dsi_phy_pll0_src
unsigned long pre_div_func = 0x01; // predivide by 2
secure_writel(pre_div_func << 12 | src_sel, DSI_PIXEL_NS_REG);
mnd_mode = 0; // Bypass MND
root_en = 1;
clk_en = 1;
secure_writel(mnd_mode << 6, DSI_PIXEL_CC_REG);
secure_writel(secure_readl(DSI_PIXEL_CC_REG) | root_en << 2, DSI_PIXEL_CC_REG);
secure_writel(secure_readl(DSI_PIXEL_CC_REG) | clk_en, DSI_PIXEL_CC_REG);
}
/* Async Reset CE2 */
void ce_async_reset()
{
/* Enable Async reset bit for HCLK CE2 */
writel((1<<7) | (1 << 4), CE2_HCLK_CTL);
/* Add a small delay between switching the
* async intput from high to low
*/
udelay(2);
/* Disable Async reset bit for HCLK for CE2 */
writel((1 << 4), CE2_HCLK_CTL);
return;
}
@@ -0,0 +1,92 @@
/* Copyright (c) 2010-2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <debug.h>
#include <reg.h>
#include <platform/iomap.h>
#include <platform/gpio.h>
#include <gsbi.h>
void gpio_tlmm_config(uint32_t gpio, uint8_t func,
uint8_t dir, uint8_t pull,
uint8_t drvstr, uint32_t enable)
{
unsigned int val = 0;
val |= pull;
val |= func << 2;
val |= drvstr << 6;
val |= enable << 9;
unsigned int *addr = (unsigned int *)GPIO_CONFIG_ADDR(gpio);
writel(val, addr);
return;
}
void gpio_set(uint32_t gpio, uint32_t dir)
{
unsigned int *addr = (unsigned int *)GPIO_IN_OUT_ADDR(gpio);
writel(dir, addr);
return;
}
/* Configure gpio for uart - based on gsbi id */
void gpio_config_uart_dm(uint8_t id)
{
switch (id) {
case GSBI_ID_12:
/* configure rx gpio */
gpio_tlmm_config(117, 2, GPIO_INPUT, GPIO_NO_PULL,
GPIO_8MA, GPIO_DISABLE);
/* configure tx gpio */
gpio_tlmm_config(118, 2, GPIO_OUTPUT, GPIO_NO_PULL,
GPIO_8MA, GPIO_DISABLE);
break;
default:
ASSERT(0);
}
}
/* Configure gpio for i2c - based on gsbi id */
void gpio_config_i2c(uint8_t id)
{
switch (id) {
case GSBI_ID_8:
gpio_tlmm_config(64, 1, GPIO_OUTPUT, GPIO_NO_PULL,
GPIO_2MA, GPIO_DISABLE);
gpio_tlmm_config(65, 1, GPIO_OUTPUT, GPIO_NO_PULL,
GPIO_2MA, GPIO_DISABLE);
break;
default:
ASSERT(0);
}
}
void gpio_config_pshold(void)
{
gpio_tlmm_config(92, 1, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_12MA,
GPIO_DISABLE);
}
@@ -0,0 +1,249 @@
/* Copyright (c) 2010-2013, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <hdmi.h>
#include <platform/timer.h>
#include <platform/gpio.h>
#include <platform/clock.h>
#include <platform/iomap.h>
#include <platform/scm-io.h>
extern void hdmi_app_clk_init(int);
extern int hdmi_msm_turn_on();
#define FB_ADDR 0x43E00000
static struct fbcon_config fb_cfg = {
.height = DTV_FB_HEIGHT,
.width = DTV_FB_WIDTH,
.stride = DTV_FB_WIDTH,
.format = DTV_FORMAT_RGB565,
.bpp = DTV_BPP,
.update_start = NULL,
.update_done = NULL,
.base = FB_ADDR;
};
struct fbcon_config *get_fbcon(void)
{
return &fb_cfg;
}
void hdmi_msm_init_phy()
{
dprintf(SPEW, "PHY INIT\n");
uint32_t offset = 0;
uint32_t len = 0;
writel(0x0C, HDMI_PHY_REG_0);
writel(0x54, HDMI_PHY_REG_1);
writel(0x7F, HDMI_PHY_REG_2);
writel(0x3F, HDMI_PHY_REG_2);
writel(0x1F, HDMI_PHY_REG_2);
writel(0x01, HDMI_PHY_REG_3);
writel(0x00, HDMI_PHY_REG_9);
writel(0x03, HDMI_PHY_REG_12);
writel(0x01, HDMI_PHY_REG_2);
writel(0x81, HDMI_PHY_REG_2);
offset = (HDMI_PHY_REG_4 - MSM_HDMI_BASE);
len = (HDMI_PHY_REG_11 - MSM_HDMI_BASE);
while (offset <= len) {
writel(0x0, MSM_HDMI_BASE + offset);
offset += 4;
}
writel(0x13, HDMI_PHY_REG_12);
}
static void hdmi_gpio_config()
{
uint32_t func;
uint32_t pull;
uint32_t drv;
uint32_t enable = 0;
uint32_t dir;
func = 1;
pull = GPIO_NO_PULL;
drv = GPIO_16MA;
dir = 1;
gpio_tlmm_config(170, func, dir, pull, drv, enable);
gpio_tlmm_config(171, func, dir, pull, drv, enable);
func = 1;
pull = GPIO_PULL_DOWN;
drv = GPIO_16MA;
gpio_tlmm_config(172, func, dir, pull, drv, enable);
}
/*
* This is the start function which initializes clocks , gpios for hdmi
* & powers on the HDMI core
*/
void hdmi_power_init()
{
// Enable HDMI clocks
hdmi_app_clk_init(1);
// Enable pm8058
pm8058_ldo_set_voltage();
pm8058_vreg_enable();
// configure HDMI Gpio
hdmi_gpio_config();
// Enable pm8091
pm8901_mpp_enable();
pm8901_vs_enable();
// Power on HDMI
hdmi_msm_turn_on();
}
static void hdmi_msm_reset_core()
{
uint32_t reg_val = 0;
hdmi_msm_set_mode(0);
// Disable clocks
hdmi_app_clk_init(0);
udelay(5);
// Enable clocks
hdmi_app_clk_init(1);
reg_val = secure_readl(SW_RESET_CORE_REG);
reg_val |= BIT(11);
secure_writel(reg_val, SW_RESET_CORE_REG);
udelay(5);
reg_val = secure_readl(SW_RESET_AHB_REG);
reg_val |= BIT(9);
secure_writel(reg_val, SW_RESET_AHB_REG);
udelay(5);
reg_val = secure_readl(SW_RESET_AHB_REG);
reg_val |= BIT(9);
secure_writel(reg_val, SW_RESET_AHB_REG);
udelay(20);
reg_val = secure_readl(SW_RESET_CORE_REG);
reg_val &= ~(BIT(11));
secure_writel(reg_val, SW_RESET_CORE_REG);
udelay(5);
reg_val = secure_readl(SW_RESET_AHB_REG);
reg_val &= ~(BIT(9));
secure_writel(reg_val, SW_RESET_AHB_REG);
udelay(5);
reg_val = secure_readl(SW_RESET_AHB_REG);
reg_val &= ~(BIT(9));
secure_writel(reg_val, SW_RESET_AHB_REG);
udelay(5);
}
int hdmi_dtv_on()
{
uint32_t val, pll_mode, ns_val, pll_config;
// Configure PLL2 for tv src clk
pll_mode |= BIT(1);
secure_writel(pll_mode, MM_PLL2_MODE_REG);
udelay(10);
pll_mode = secure_readl(MM_PLL2_MODE_REG);
pll_mode &= ~BIT(0);
secure_writel(pll_mode, MM_PLL2_MODE_REG);
pll_mode &= ~BIT(2);
secure_writel(pll_mode, MM_PLL2_MODE_REG);
secure_writel(0x2C, MM_PLL2_L_VAL_REG);
secure_writel(0x0, MM_PLL2_M_VAL_REG);
secure_writel(0x0, MM_PLL2_N_VAL_REG);
udelay(10);
val = 0xA6248F;
secure_writel(val, MM_PLL2_CONFIG_REG);
// set M N D
ns_val = secure_readl(TV_NS_REG);
ns_val |= BIT(7);
secure_writel(ns_val, TV_NS_REG);
secure_writel(0xff, TV_MD_REG);
val = secure_readl(TV_CC_REG);
val &= ~(BM(7, 6));
val |= CC(6, 0);
secure_writel(val, TV_CC_REG);
ns_val &= ~BIT(7);
secure_writel(ns_val, TV_NS_REG);
// confiure hdmi_ref clk to run @ 148.5 MHz
val = secure_readl(MISC_CC2_REG);
val &= ~(BIT(28) | BM(21, 18));
ns_val = NS_MM(23, 16, 0, 0, 15, 14, 2, 2, 0, 3);
val |= (BIT(28) | BVAL(21, 18, (ns_val >> 14) & 0x3));
secure_writel(val, MISC_CC2_REG);
pll_mode |= BIT(2);
secure_writel(pll_mode, MM_PLL2_MODE_REG);
pll_mode |= BIT(0);
secure_writel(pll_mode, MM_PLL2_MODE_REG);
udelay(50);
// Enable TV src clk
val = secure_readl(TV_NS_REG);
val &= ~(BM(23, 16) | BM(15, 14) | BM(2, 0));
ns_val = NS_MM(23, 16, 0, 0, 15, 14, 2, 2, 0, 3);
val |= (ns_val & (BM(23, 16) | BM(15, 14) | BM(2, 0)));
secure_writel(val, TV_NS_REG);
// Enable hdmi clk
val = secure_readl(TV_CC_REG);
val |= BIT(12);
secure_writel(val, TV_CC_REG);
// Root en of tv src clk
val = secure_readl(TV_CC_REG);
val |= BIT(2);
secure_writel(val, TV_CC_REG);
// De-Assert hdmi clk
val = secure_readl(SW_RESET_CORE_REG);
val |= BIT(1);
secure_writel(val, SW_RESET_CORE_REG);
udelay(10);
val = secure_readl(SW_RESET_CORE_REG);
val &= ~(BIT(1));
secure_writel(val, SW_RESET_CORE_REG);
udelay(10);
// enable mdp dtv clk
val = secure_readl(TV_CC_REG);
val |= BIT(0);
secure_writel(val, TV_CC_REG);
udelay(10);
return 0;
}
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PLATFORM_ADM_H
#define __PLATFORM_ADM_H
/* Channel #s and security domain */
#define ADM_CHN 8
#define ADM_SD 1
#endif
@@ -0,0 +1,152 @@
/*
* * Copyright (c) 2010-2012, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PLATFORM_MSM8X60_CLOCK_H
#define __PLATFORM_MSM8X60_CLOCK_H
#define MSM_MMSS_CLK_CTL_SIZE 4096
#define REG_MM(off) (MSM_MMSS_CLK_CTL_BASE + (off))
#define AHB_NS_REG REG_MM(0x0004)
#define AXI_NS_REG REG_MM(0x0014)
#define MM_PLL0_CONFIG_REG REG_MM(0x0310)
#define MM_PLL0_L_VAL_REG REG_MM(0x0304)
#define MM_PLL0_M_VAL_REG REG_MM(0x0308)
#define MM_PLL0_MODE_REG REG_MM(0x0300)
#define MM_PLL0_N_VAL_REG REG_MM(0x030C)
#define MM_PLL0_STATUS_REG REG_MM(0x0318)
#define MM_PLL1_CONFIG_REG REG_MM(0x032C)
#define MM_PLL1_L_VAL_REG REG_MM(0x0320)
#define MM_PLL1_M_VAL_REG REG_MM(0x0324)
#define MM_PLL1_MODE_REG REG_MM(0x031C)
#define MM_PLL1_N_VAL_REG REG_MM(0x0328)
#define MM_PLL1_STATUS_REG REG_MM(0x0334)
#define MM_PLL2_CONFIG_REG REG_MM(0x0348)
#define MM_PLL2_L_VAL_REG REG_MM(0x033C)
#define MM_PLL2_M_VAL_REG REG_MM(0x0340)
#define MM_PLL2_MODE_REG REG_MM(0x0338)
#define MM_PLL2_N_VAL_REG REG_MM(0x0344)
#define MM_PLL2_STATUS_REG REG_MM(0x0350)
/* LCD related clock defines */
#define MMSS_AHB_NS_REG REG_MM(0x04)
#define MMSS_AHB_EN_REG REG_MM(0x08)
#define MMSS_AXI_NS_REG REG_MM(0x14)
#define MMSS_MAXI_EN_REG REG_MM(0x18)
#define MMSS_MAXI_EN2_REG REG_MM(0x20)
#define MMSS_SAXI_EN_REG REG_MM(0x30)
#define DSI_NS_REG REG_MM(0x54)
#define DSI_MD_REG REG_MM(0x50)
#define DSI_CC_REG REG_MM(0x4C)
#define MISC_CC2_REG REG_MM(0x5C)
#define MDP_CC_REG REG_MM(0xC0)
#define MDP_MD_REG REG_MM(0xC4)
#define MDP_NS_REG REG_MM(0xD0)
#define MMSS_PIXEL_MD_REG REG_MM(0xD8)
#define MMSS_PIXEL_NS_REG REG_MM(0xDC)
#define MMSS_PIXEL_CC_REG REG_MM(0xD4)
/* MMSS DSI Pixel Registers not MMSS Pixel */
#define DSI_PIXEL_MD_REG REG_MM(0x134)
#define DSI_PIXEL_NS_REG REG_MM(0x138)
#define DSI_PIXEL_CC_REG REG_MM(0x130)
/* Configured at 200 MHz */
#define MDP_NS_VAL 0x3F000008
#define MDP_MD_VAL 0x000001FB
#define MDP_CC_VAL 0x00000400
/* Configured at 53.99 MHz */
#define PIXEL_NS_VAL 0xFE4F4002
#define PIXEL_MD_VAL 0x00A9FDA6
#define PIXEL_CC_VAL 0x00000080
/* Configured at 25 MHz (AUO Panel) */
#define PIXEL_NS_VAL_25M 0xFFF10002
#define PIXEL_MD_VAL_25M 0x0001FFF0
#define PIXEL_CC_VAL_25M 0x00000080
/* PIXEL clock index */
#define PIXEL_CLK_INDEX_54M 0 /* 53.99MHz */
#define PIXEL_CLK_INDEX_25M 1 /* 25MHz */
#define MSM_CLK_CTL_BASE 0x00900000
#define BB_PLL8_L_VAL_REG (MSM_CLK_CTL_BASE + 0x3144)
#define BB_PLL8_M_VAL_REG (MSM_CLK_CTL_BASE + 0x3148)
#define BB_PLL8_MODE_REG (MSM_CLK_CTL_BASE + 0x3140)
#define BB_PLL8_N_VAL_REG (MSM_CLK_CTL_BASE + 0x314C)
#define CE2_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2740)
/* NS/MD value for UART */
#define UART_DM_CLK_NS_115200 0xFD940043
#define UART_DM_CLK_MD_115200 0x0006FD8E
#define UART_DM_CLK_RX_TX_BIT_RATE 0xEE
/* GSBI/I2C QUP APPS CLK definitions */
#define I2C_CLK_MD_24MHz 0x000100FB
#define I2C_CLK_NS_24MHz 0x00FC005B
/* NS/MD value for MMC */
#define SDC_CLK_NS_400KHZ 0x0010005B
#define SDC_CLK_MD_400KHZ 0x0001000F
#define SDC_CLK_NS_48MHZ 0x00FE005B
#define SDC_CLK_MD_48MHZ 0x000100FD
/* HDMI Clocks */
#define SW_RESET_AHB_REG REG_MM(0x020C)
#define SW_RESET_CORE_REG REG_MM(0x0210)
#define TV_CC_REG REG_MM(0x00EC)
#define TV_NS_REG REG_MM(0x00F4)
#define TV_MD_REG REG_MM(0x00F0)
enum clk_sources {
PLL_0 = 0,
PLL_1,
PLL_2,
PLL_3,
PLL_4,
PLL_5,
PLL_6,
PLL_7,
PLL_8,
MXO,
PXO,
CXO,
NUM_SRC
};
void hsusb_clock_init(void);
void clock_config_uart_dm(uint8_t id);
void clock_config_i2c(uint8_t id, uint32_t freq);
void mdp_clock_init(void);
void mmss_pixel_clock_configure(uint32_t pclk_index);
#endif
@@ -0,0 +1,63 @@
/* Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PLATFORM_MSM8X60_GPIO_H
#define __PLATFORM_MSM8X60_GPIO_H
/* GPIO TLMM: Direction */
#ifndef GPIO_INPUT
#define GPIO_INPUT 0
#endif
#ifndef GPIO_OUTPUT
#define GPIO_OUTPUT 1
#endif
/* GPIO TLMM: Pullup/Pulldown */
#define GPIO_NO_PULL 0
#define GPIO_PULL_DOWN 1
#define GPIO_KEEPER 2
#define GPIO_PULL_UP 3
/* GPIO TLMM: Drive Strength */
#define GPIO_2MA 0
#define GPIO_4MA 1
#define GPIO_6MA 2
#define GPIO_8MA 3
#define GPIO_10MA 4
#define GPIO_12MA 5
#define GPIO_14MA 6
#define GPIO_16MA 7
/* GPIO TLMM: Status */
#define GPIO_ENABLE 0
#define GPIO_DISABLE 1
void gpio_config_i2c(uint8_t gsbi_id);
void gpio_config_uart_dm(uint8_t id);
#endif
@@ -0,0 +1,208 @@
/* Copyright (c) 2008, Google Inc.
* All rights reserved.
*
* Copyright (c) 2009-2011, The Linux Foundation. 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 Google, Inc. 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 OWNER 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 _PLATFORM_MSM8X60_IOMAP_H_
#define _PLATFORM_MSM8X60_IOMAP_H_
#define MSM_IOMAP_BASE 0x00100000
#define MSM_IOMAP_END 0x28000000
#define MSM_USB_BASE 0x12500000
#define MSM_UART3_BASE 0xA9C00000
#define MSM_VIC_BASE 0x02080000
#define MSM_TMR_BASE 0x02000000
#define MSM_GPT_BASE (MSM_TMR_BASE + 0x04)
#define MSM_DGT_BASE (MSM_TMR_BASE + 0x24)
#define SPSS_TIMER_STATUS (MSM_TMR_BASE + 0x88)
#define GPT_REG(off) (MSM_GPT_BASE + (off))
#define DGT_REG(off) (MSM_DGT_BASE + (off))
#define GPT_MATCH_VAL GPT_REG(0x0000)
#define GPT_COUNT_VAL GPT_REG(0x0004)
#define GPT_ENABLE GPT_REG(0x0008)
#define GPT_CLEAR GPT_REG(0x000C)
#define DGT_MATCH_VAL DGT_REG(0x0000)
#define DGT_COUNT_VAL DGT_REG(0x0004)
#define DGT_ENABLE DGT_REG(0x0008)
#define DGT_CLEAR DGT_REG(0x000C)
#define DGT_CLK_CTL DGT_REG(0x0010)
#define MSM_TCSR_BASE 0x16B00000
#define MSM_GIC_CPU_BASE 0x02081000
#define MSM_GIC_DIST_BASE 0x02080000
#define MSM_TCSR_SIZE 4096
#define MSM_GPT_BASE (MSM_TMR_BASE + 0x04)
#define MSM_CSR_BASE 0x02081000
#define MSM_GCC_BASE 0x02082000
#define MSM_ACC0_BASE 0x02041000
#define MSM_ACC1_BASE 0x02051000
#define TLMM_BASE_ADDR 0x00800000
#define TCSR_WDOG_CFG 0x30
#define MSM_WDT0_RST (MSM_TMR_BASE + 0x38)
#define MSM_WDT0_EN (MSM_TMR_BASE + 0x40)
#define MSM_WDT0_BT (MSM_TMR_BASE + 0x4C)
#define MSM_PSHOLD_CTL_SU (TLMM_BASE_ADDR + 0x820)
#define MSM_SDC1_BASE 0x12400000
#define MSM_CRYPTO_BASE 0x18500000
#define MSM_SHARED_BASE 0x40000000
#define SURF_DEBUG_LED_ADDR 0x1D000202
#define TLMM_BASE_ADDR 0x00800000
#define GPIO_CONFIG_ADDR(x) (TLMM_BASE_ADDR + 0x1000 + (x)*0x10)
#define GPIO_IN_OUT_ADDR(x) (TLMM_BASE_ADDR + 0x1004 + (x)*0x10)
#define GPIO_CFG133_ADDR 0x00801850
#define GPIO_CFG135_ADDR 0x00801870
#define GPIO_CFG136_ADDR 0x00801880
#define GPIO_CFG137_ADDR 0x00801890
#define GPIO_CFG138_ADDR 0x008018A0
#define GPIO_CFG139_ADDR 0x008018B0
#define GPIO_CFG140_ADDR 0x008018C0
#define GPIO_CFG141_ADDR 0x008018D0
#define GPIO_CFG142_ADDR 0x008018E0
#define GPIO_CFG143_ADDR 0x008018F0
#define GPIO_CFG144_ADDR 0x00801900
#define GPIO_CFG145_ADDR 0x00801910
#define GPIO_CFG146_ADDR 0x00801920
#define GPIO_CFG147_ADDR 0x00801930
#define GPIO_CFG148_ADDR 0x00801940
#define GPIO_CFG149_ADDR 0x00801950
#define GPIO_CFG150_ADDR 0x00801960
#define GPIO_CFG151_ADDR 0x00801970
#define GPIO_CFG152_ADDR 0x00801980
#define GPIO_CFG153_ADDR 0x00801990
#define GPIO_CFG154_ADDR 0x008019A0
#define GPIO_CFG155_ADDR 0x008019B0
#define GPIO_CFG156_ADDR 0x008019C0
#define GPIO_CFG157_ADDR 0x008019D0
#define GPIO_CFG158_ADDR 0x008019E0
#define GSBI_BASE(id) ((id) <= 7 ? (0x16000000 + (((id)-1) << 20)) : \
(0x19800000 + (((id)-8) << 20)))
#define GSBI_UART_DM_BASE(id) (GSBI_BASE(id) + 0x40000)
#define QUP_BASE(id) (GSBI_BASE(id) + 0x80000)
#define CLK_CTL_BASE 0x00900000
#define SDC_MD(n) (CLK_CTL_BASE + 0x2828 + (32 * ((n) - 1)))
#define SDC_NS(n) (CLK_CTL_BASE + 0x282C + (32 * ((n) - 1)))
#define USB_HS1_HCLK_CTL (CLK_CTL_BASE + 0x2900)
#define USB_HS1_XCVR_FS_CLK_MD (CLK_CTL_BASE + 0x2908)
#define USB_HS1_XCVR_FS_CLK_NS (CLK_CTL_BASE + 0x290C)
#define MSM_BOOT_PLL_ENABLE_SC0 (CLK_CTL_BASE + 0x34C0)
#define MSM_BOOT_PLL8_STATUS (CLK_CTL_BASE + 0x3158)
#define GSBIn_HCLK_CTL(n) (CLK_CTL_BASE + 0x29C0 + (32 * ((n) - 1)))
#define GSBIn_HCLK_FS(n) (CLK_CTL_BASE + 0x29C4 + (32 * ((n) - 1)))
#define GSBIn_QUP_APPS_MD(n) (CLK_CTL_BASE + 0x29C8 + (32 * ((n) - 1)))
#define GSBIn_QUP_APPS_NS(n) (CLK_CTL_BASE + 0x29CC + (32 * ((n) - 1)))
#define GSBIn_UART_APPS_MD(n) (CLK_CTL_BASE + 0x29D0 + (32 * ((n) - 1)))
#define GSBIn_UART_APPS_NS(n) (CLK_CTL_BASE + 0x29D4 + (32 * ((n) - 1)))
/* Defines for the GPIO EXPANDER chip, SX1509QIULTRT */
#define GPIO_EXPANDER_REG_OPEN_DRAIN_A (0x0B)
#define GPIO_EXPANDER_REG_DIR_B (0x0E)
#define GPIO_EXPANDER_REG_DIR_A (0x0F)
#define GPIO_EXPANDER_REG_DATA_B (0x10)
#define GPIO_EXPANDER_REG_DATA_A (0x11)
#define CORE_GPIO_EXPANDER_I2C_ADDRESS (0x3E)
#define EEPROM_I2C_ADDRESS (0x52)
#define EBI2_CHIP_SELECT_CFG0 0x1A100000
#define EBI2_XMEM_CS3_CFG1 0x1A110034
#define MSM_ADM_BASE 0x18400000
#define MSM_ADM_SD_OFFSET 0x00020800
/* MMSS CLK CTR base address */
#define MSM_MMSS_CLK_CTL_BASE 0x04000000
#define MIPI_DSI_BASE (0x04700000)
#define REG_DSI(off) (MIPI_DSI_BASE + (off))
#define DSIPHY_REGULATOR_BASE (0x2CC)
#define DSIPHY_TIMING_BASE (0x260)
#define DSIPHY_CTRL_BASE (0x290)
#define DSIPHY_PLL_BASE (0x200)
#define DSIPHY_STRENGTH_BASE (0x2A0)
/* Range 0 - 4 */
#define DSIPHY_REGULATOR_CTRL(x) REG_DSI(DSIPHY_REGULATOR_BASE + (x) * 4)
/* Range 0 - 11 */
#define DSIPHY_TIMING_CTRL(x) REG_DSI(DSIPHY_TIMING_BASE + (x) * 4)
/* Range 0 - 3 */
#define DSIPHY_CTRL(x) REG_DSI(DSIPHY_CTRL_BASE + (x) * 4)
/* Range 0 - 2 */
#define DSIPHY_STRENGTH_CTRL(x) REG_DSI(DSIPHY_STRENGTH_BASE + (x) * 4)
/* Range 0 - 19 */
#define DSIPHY_PLL_CTRL(x) REG_DSI(DSIPHY_PLL_BASE + (x) * 4)
//TODO: Use mem on the stack
#define DSI_CMD_DMA_MEM_START_ADDR_PANEL (0x46000000)
#define MDP_BASE (0x05100000)
#define REG_MDP(off) (MDP_BASE + (off))
//TODO: Where does this belong?
#define MMSS_SFPB_GPREG (0x05700058)
/* HDMI base addresses */
#define MSM_HDMI_BASE 0x04A00000
#define DTV_BASE 0xD0000
#define HDMI_USEC_REFTIMER (MSM_HDMI_BASE + 0x0208)
#define HDMI_CTRL (MSM_HDMI_BASE + 0x0000)
#define HDMI_PHY_REG_0 (MSM_HDMI_BASE + 0x00000300)
#define HDMI_PHY_REG_1 (MSM_HDMI_BASE + 0x00000304)
#define HDMI_PHY_REG_2 (MSM_HDMI_BASE + 0x00000308)
#define HDMI_PHY_REG_3 (MSM_HDMI_BASE + 0x0000030c)
#define HDMI_PHY_REG_4 (MSM_HDMI_BASE + 0x00000310)
#define HDMI_PHY_REG_9 (MSM_HDMI_BASE + 0x00000324)
#define HDMI_PHY_REG_11 (MSM_HDMI_BASE + 0x0000032c)
#define HDMI_PHY_REG_12 (MSM_HDMI_BASE + 0x00000330)
#define HDMI_TOTAL (MSM_HDMI_BASE + 0x000002C0)
#define HDMI_ACTIVE_HSYNC (MSM_HDMI_BASE + 0x000002B4)
#define HDMI_ACTIVE_VSYNC (MSM_HDMI_BASE + 0x000002B8)
#define HDMI_VSYNC_TOTAL_F2 (MSM_HDMI_BASE + 0x000002C4)
#define HDMI_VSYNC_ACTIVE_F2 (MSM_HDMI_BASE + 0x000002BC)
#define HDMI_FRAME_CTRL (MSM_HDMI_BASE + 0x000002C8)
#endif
@@ -0,0 +1,56 @@
/* Copyright (c) 2009-2011, The Linux Foundation. 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 Linux Foundation 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, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __ASM_ARCH_MSM_IRQS_8x60_H
#define __ASM_ARCH_MSM_IRQS_8x60_H
/* MSM ACPU Interrupt Numbers */
#define GIC_PPI_START 16
#define GIC_SPI_START 32
#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 0)
#define USB1_HS_BAM_IRQ (GIC_SPI_START + 94)
#define USB1_HS_IRQ (GIC_SPI_START + 100)
#define USB2_IRQ (GIC_SPI_START + 141)
#define USB1_IRQ (GIC_SPI_START + 142)
#define GSBI_QUP_IRQ(id) ((id) <= 8 ? (GIC_SPI_START + 145 + 2*(id)) : \
(GIC_SPI_START + 187 + 2*((id)-8)))
/* Retrofit universal macro names */
#define INT_USB_HS USB1_HS_IRQ
#define NR_MSM_IRQS 256
#define NR_GPIO_IRQS 173
#define NR_BOARD_IRQS 0
#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS)
#endif /* __ASM_ARCH_MSM_IRQS_8x60_H */
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2011, The Linux Foundation. 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 Google, Inc. 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 OWNER 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 _PLATFORM_MSM8X60_MACHTYPE_H_
#define _PLATFORM_MSM8X60_MACHTYPE_H_
#define LINUX_MACHTYPE_8660_SURF 2755
#define LINUX_MACHTYPE_8660_FFA 3017
#define LINUX_MACHTYPE_8660_FLUID 3124
#define LINUX_MACHTYPE_8660_QT 3298
#define LINUX_MACHTYPE_8660_CHARM_SURF 3181
#define LINUX_MACHTYPE_8660_CHARM_FFA 3199
#define LINUX_MACHTYPE_8x60_DRAGON 3586
#endif
@@ -0,0 +1,209 @@
/*
* * Copyright (c) 2010-2013, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PLATFORM_MSM8X60_PMIC_H
#define __PLATFORM_MSM8X60_PMIC_H
/* PMIC 8901 LDO Module defines */
#define PM8901_LDO_BASE (0x2F)
#define PM8901_LDO_L0 (PM8901_LDO_BASE + 0x00)
#define PM8901_LDO_L0_TEST_BANK (PM8901_LDO_BASE + 0x01)
#define PM8901_LDO_L1 (PM8901_LDO_BASE + 0x02)
#define PM8901_LDO_L1_TEST_BANK (PM8901_LDO_BASE + 0x03)
#define PM8901_LDO_L2 (PM8901_LDO_BASE + 0x04)
#define PM8901_LDO_L2_TEST_BANK (PM8901_LDO_BASE + 0x05)
#define PM8901_LDO_L3 (PM8901_LDO_BASE + 0x06)
#define PM8901_LDO_L3_TEST_BANK (PM8901_LDO_BASE + 0x07)
#define PM8901_LDO_L4 (PM8901_LDO_BASE + 0x08)
#define PM8901_LDO_L4_TEST_BANK (PM8901_LDO_BASE + 0x09)
#define PM8901_LDO_L5 (PM8901_LDO_BASE + 0x0A)
#define PM8901_LDO_L5_TEST_BANK (PM8901_LDO_BASE + 0x0B)
#define PM8901_LDO_L6 (PM8901_LDO_BASE + 0x0C)
#define PM8901_LDO_L6_TEST_BANK (PM8901_LDO_BASE + 0x0D)
#define PM8901_LDO_L7 (PM8901_LDO_BASE + 0x0E)
#define PM8901_LDO_L7_TEST_BANK (PM8901_LDO_BASE + 0x0F)
enum {
LDO_START,
LDO_L0 = LDO_START,
LDO_L1,
LDO_L2,
LDO_L3,
LDO_L4,
LDO_L5,
LDO_L6,
LDO_END = LDO_L6,
};
#define PM8901_PMR_REG_BASE 0xAB
#define PM8901_PMR_REG(ldo_id) (PM8901_PMR_REG_BASE + ldo_id)
#define PM8901_LDO_TEST_BANK(n) ((n)<<4)
#define PM8901_LDO_CTL_ENABLE__S (7)
#define PM8901_LDO_CTL_PULL_DOWN__S (6)
#define PM8901_LDO_CTL_MODE__S (5)
/* LDO CTL */
#define LDO_CTL_ENABLE_MASK (0x80)
#define LDO_CTL_PULL_DOWN_MASK (0x40)
#define LDO_CTL_NORMAL_POWER_MODE_MASK (0x20)
#define LDO_CTL_VOLTAGE_SET_MASK (0x1F)
/* LDO TEST BANK 2 */
#define LDO_TEST_RANGE_SELECT_MASK (0x01)
/* LDO TEST BANK 4 */
#define LDO_TEST_OUTPUT_RANGE_MASK (0x01)
/* LDO TEST BANK 5 */
#define LDO_TEST_XO_EN_ALL_MASK (0x1F)
/* PMIC 8058 defines */
#define PM8058_LPG_CTL_BASE (0x13C)
#define PM8058_LPG_CTL(n) (PM8058_LPG_CTL_BASE + (n))
#define PM8058_LPG_BANK_SEL (0x143)
#define PM8058_LPG_BANK_ENABLE (0x144)
#define GPIO24_GPIO_CNTRL (0x167)
#define GPIO25_GPIO_CNTRL (0x168)
#define IRQ_BLOCK_SEL_USR_ADDR 0x1C0
#define IRQ_STATUS_RT_USR_ADDR 0x1C3
/* PMIC 8058 LDO module defines */
#define PM8058_LDO_CTRL_L0 (0x009)
#define PM8058_LDO_TEST_L0 (0x065)
#define PM8058_LDO_CTRL_L1 (0x00A)
#define PM8058_LDO_TEST_L1 (0x066)
#define PM8058_LDO_CTRL_L2 (0x00B)
#define PM8058_LDO_TEST_L2 (0x067)
#define PM8058_LDO_CTRL_L3 (0x00C)
#define PM8058_LDO_TEST_L3 (0x068)
#define PM8058_LDO_CTRL_L4 (0x00D)
#define PM8058_LDO_TEST_L4 (0x069)
#define PM8058_LDO_CTRL_L5 (0x00E)
#define PM8058_LDO_TEST_L5 (0x06A)
#define PM8058_LDO_CTRL_L6 (0x00F)
#define PM8058_LDO_TEST_L6 (0x06B)
#define PM8058_LDO_CTRL_L7 (0x010)
#define PM8058_LDO_TEST_L7 (0x06C)
#define PM8058_LDO_CTRL_L8 (0x011)
#define PM8058_LDO_TEST_L8 (0x06D)
#define PM8058_LDO_CTRL_L9 (0x012)
#define PM8058_LDO_TEST_L9 (0x06E)
#define PM8058_LDO_CTRL_L10 (0x013)
#define PM8058_LDO_TEST_L10 (0x06F)
#define PM8058_LDO_CTRL_L11 (0x014)
#define PM8058_LDO_TEST_L11 (0x070)
#define PM8058_LDO_CTRL_L12 (0x015)
#define PM8058_LDO_TEST_L12 (0x071)
#define PM8058_LDO_CTRL_L13 (0x016)
#define PM8058_LDO_TEST_L13 (0x072)
#define PM8058_LDO_CTRL_L14 (0x017)
#define PM8058_LDO_TEST_L14 (0x073)
#define PM8058_LDO_CTRL_L15 (0x089)
#define PM8058_LDO_TEST_L15 (0x0E5)
#define PM8058_LDO_CTRL_L16 (0x08A)
#define PM8058_LDO_TEST_L16 (0x0E6)
#define PM8058_LDO_CTRL_L17 (0x08B)
#define PM8058_LDO_TEST_L17 (0x0E7)
#define PM8058_LDO_CTRL_L18 (0x11D)
#define PM8058_LDO_TEST_L18 (0x125)
#define PM8058_LDO_CTRL_L19 (0x11E)
#define PM8058_LDO_TEST_L19 (0x126)
#define PM8058_LDO_CTRL_L20 (0x11F)
#define PM8058_LDO_TEST_L20 (0x127)
#define PM8058_LDO_CTRL_L21 (0x120)
#define PM8058_LDO_TEST_L21 (0x128)
#define PM8058_LDO_CTRL_L22 (0x121)
#define PM8058_LDO_TEST_L22 (0x129)
#define PM8058_LDO_CTRL_L23 (0x122)
#define PM8058_LDO_TEST_L23 (0x12A)
#define PM8058_LDO_CTRL_L24 (0x123)
#define PM8058_LDO_TEST_L24 (0x12B)
#define PM8058_LDO_CTRL_L25 (0x124)
#define PM8058_LDO_TEST_L25 (0x12C)
typedef enum {
PM_KYPD_PWRON_IRQ_ID = 51,
/* Block 24 Interrupts */
PM_GPIO01_CHGED_ST_IRQ_ID = 192,
PM_GPIO02_CHGED_ST_IRQ_ID = 193,
PM_GPIO03_CHGED_ST_IRQ_ID = 194,
PM_GPIO04_CHGED_ST_IRQ_ID = 195,
PM_GPIO05_CHGED_ST_IRQ_ID = 196,
PM_GPIO06_CHGED_ST_IRQ_ID = 197,
PM_GPIO07_CHGED_ST_IRQ_ID = 198,
PM_GPIO08_CHGED_ST_IRQ_ID = 199,
/* Block 25 Interrupts */
PM_GPIO09_CHGED_ST_IRQ_ID = 200,
PM_GPIO10_CHGED_ST_IRQ_ID = 201,
PM_GPIO11_CHGED_ST_IRQ_ID = 202,
PM_GPIO12_CHGED_ST_IRQ_ID = 203,
PM_GPIO13_CHGED_ST_IRQ_ID = 204,
PM_GPIO14_CHGED_ST_IRQ_ID = 205,
PM_GPIO15_CHGED_ST_IRQ_ID = 206,
PM_GPIO16_CHGED_ST_IRQ_ID = 207,
/* Block 26 Interrupts */
PM_GPIO17_CHGED_ST_IRQ_ID = 208,
PM_GPIO18_CHGED_ST_IRQ_ID = 209,
PM_GPIO19_CHGED_ST_IRQ_ID = 210,
PM_GPIO20_CHGED_ST_IRQ_ID = 211,
PM_GPIO21_CHGED_ST_IRQ_ID = 212,
PM_GPIO22_CHGED_ST_IRQ_ID = 213,
PM_GPIO23_CHGED_ST_IRQ_ID = 214,
PM_GPIO24_CHGED_ST_IRQ_ID = 215,
/* Block 27 Interrupts */
PM_GPIO25_CHGED_ST_IRQ_ID = 216,
PM_GPIO26_CHGED_ST_IRQ_ID = 217,
PM_GPIO27_CHGED_ST_IRQ_ID = 218,
PM_GPIO28_CHGED_ST_IRQ_ID = 219,
PM_GPIO29_CHGED_ST_IRQ_ID = 220,
PM_GPIO30_CHGED_ST_IRQ_ID = 221,
PM_GPIO31_CHGED_ST_IRQ_ID = 222,
PM_GPIO32_CHGED_ST_IRQ_ID = 223,
/* Block 28 Interrupts */
PM_GPIO33_CHGED_ST_IRQ_ID = 224,
PM_GPIO34_CHGED_ST_IRQ_ID = 225,
PM_GPIO35_CHGED_ST_IRQ_ID = 226,
PM_GPIO36_CHGED_ST_IRQ_ID = 227,
PM_GPIO37_CHGED_ST_IRQ_ID = 228,
PM_GPIO38_CHGED_ST_IRQ_ID = 229,
PM_GPIO39_CHGED_ST_IRQ_ID = 230,
PM_GPIO40_CHGED_ST_IRQ_ID = 231,
} pm_irq_id_type;
#endif
@@ -0,0 +1,142 @@
/*
* * Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PMIC_BATT_ALARM_H
#define __PMIC_BATT_ALARM_H
#define BIT(x) (1 << (x))
/* PM8058 Battery alarm control registers */
#define PM8058_REG_THRESHOLD 0x023
#define PM8058_REG_CTRL1 0x024
#define PM8058_REG_CTRL2 0x0AA
#define PM8058_REG_PWM_CTRL 0x0A3
/* Available voltage threshold values */
#define THRESHOLD_MIN_MV 2500
#define THRESHOLD_MAX_MV 5675
#define THRESHOLD_STEP_MV 25
/* Register bit definitions */
/* Threshold register */
#define THRESHOLD_UPPER_MASK 0xF0
#define THRESHOLD_LOWER_MASK 0x0F
#define THRESHOLD_UPPER_SHIFT 4
#define THRESHOLD_LOWER_SHIFT 0
/* CTRL 1 register */
#define CTRL1_BATT_ALARM_EN_MASK 0x80
#define CTRL1_HOLD_TIME_MASK 0x70
#define CTRL1_STATUS_UPPER_MASK 0x02
#define CTRL1_STATUS_LOWER_MASK 0x01
#define CTRL1_HOLD_TIME_SHIFT 4
#define CTRL1_HOLD_TIME_MIN 0
#define CTRL1_HOLD_TIME_MAX 7
/* CTRL 2 register */
#define CTRL2_COMP_UPPER_DISABLE_MASK 0x80
#define CTRL2_COMP_LOWER_DISABLE_MASK 0x40
#define CTRL2_FINE_STEP_UPPER_MASK 0x30
#define CTRL2_RANGE_EXT_UPPER_MASK 0x08
#define CTRL2_FINE_STEP_LOWER_MASK 0x06
#define CTRL2_RANGE_EXT_LOWER_MASK 0x01
#define CTRL2_FINE_STEP_UPPER_SHIFT 4
#define CTRL2_FINE_STEP_LOWER_SHIFT 1
/* PWM control register */
#define PWM_CTRL_ALARM_EN_MASK 0xC0
#define PWM_CTRL_ALARM_EN_NEVER 0x00
#define PWM_CTRL_ALARM_EN_TCXO 0x40
#define PWM_CTRL_ALARM_EN_PWM 0x80
#define PWM_CTRL_ALARM_EN_ALWAYS 0xC0
#define PWM_CTRL_PRE_MASK 0x38
#define PWM_CTRL_DIV_MASK 0x07
#define PWM_CTRL_PRE_SHIFT 3
#define PWM_CTRL_DIV_SHIFT 0
#define PWM_CTRL_PRE_MIN 0
#define PWM_CTRL_PRE_MAX 7
#define PWM_CTRL_DIV_MIN 1
#define PWM_CTRL_DIV_MAX 7
/* PWM control input range */
#define PWM_CTRL_PRE_INPUT_MIN 2
#define PWM_CTRL_PRE_INPUT_MAX 9
#define PWM_CTRL_DIV_INPUT_MIN 2
#define PWM_CTRL_DIV_INPUT_MAX 8
/* Available voltage threshold values */
#define THRESHOLD_BASIC_MIN_MV 2800
#define THRESHOLD_EXT_MIN_MV 4400
#define DEFAULT_THRESHOLD_LOWER 3200
#define DEFAULT_THRESHOLD_UPPER 4300
#define DEFAULT_HOLD_TIME HOLD_TIME_16_MS
#define DISABLE_USE_PWM 0
#define ENABLE_USE_PWM 1
#define DEFAULT_PWM_SCALER 9
#define DEFAULT_PWM_DIVIDER 8
#define LOWER_COMP_DISABLE 0
#define UPPER_COMP_DISABLE 0
#define LOWER_COMP_ENABLE 1
#define UPPER_COMP_ENABLE 1
#define PM_BATT_ALARM_STATUS_BELOW_LOWER BIT(0)
#define PM_BATT_ALARM_STATUS_ABOVE_UPPER BIT(1)
typedef enum {
HOLD_TIME_0p125_MS = 0,
HOLD_TIME_0p25_MS,
HOLD_TIME_0p5_MS,
HOLD_TIME_1_MS,
HOLD_TIME_2_MS,
HOLD_TIME_4_MS,
HOLD_TIME_8_MS,
HOLD_TIME_16_MS,
} pm_batt_alarm_hold_time;
typedef enum {
ALARM_EN_NEVER = 0,
ALARM_EN_PWM,
ALARM_EN_ALWAYS,
} pm_batt_alarm_pwm_ctrl;
struct pm_batt_alarm_device {
uint8_t reg_threshold;
uint8_t reg_ctrl1;
uint8_t reg_ctrl2;
uint8_t reg_pwm_ctrl;
};
extern int pm8058_mwrite(uint16_t addr, uint8_t val, uint8_t mask,
uint8_t * reg_save);
extern int pm8058_read(uint16_t addr, uint8_t * data, uint16_t length);
extern void mdelay(uint32_t ms);
#endif
@@ -0,0 +1,152 @@
/*
* * Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PMIC_PWM_H
#define __PMIC_PWM_H
#define USEC_PER_SEC 1000000L
#define NSEC_PER_SEC 1000000000L
#define NSEC_PER_USEC 1000
#define PWM_FREQ_HZ 300
#define PWM_LEVEL 15
#define NUM_CLOCKS 3
#define NUM_PRE_DIVIDE 3
#define NUM_LPG_CTL_REGS 7
#define PRE_DIVIDE_0 2
#define PRE_DIVIDE_1 3
#define PRE_DIVIDE_2 5
#define PRE_DIVIDE_MIN PRE_DIVIDE_0
#define PRE_DIVIDE_MAX PRE_DIVIDE_2
#define PM_PWM_M_MIN 0
#define PM_PWM_M_MAX 7
#define NSEC_1000HZ (NSEC_PER_SEC / 1000)
#define NSEC_32768HZ (NSEC_PER_SEC / 32768)
#define NSEC_19P2MHZ (NSEC_PER_SEC / 19200000)
#define CLK_PERIOD_MIN NSEC_19P2MHZ
#define CLK_PERIOD_MAX NSEC_1000HZ
#define MIN_MPT ((PRE_DIVIDE_MIN * CLK_PERIOD_MIN) << PM_PWM_M_MIN)
#define MAX_MPT ((PRE_DIVIDE_MAX * CLK_PERIOD_MAX) << PM_PWM_M_MAX)
/* The MAX value is computation limit. Hardware limit is 393 seconds. */
#define PM_PWM_PERIOD_MAX (274 * USEC_PER_SEC)
/* The MIN value is hardware limit. */
#define PM_PWM_PERIOD_MIN 7 /* micro seconds */
#define PWM_PERIOD_USEC (USEC_PER_SEC / PWM_FREQ_HZ)
#define PWM_DUTY_LEVEL (PWM_PERIOD_USEC / PWM_LEVEL)
/* Control 0 */
#define PM_PWM_1KHZ_COUNT_MASK 0xF0
#define PM_PWM_1KHZ_COUNT_SHIFT 4
#define PM_PWM_1KHZ_COUNT_MAX 15
#define PM_PWM_OUTPUT_EN 0x08
#define PM_PWM_PWM_EN 0x04
#define PM_PWM_RAMP_GEN_EN 0x02
#define PM_PWM_RAMP_START 0x01
#define PM_PWM_PWM_START (PM_PWM_OUTPUT_EN \
| PM_PWM_PWM_EN)
#define PM_PWM_RAMP_GEN_START (PM_PWM_RAMP_GEN_EN \
| PM_PWM_RAMP_START)
/* Control 1 */
#define PM_PWM_REVERSE_EN 0x80
#define PM_PWM_BYPASS_LUT 0x40
#define PM_PWM_HIGH_INDEX_MASK 0x3F
/* Control 2 */
#define PM_PWM_LOOP_EN 0x80
#define PM_PWM_RAMP_UP 0x40
#define PM_PWM_LOW_INDEX_MASK 0x3F
/* Control 3 */
#define PM_PWM_VALUE_BIT7_0 0xFF
#define PM_PWM_VALUE_BIT5_0 0x3F
/* Control 4 */
#define PM_PWM_VALUE_BIT8 0x80
#define PM_PWM_CLK_SEL_MASK 0x60
#define PM_PWM_CLK_SEL_SHIFT 5
#define PM_PWM_CLK_SEL_NO 0
#define PM_PWM_CLK_SEL_1KHZ 1
#define PM_PWM_CLK_SEL_32KHZ 2
#define PM_PWM_CLK_SEL_19P2MHZ 3
#define PM_PWM_PREDIVIDE_MASK 0x18
#define PM_PWM_PREDIVIDE_SHIFT 3
#define PM_PWM_PREDIVIDE_2 0
#define PM_PWM_PREDIVIDE_3 1
#define PM_PWM_PREDIVIDE_5 2
#define PM_PWM_PREDIVIDE_6 3
#define PM_PWM_M_MASK 0x07
#define PM_PWM_M_MIN 0
#define PM_PWM_M_MAX 7
/* Control 5 */
#define PM_PWM_PAUSE_COUNT_HI_MASK 0xFC
#define PM_PWM_PAUSE_COUNT_HI_SHIFT 2
#define PM_PWM_PAUSE_ENABLE_HIGH 0x02
#define PM_PWM_SIZE_9_BIT 0x01
/* Control 6 */
#define PM_PWM_PAUSE_COUNT_LO_MASK 0xFC
#define PM_PWM_PAUSE_COUNT_LO_SHIFT 2
#define PM_PWM_PAUSE_ENABLE_LOW 0x02
#define PM_PWM_RESERVED 0x01
#define PM_PWM_PAUSE_COUNT_MAX 56 /* < 2^6 = 64 */
struct pm_pwm_config {
int pwm_size; /* round up to 6 or 9 for 6/9-bit PWM SIZE */
int clk;
int pre_div;
int pre_div_exp;
int pwm_value;
int bypass_lut;
uint8_t pwm_ctl[NUM_LPG_CTL_REGS];
};
#endif
@@ -0,0 +1,37 @@
/*
* * Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 __PLATFORM_MSM8X60_SCM_IO_H
#define __PLATFORM_MSM8X60_SCM_IO_H
#include <sys/types.h>
uint32_t secure_readl(uint32_t);
void secure_writel(uint32_t, uint32_t);
#endif
@@ -0,0 +1,422 @@
/*
* * Copyright (c) 2010-2013, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <debug.h>
#include <kernel/thread.h>
#include <i2c_qup.h>
#include <platform.h>
#include <platform/iomap.h>
#include <platform/gpio.h>
#include <platform/clock.h>
#include <platform/pmic.h>
#include <platform/pmic_pwm.h>
#include <platform/machtype.h>
#include <platform/timer.h>
#include <gsbi.h>
#include <dev/lcdc.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static struct qup_i2c_dev *dev = NULL;
void gpio_tlmm_config(uint32_t gpio, uint8_t func,
uint8_t dir, uint8_t pull,
uint8_t drvstr, uint32_t enable);
uint8_t expander_read(uint8_t addr)
{
uint8_t ret = 0;
/* Create a i2c_msg buffer, that is used to put the controller into read
mode and then to read some data. */
struct i2c_msg msg_buf[] = {
{CORE_GPIO_EXPANDER_I2C_ADDRESS, I2C_M_WR, 1, &addr},
{CORE_GPIO_EXPANDER_I2C_ADDRESS, I2C_M_RD, 1, &ret}
};
qup_i2c_xfer(dev, msg_buf, 2);
return ret;
}
uint8_t expander_write(uint8_t addr, uint8_t val)
{
uint8_t data_buf[] = { addr, val };
/* Create a i2c_msg buffer, that is used to put the controller into write
mode and then to write some data. */
struct i2c_msg msg_buf[] = { {CORE_GPIO_EXPANDER_I2C_ADDRESS,
I2C_M_WR, 2, data_buf}
};
qup_i2c_xfer(dev, msg_buf, 1);
/* Double check that the write worked. */
if (val != expander_read(addr)) {
return -1;
}
return 0;
}
void panel_backlight(int on)
{
}
static int display_common_power(int on)
{
}
static int lcd_power_on()
{
uint8_t buffer = 0x0, mask = 0x0, prev_val = 0x0;
int ret = 0;
/* Configure LDO L2 TEST Bank 2, to Range Select 0 */
/* Not updating reference voltage */
buffer = (0x80); /* Write mode */
buffer |= (PM8901_LDO_TEST_BANK(2)); /* Test Bank 2 */
mask = buffer | LDO_TEST_RANGE_SELECT_MASK;
if ((ret = pm8901_test_bank_read(&prev_val,
PM8901_LDO_TEST_BANK(2),
PM8901_LDO_L2_TEST_BANK))) {
return ret;
}
if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
prev_val))) {
return ret;
}
/* Enable LDO L2 at Max Voltage (should be around 3.3v) */
buffer = (0x0 << PM8901_LDO_CTL_ENABLE__S);
/* Disable Pull Down */
buffer |= (0x1 << PM8901_LDO_CTL_PULL_DOWN__S);
/* Put LDO into normal mode instead of low power mode */
buffer |= (0x0 << PM8901_LDO_CTL_MODE__S);
/* Set voltage programming to 3.3V or 2.85V(8660 fluid) */
if (board_machtype() == LINUX_MACHTYPE_8660_FLUID)
buffer |= (0xB);
else
buffer |= (0xF);
mask = buffer | LDO_CTL_ENABLE_MASK |
LDO_CTL_PULL_DOWN_MASK |
LDO_CTL_NORMAL_POWER_MODE_MASK | LDO_CTL_VOLTAGE_SET_MASK;
/* Do a normal read here, as to not destroy the value in LDO control */
if ((ret = pm8901_read(&prev_val, 1, PM8901_LDO_L2))) {
return ret;
}
/* Configure the LDO2 for 3.3V or 2.85V(8660 fluid) */
ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2, prev_val);
/* Configure LDO L2 TEST Bank 4, for High Range Mode */
buffer = (0x80); /* Write mode */
buffer |= (PM8901_LDO_TEST_BANK(4)); /* Test Bank 4 */
buffer |= (0x01); /* Put into High Range Mode */
mask = buffer | LDO_TEST_OUTPUT_RANGE_MASK;
if ((ret = pm8901_test_bank_read(&prev_val,
PM8901_LDO_TEST_BANK(4),
PM8901_LDO_L2_TEST_BANK))) {
return ret;
}
if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
prev_val))) {
return ret;
}
/* Configure LDO L2 TEST Bank 2, to Range Select 0 */
buffer = (0x80); /* Write mode */
buffer |= (PM8901_LDO_TEST_BANK(2)); /* Test Bank 2 */
buffer |= (1 << 1); /* For fine step 50 mV */
buffer |= (1 << 3); /* to update reference voltage */
mask = buffer | LDO_TEST_RANGE_SELECT_MASK;
mask |= (1 << 2); /* Setting mask to make ref voltage as 1.25 V */
if ((ret = pm8901_test_bank_read(&prev_val,
PM8901_LDO_TEST_BANK(2),
PM8901_LDO_L2_TEST_BANK))) {
return ret;
}
if ((ret = pm8901_vreg_write(&buffer, mask, PM8901_LDO_L2_TEST_BANK,
prev_val))) {
return ret;
}
/* Enable PMR for LDO L2 */
buffer = 0x7F;
mask = 0x7F;
if ((ret = pm8901_read(&prev_val, 1, PM8901_PMR_REG(LDO_L2)))) {
return ret;
}
ret = pm8901_vreg_write(&buffer, mask, PM8901_PMR_REG(LDO_L2), prev_val);
return ret;
}
/* Configures the GPIO that are needed to enable LCD.
* This function also configures the PMIC for PWM control of the LCD backlight.
*/
static void lcd_gpio_cfg(uint8_t on)
{
uint32_t func;
uint32_t pull;
uint32_t dir;
uint32_t enable = 0; /* not used in gpio_tlmm_config */
uint32_t drv;
if (on) {
func = 1; /* Configure GPIO for LCDC function */
pull = GPIO_NO_PULL;
dir = 1; /* doesn't matter since it is not configured as
GPIO */
drv = GPIO_16MA;
} else {
/* As discussed in the MSM8660 FFA HW SW Control Doc configure these
GPIO as input and pull down. */
func = 0; /* GPIO */
pull = GPIO_PULL_DOWN;
dir = 0; /* Input */
drv = 0; /* does not matter configured as input */
}
gpio_tlmm_config(0, func, dir, pull, drv, enable); /* lcdc_pclk */
gpio_tlmm_config(1, func, dir, pull, drv, enable); /* lcdc_hsync */
gpio_tlmm_config(2, func, dir, pull, drv, enable); /* lcdc_vsync */
gpio_tlmm_config(3, func, dir, pull, drv, enable); /* lcdc_den */
gpio_tlmm_config(4, func, dir, pull, drv, enable); /* lcdc_red7 */
gpio_tlmm_config(5, func, dir, pull, drv, enable); /* lcdc_red6 */
gpio_tlmm_config(6, func, dir, pull, drv, enable); /* lcdc_red5 */
gpio_tlmm_config(7, func, dir, pull, drv, enable); /* lcdc_red4 */
gpio_tlmm_config(8, func, dir, pull, drv, enable); /* lcdc_red3 */
gpio_tlmm_config(9, func, dir, pull, drv, enable); /* lcdc_red2 */
gpio_tlmm_config(10, func, dir, pull, drv, enable); /* lcdc_red1 */
gpio_tlmm_config(11, func, dir, pull, drv, enable); /* lcdc_red0 */
gpio_tlmm_config(12, func, dir, pull, drv, enable); /* lcdc_rgn7 */
gpio_tlmm_config(13, func, dir, pull, drv, enable); /* lcdc_rgn6 */
gpio_tlmm_config(14, func, dir, pull, drv, enable); /* lcdc_rgn5 */
gpio_tlmm_config(15, func, dir, pull, drv, enable); /* lcdc_rgn4 */
gpio_tlmm_config(16, func, dir, pull, drv, enable); /* lcdc_rgn3 */
gpio_tlmm_config(17, func, dir, pull, drv, enable); /* lcdc_rgn2 */
gpio_tlmm_config(18, func, dir, pull, drv, enable); /* lcdc_rgn1 */
gpio_tlmm_config(19, func, dir, pull, drv, enable); /* lcdc_rgn0 */
gpio_tlmm_config(20, func, dir, pull, drv, enable); /* lcdc_blu7 */
gpio_tlmm_config(21, func, dir, pull, drv, enable); /* lcdc_blu6 */
gpio_tlmm_config(22, func, dir, pull, drv, enable); /* lcdc_blu5 */
gpio_tlmm_config(23, func, dir, pull, drv, enable); /* lcdc_blu4 */
gpio_tlmm_config(24, func, dir, pull, drv, enable); /* lcdc_blu3 */
gpio_tlmm_config(25, func, dir, pull, drv, enable); /* lcdc_blu2 */
gpio_tlmm_config(26, func, dir, pull, drv, enable); /* lcdc_blu1 */
gpio_tlmm_config(27, func, dir, pull, drv, enable); /* lcdc_blu0 */
}
/* API to set backlight level configuring PWM in PM8058 */
int panel_set_backlight(uint8_t bt_level)
{
int rc = -1;
uint32_t duty_us, period_us;
if ((bt_level < 0) || (bt_level > 15)) {
dprintf(CRITICAL, "Error in brightness level (1-15 allowed)\n");
goto bail_out;
}
duty_us = bt_level * PWM_DUTY_LEVEL;
period_us = PWM_PERIOD_USEC;
rc = pm_pwm_config(0, duty_us, period_us);
if (rc) {
dprintf(CRITICAL, "Error in pwm_config0\n");
goto bail_out;
}
duty_us = PWM_PERIOD_USEC - (bt_level * PWM_DUTY_LEVEL);
period_us = PWM_PERIOD_USEC;
rc = pm_pwm_config(1, duty_us, period_us);
if (rc) {
dprintf(CRITICAL, "Error in pwm_config1\n");
goto bail_out;
}
rc = pm_pwm_enable(0);
if (rc) {
dprintf(CRITICAL, "Error in pwm_enable0\n");
goto bail_out;
}
rc = pm_pwm_enable(1);
if (rc)
dprintf(CRITICAL, "Error in pwm_enable1\n");
bail_out:
return rc;
}
void bl_gpio_init(void)
{
/* Configure PM8058 GPIO24 as a PWM driver (LPG ch0) for chain 1 of 6 LEDs */
pm8058_write_one(0x81, GPIO24_GPIO_CNTRL); /* Write, Bank0, VIN0, Mode
selection enabled */
pm8058_write_one(0x98, GPIO24_GPIO_CNTRL); /* Write, Bank1, OutOn/InOff,
CMOS, Don't Invert Output */
pm8058_write_one(0xAA, GPIO24_GPIO_CNTRL); /* Write, Bank2, GPIO no pull */
pm8058_write_one(0xB4, GPIO24_GPIO_CNTRL); /* Write, Bank3, high drv
strength */
pm8058_write_one(0xC6, GPIO24_GPIO_CNTRL); /* Write, Bank4, Src: LPG_DRV1
(Spec. Fnc 2) */
pm8058_write_one(0xD8, GPIO24_GPIO_CNTRL); /* Write, Bank5, Interrupt
polarity noninversion */
/* Configure PM8058 GPIO25 as a PWM driver (LPG ch1) for chain 2 of 5 LEDs */
pm8058_write_one(0x81, GPIO25_GPIO_CNTRL); /* Write, Bank0, VIN0, Mode
selection enabled */
pm8058_write_one(0x98, GPIO25_GPIO_CNTRL); /* Write, Bank1, OutOn/InOff,
CMOS, Don't Invert Output */
pm8058_write_one(0xAA, GPIO25_GPIO_CNTRL); /* Write, Bank2, GPIO no pull */
pm8058_write_one(0xB4, GPIO25_GPIO_CNTRL); /* Write, Bank3, high drv
strength */
pm8058_write_one(0xC6, GPIO25_GPIO_CNTRL); /* Write, Bank4, Src: LPG_DRV2
(Spec. Fnc 2) */
pm8058_write_one(0xD8, GPIO25_GPIO_CNTRL); /* Write, Bank5, Interrupt
polarity noninversion */
}
void board_lcd_enable(void)
{
int rc = -1;
dev = qup_i2c_init(GSBI_ID_8, 100000, 24000000);
/* Make sure dev is created and initialized properly */
if (!dev) {
while (1) ;
return;
}
/* Store current value of these registers as to not destroy their previous
state. */
uint8_t open_drain_a = expander_read(GPIO_EXPANDER_REG_OPEN_DRAIN_A);
uint8_t dir_b = expander_read(GPIO_EXPANDER_REG_DIR_B);
uint8_t dir_a = expander_read(GPIO_EXPANDER_REG_DIR_A);
uint8_t data_b = expander_read(GPIO_EXPANDER_REG_DATA_B);
uint8_t data_a = expander_read(GPIO_EXPANDER_REG_DATA_A);
/* Set the LVDS_SHUTDOWN_N to open drain and output low. */
dprintf(INFO, "Enable lvds_shutdown_n line for Open Drain.\n");
expander_write(GPIO_EXPANDER_REG_OPEN_DRAIN_A, 0x04 | open_drain_a);
dprintf(INFO, "Enable lvds_shutdown_n line for output.\n");
expander_write(GPIO_EXPANDER_REG_DIR_A, ~0x04 & dir_a);
dprintf(INFO, "Drive the LVDS_SHUTDOWN_N pin high here.\n");
expander_write(GPIO_EXPANDER_REG_DATA_A, 0x04 | data_a);
/* Turn on the VREG_L2B to 3.3V. */
/* Power on the appropiate PMIC LDO power rails */
if (lcd_power_on())
return;
/* Enable the GPIO as LCDC mode LCD. */
lcd_gpio_cfg(1);
/* Arbitrary delay */
udelay(20000);
/* Set the GPIOs needed for backlight */
bl_gpio_init();
/* Set backlight level with API (to 8 by default) */
rc = panel_set_backlight(8);
if (rc)
dprintf(CRITICAL, "Error in setting panel backlight\n");
dprintf(INFO, "Enable BACKLIGHT_EN line for output.\n");
expander_write(GPIO_EXPANDER_REG_DIR_B, ~0x10 & dir_b);
dprintf(INFO, "Drive BACKLIGHT_EN to high\n");
expander_write(GPIO_EXPANDER_REG_DATA_B, 0x10 | data_b);
}
void lcdc_on(void)
{
board_lcd_enable();
}
void auo_board_lcd_enable(void)
{
/* Make sure dev is created and initialized properly */
dev = qup_i2c_init(GSBI_ID_8, 100000, 24000000);
if (!dev) {
dprintf(CRITICAL, "Error in qup_i2c_init\n");
while (1) ;
}
/* Setup RESX_N */
uint8_t open_drain_a = expander_read(GPIO_EXPANDER_REG_OPEN_DRAIN_A);
uint8_t dir_a = expander_read(GPIO_EXPANDER_REG_DIR_A);
uint8_t data_a = expander_read(GPIO_EXPANDER_REG_DATA_A);
expander_write(GPIO_EXPANDER_REG_DIR_A, ~0x04 & dir_a);
expander_write(GPIO_EXPANDER_REG_DATA_A, ~0x04 & data_a);
/* Power on the appropiate PMIC LDO power rails */
if (lcd_power_on())
return;
/* Toggle RESX_N */
mdelay(20);
expander_write(GPIO_EXPANDER_REG_DATA_A, 0x04 | data_a);
mdelay(1);
expander_write(GPIO_EXPANDER_REG_DATA_A, ~0x04 & data_a);
mdelay(1);
expander_write(GPIO_EXPANDER_REG_DATA_A, 0x04 | data_a);
mdelay(25);
/* Enable the gpios for LCD */
lcd_gpio_cfg(1);
auo_lcdc_init();
}
void panel_poweron(void)
{
if (board_machtype() == LINUX_MACHTYPE_8660_FLUID) {
auo_board_lcd_enable();
} else {
panel_backlight(1);
lcdc_on();
}
}
struct lcdc_timing_parameters *get_lcd_timing(void)
{
if (board_machtype() == LINUX_MACHTYPE_8660_FLUID)
return auo_timing_param();
else
return DEFAULT_LCD_TIMING;
}
@@ -0,0 +1,184 @@
/*
* Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 OWNER 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 <debug.h>
#include <dev/gpio.h>
#include <kernel/thread.h>
#include <platform/gpio.h>
#include <dev/lcdc.h>
#define GPIO_SET_OUT_VAL(gpio,val) (gpio_set(gpio,(val)<<1))
#define LCDC_SPI_GPIO_CLK 73
#define LCDC_SPI_GPIO_CS 72
#define LCDC_SPI_GPIO_MOSI 70
/* panel cmd addresses */
#define PANEL_CMD_SLEEP_OUT 0x1100
#define PANEL_CMD_RGBCTRL 0x3B00
#define PANEL_CMD_DISP_ON 0x2900
#define PANEL_CMD_BCTRL 0x5300
#define PANEL_CMD_PWM_EN 0x6A17
#define PANEL_CMD_FORMAT 0x3A00
#define PANEL_CMD_CABC_FORCE2 0x6A18 /* backlight level */
/* timing info */
static struct lcdc_timing_parameters param = {
.lcdc_fb_width = 480,
.lcdc_fb_height = 800,
.lcdc_hsync_pulse_width_dclk = 2,
.lcdc_hsync_back_porch_dclk = 14,
.lcdc_hsync_front_porch_dclk = 16,
.lcdc_hsync_skew_dclk = 0,
.lcdc_vsync_pulse_width_lines = 2,
.lcdc_vsync_back_porch_lines = 1,
.lcdc_vsync_front_porch_lines = 28,
};
struct lcdc_timing_parameters *auo_timing_param()
{
return &param;
}
/* spi commands */
static void auo_spi_write_byte(uint32_t data)
{
uint32_t bit;
uint32_t bnum;
bnum = 8;
bit = 0x80;
while (bnum--) {
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_CLK, 0);
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_MOSI, (data & bit) ? 1 : 0);
udelay(1);
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_CLK, 1);
udelay(1);
bit >>= 1;
}
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_MOSI, 0);
}
static uint32_t auo_serigo(uint32_t * input_data, uint32_t input_len)
{
uint32_t i;
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_CS, 0);
udelay(2);
for (i = 0; i < input_len; ++i) {
auo_spi_write_byte(input_data[i]);
udelay(2);
}
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_CS, 1);
return 0;
}
static void auo_write_cmd(uint32_t cmd)
{
uint32_t local_data[4];
local_data[0] = 0x20;
local_data[1] = (uint32_t) (cmd >> 8);
local_data[2] = 0;
local_data[3] = (uint32_t) cmd;
auo_serigo(local_data, 4);
}
static void auo_write_cmd_param(uint32_t cmd, uint32_t param)
{
uint32_t local_data[6];
local_data[0] = 0x20;
local_data[1] = (uint32_t) (cmd >> 8);
local_data[2] = 0;
local_data[3] = (uint32_t) cmd;
local_data[4] = 0x40;
local_data[5] = param;
auo_serigo(local_data, 6);
}
static void auo_spi_init(void)
{
gpio_tlmm_config(LCDC_SPI_GPIO_CLK, 0, GPIO_OUTPUT, GPIO_NO_PULL,
GPIO_2MA, 1);
gpio_tlmm_config(LCDC_SPI_GPIO_CS, 0, GPIO_OUTPUT, GPIO_NO_PULL,
GPIO_2MA, 1);
gpio_tlmm_config(LCDC_SPI_GPIO_MOSI, 0, GPIO_OUTPUT, GPIO_NO_PULL,
GPIO_2MA, 1);
/* Set the output so that we don't disturb the slave device */
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_CLK, 1);
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_MOSI, 0);
/* Set the Chip Select deasserted (active low) */
GPIO_SET_OUT_VAL(LCDC_SPI_GPIO_CS, 1);
}
/* panel initialization */
static void auo_panel_init(void)
{
auo_write_cmd(PANEL_CMD_SLEEP_OUT);
mdelay(150);
/* SET_PIXEL_FORMAT: Set how many bits per pixel are used (3A00h), 18bits */
auo_write_cmd_param(PANEL_CMD_FORMAT, 0x66);
mdelay(1);
/* RGBCTRL: RGB Interface Signal Control (3B00h) */
auo_write_cmd_param(PANEL_CMD_RGBCTRL, 0x2B);
mdelay(1);
/* Turn on display */
auo_write_cmd(PANEL_CMD_DISP_ON);
mdelay(1);
/* Turn on backlight */
auo_write_cmd_param(PANEL_CMD_BCTRL, 0x24);
mdelay(1);
/* Enable PWM level */
auo_write_cmd_param(PANEL_CMD_PWM_EN, 0x01);
mdelay(1);
/* Set backlight level to mid range level */
auo_write_cmd_param(PANEL_CMD_CABC_FORCE2, 0x77);
mdelay(10);
}
void auo_lcdc_init(void)
{
auo_spi_init();
auo_panel_init();
}
@@ -0,0 +1,279 @@
/*
* Copyright (c) 2008, Google Inc.
* All rights reserved.
* Copyright (c) 2009-2013, The Linux Foundation. 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 Google, Inc. 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 OWNER 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 <debug.h>
#include <reg.h>
#include <dev/fbcon.h>
#include <kernel/thread.h>
#include <platform/debug.h>
#include <platform/iomap.h>
#include <platform/clock.h>
#include <platform/machtype.h>
#include <platform/pmic.h>
#include <qgic.h>
#include <i2c_qup.h>
#include <gsbi.h>
#include <uart_dm.h>
#include <mmu.h>
#include <arch/arm/mmu.h>
#include <dev/lcdc.h>
static uint32_t ticks_per_sec = 0;
#define MB (1024*1024)
/* LK memory - cacheable, write through */
#define LK_MEMORY (MMU_MEMORY_TYPE_STRONGLY_ORDERED | \
MMU_MEMORY_AP_READ_WRITE)
/* Kernel region - cacheable, write through */
#define KERNEL_MEMORY (MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH | \
MMU_MEMORY_AP_READ_WRITE)
/* Scratch region - cacheable, write through */
#define SCRATCH_MEMORY (MMU_MEMORY_TYPE_NORMAL_WRITE_THROUGH | \
MMU_MEMORY_AP_READ_WRITE)
/* Peripherals - non-shared device */
#define IOMAP_MEMORY (MMU_MEMORY_TYPE_DEVICE_NON_SHARED | \
MMU_MEMORY_AP_READ_WRITE)
#define MSM_IOMAP_SIZE ((MSM_IOMAP_END - MSM_IOMAP_BASE)/MB)
mmu_section_t mmu_section_table[] = {
/* Physical addr, Virtual addr, Size (in MB), Flags */
{MEMBASE, MEMBASE, (MEMSIZE / MB), LK_MEMORY},
{BASE_ADDR, BASE_ADDR, 44, KERNEL_MEMORY},
{SCRATCH_ADDR, SCRATCH_ADDR, 128, SCRATCH_MEMORY},
{MSM_IOMAP_BASE, MSM_IOMAP_BASE, MSM_IOMAP_SIZE, IOMAP_MEMORY},
};
#define CONVERT_ENDIAN_U32(val) \
((((uint32_t)(val) & 0x000000FF) << 24) | \
(((uint32_t)(val) & 0x0000FF00) << 8) | \
(((uint32_t)(val) & 0x00FF0000) >> 8) | \
(((uint32_t)(val) & 0xFF000000) >> 24))
#define CONVERT_ENDIAN_U16(val) \
((((uint16_t)(val) & 0x00FF) << 8) | \
(((uint16_t)(val) & 0xFF00) >> 8))
/* Configuration Data Table */
#define CDT_MAGIC_NUMBER 0x43445400
struct cdt_header {
uint32_t magic; /* Magic number */
uint16_t version; /* Version number */
uint32_t reserved1;
uint32_t reserved2;
} __attribute__ ((packed));
void platform_init_timer();
struct fbcon_config *lcdc_init(void);
/* CRCI - mmc slot mapping.
* mmc slot numbering start from 1.
* entry at index 0 is just dummy.
*/
uint8_t sdc_crci_map[5] = { 0, 1, 4, 2, 5 };
void platform_early_init(void)
{
uint8_t gsbi_id = target_uart_gsbi();
uart_dm_init(gsbi_id, GSBI_BASE(gsbi_id), GSBI_UART_DM_BASE(gsbi_id));
qgic_init();
platform_init_timer();
}
void platform_init(void)
{
dprintf(INFO, "platform_init()\n");
}
void display_init(void)
{
struct fbcon_config *fb_cfg;
#if DISPLAY_TYPE_LCDC
struct lcdc_timing_parameters *lcd_timing;
mdp_clock_init();
if (board_machtype() == LINUX_MACHTYPE_8660_FLUID) {
mmss_pixel_clock_configure(PIXEL_CLK_INDEX_25M);
} else {
mmss_pixel_clock_configure(PIXEL_CLK_INDEX_54M);
}
lcd_timing = get_lcd_timing();
fb_cfg = lcdc_init_set(lcd_timing);
fbcon_setup(fb_cfg);
fbcon_clear();
panel_poweron();
#endif
#if DISPLAY_TYPE_MIPI
mdp_clock_init();
configure_dsicore_dsiclk();
configure_dsicore_byteclk();
configure_dsicore_pclk();
fb_cfg = mipi_init();
fbcon_setup(fb_cfg);
#endif
#if DISPLAY_TYPE_HDMI
struct hdmi_disp_mode_timing_type *hdmi_timing;
mdp_clock_init();
hdmi_power_init();
fb_cfg = get_fbcon();
hdmi_set_fb_addr(fb_cfg.base);
fbcon_setup(fb_cfg);
hdmi_dtv_init();
hdmi_dtv_on();
hdmi_msm_turn_on();
#endif
}
void display_shutdown(void)
{
#if DISPLAY_TYPE_LCDC
unsigned rc = 0;
/* Turning off LCDC */
rc = panel_set_backlight(0);
if (rc)
dprintf(CRITICAL, "Error in setting panel backlight\n");
lcdc_shutdown();
pm8901_ldo_disable(LDO_L2);
#endif
#if DISPLAY_TYPE_MIPI
mipi_dsi_shutdown();
#endif
#if DISPLAY_TYPE_HDMI
hdmi_display_shutdown();
#endif
}
static struct qup_i2c_dev *dev = NULL;
uint32_t eprom_read(uint16_t addr, uint8_t count)
{
uint32_t ret = 0;
if (!dev) {
return ret;
}
/* Create a i2c_msg buffer, that is used to put the controller into
* read mode and then to read some data.
*/
struct i2c_msg msg_buf[] = {
{EEPROM_I2C_ADDRESS, I2C_M_WR, 2, &addr},
{EEPROM_I2C_ADDRESS, I2C_M_RD, count, &ret}
};
qup_i2c_xfer(dev, msg_buf, 2);
return ret;
}
/* Read EEPROM to find out product id. Return 0 in case of failure */
uint32_t platform_id_read(void)
{
uint32_t id = 0;
uint16_t offset = 0;
dev = qup_i2c_init(GSBI_ID_8, 100000, 24000000);
if (!dev) {
return id;
}
/* Check if EPROM is valid */
if (CONVERT_ENDIAN_U32(eprom_read(0, 4)) == CDT_MAGIC_NUMBER) {
/* Get offset for platform ID info from Meta Data block 0 */
offset = eprom_read(CONVERT_ENDIAN_U16(0 +
sizeof(struct
cdt_header)), 2);
/* Read platform ID */
id = eprom_read(CONVERT_ENDIAN_U16(offset), 4);
id = CONVERT_ENDIAN_U32(id);
id = (id & 0x00FF0000) >> 16;
}
return id;
}
/* Setup memory for this platform */
void platform_init_mmu_mappings(void)
{
uint32_t i;
uint32_t sections;
uint32_t table_size = ARRAY_SIZE(mmu_section_table);
for (i = 0; i < table_size; i++) {
sections = mmu_section_table[i].num_of_sections;
while (sections--) {
arm_mmu_map_section(mmu_section_table[i].paddress +
sections * MB,
mmu_section_table[i].vaddress +
sections * MB,
mmu_section_table[i].flags);
}
}
}
/* Do any platform specific cleanup just before kernel entry */
void platform_uninit(void)
{
/* As a effect of enabling caches, display gets shutdown even before
* the splash screen shows up. Until we can speed up the splash screen
* display, add an artificial delay so that current user experience
* is not affected.
*/
mdelay(400);
#if DISPLAY_SPLASH_SCREEN
display_shutdown();
#endif
platform_uninit_timer();
}
/* Initialize DGT timer */
void platform_init_timer(void)
{
/* disable timer */
writel(0, DGT_ENABLE);
/* DGT uses LPXO source which is 27MHz.
* Set clock divider to 4.
*/
writel(3, DGT_CLK_CTL);
ticks_per_sec = 6750000; /* (27 MHz / 4) */
}
/* Returns timer ticks per sec */
uint32_t platform_tick_rate(void)
{
return ticks_per_sec;
}
@@ -0,0 +1,425 @@
/*
* * Copyright (c) 2010-2013, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <debug.h>
#include <reg.h>
#include <bits.h>
#include <platform/iomap.h>
#include <platform/pmic.h>
#define TRUE 1
#define FALSE 0
/* FTS regulator PMR registers */
#define SSBI_REG_ADDR_S1_PMR (0xA7)
#define SSBI_REG_ADDR_S2_PMR (0xA8)
#define SSBI_REG_ADDR_S3_PMR (0xA9)
#define SSBI_REG_ADDR_S4_PMR (0xAA)
#define REGULATOR_PMR_STATE_MASK 0x60
#define REGULATOR_PMR_STATE_OFF 0x20
/* Regulator control registers for shutdown/reset */
#define SSBI_REG_ADDR_L22_CTRL 0x121
/* SLEEP CNTL register */
#define SSBI_REG_ADDR_SLEEP_CNTL 0x02B
#define PM8058_SLEEP_SMPL_EN_MASK 0x04
#define PM8058_SLEEP_SMPL_EN_RESET 0x04
#define PM8058_SLEEP_SMPL_EN_PWR_OFF 0x00
/* PON CNTL 1 register */
#define SSBI_REG_ADDR_PON_CNTL_1 0x01C
#define PM8058_PON_PUP_MASK 0xF0
#define PM8058_PON_WD_EN_MASK 0x08
#define PM8058_PON_WD_EN_RESET 0x08
#define PM8058_PON_WD_EN_PWR_OFF 0x00
#define PM8058_RTC_CTRL 0x1E8
#define PM8058_RTC_ALARM_ENABLE BIT(1)
#define PM_IRQ_ID_TO_BLOCK_INDEX(id) (uint8_t)(id / 8)
#define PM_IRQ_ID_TO_BIT_MASK(id) (uint8_t)(1 << (id % 8))
/* HDMI MPP Registers */
#define SSBI_MPP_CNTRL_BASE 0x27
#define SSBI_MPP_CNTRL(n) (SSBI_MPP_CNTRL_BASE + (n))
#define PM8901_MPP_TYPE_MASK 0xE0
#define PM8901_MPP_CONFIG_LVL_MASK 0x1C
#define PM8901_MPP_CONFIG_CTL_MASK 0x03
#define PM8901_MPP0_CTRL_VAL 0x30
#define VREG_PMR_STATE_MASK 0x60
#define VREG_PMR_STATE_HPM 0x7F
#define VS_CTRL_USE_PMR 0xD0
#define VS_CTRL_ENABLE_MASK 0xD0
#define LDO_CTRL_VPROG_MASK 0x1F
#define REGULATOR_EN_MASK 0x80
#define PM8901_HDMI_MVS_CTRL 0x058
#define PM8901_HDMI_MVS_PMR 0x0B8
#define PM8058_HDMI_L16_CTRL 0x08A
typedef int (*pm8058_write_func) (unsigned char *, unsigned short,
unsigned short);
extern int pa1_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
extern int pa1_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
extern int pa2_ssbi2_write_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
extern int pa2_ssbi2_read_bytes(unsigned char *buffer, unsigned short length,
unsigned short slave_addr);
/* PM8058 APIs */
int pm8058_write(uint16_t addr, uint8_t * data, uint16_t length)
{
return pa1_ssbi2_write_bytes(data, length, addr);
}
int pm8058_read(uint16_t addr, uint8_t * data, uint16_t length)
{
return pa1_ssbi2_read_bytes(data, length, addr);
}
void pm8058_write_one(unsigned data, unsigned address)
{
pm8058_write_func wr_function = &pa1_ssbi2_write_bytes;
if (wr_function == NULL)
return;
if ((*wr_function) (&data, 1, address))
dprintf(CRITICAL, "Error in initializing register\n");
}
int pm8058_get_irq_status(pm_irq_id_type irq, bool * rt_status)
{
unsigned block_index, reg_data, reg_mask;
int errFlag;
block_index = PM_IRQ_ID_TO_BLOCK_INDEX(irq);
/* select the irq block */
errFlag =
pa1_ssbi2_write_bytes(&block_index, 1, IRQ_BLOCK_SEL_USR_ADDR);
if (errFlag) {
dprintf(INFO, "Device Timeout");
return 1;
}
/* read real time status */
errFlag = pa1_ssbi2_read_bytes(&reg_data, 1, IRQ_STATUS_RT_USR_ADDR);
if (errFlag) {
dprintf(INFO, "Device Timeout");
return 1;
}
reg_mask = PM_IRQ_ID_TO_BIT_MASK(irq);
if ((reg_data & reg_mask) == reg_mask) {
/* The RT Status is high. */
*rt_status = TRUE;
} else {
/* The RT Status is low. */
*rt_status = FALSE;
}
return 0;
}
bool pm8058_gpio_get(unsigned int gpio)
{
pm_irq_id_type gpio_irq;
bool status;
int ret;
gpio_irq = gpio + PM_GPIO01_CHGED_ST_IRQ_ID;
ret = pm8058_get_irq_status(gpio_irq, &status);
if (ret)
dprintf(CRITICAL, "pm8058_gpio_get failed\n");
return status;
}
int pm8058_mwrite(uint16_t addr, uint8_t val, uint8_t mask, uint8_t * reg_save)
{
int rc = 0;
uint8_t reg;
reg = (*reg_save & ~mask) | (val & mask);
if (reg != *reg_save)
rc = pm8058_write(addr, &reg, 1);
if (rc)
dprintf(CRITICAL, "pm8058_write failed; addr=%03X, rc=%d\n",
addr, rc);
else
*reg_save = reg;
return rc;
}
int pm8058_ldo_set_voltage()
{
int ret = 0;
unsigned vprog = 0x00000110;
ret =
pm8058_mwrite(PM8058_HDMI_L16_CTRL, vprog, LDO_CTRL_VPROG_MASK, 0);
if (ret) {
dprintf(SPEW, "Failed to set voltage for l16 regulator\n");
}
return ret;
}
int pm8058_vreg_enable()
{
int ret = 0;
ret =
pm8058_mwrite(PM8058_HDMI_L16_CTRL, REGULATOR_EN_MASK,
REGULATOR_EN_MASK, 0);
if (ret) {
dprintf(SPEW, "Vreg enable failed for PM 8058\n");
}
return ret;
}
/* PM8901 APIs */
/*
* Write to the control registers on PMIC via the SSBI2 interface.
* Returns : (0) on success and (-1) on error.
*/
int pm8901_write(uint8_t * buffer, uint32_t length, uint32_t slave_addr)
{
return pa2_ssbi2_write_bytes(buffer, length, slave_addr);
}
/*
* Read from the control registers on PMIC via the SSBI2 interface.
* Returns : (0) on success and (-1) on error.
*/
int pm8901_read(uint8_t * buffer, uint32_t length, uint32_t slave_addr)
{
return pa2_ssbi2_read_bytes(buffer, length, slave_addr);
}
/*
* PMIC 8901 LDO vreg read.
*/
int pm8901_test_bank_read(uint8_t * buffer, uint8_t bank, uint16_t addr)
{
int ret = pm8901_write(&bank, 1, addr);
/* if the write does not work we can't read. */
if (ret) {
return ret;
}
return pm8901_read(buffer, 1, addr);
}
/*
* PMIC 8901 LDO vreg write.
*/
int pm8901_vreg_write(uint8_t * buffer, uint8_t mask, uint16_t addr,
uint8_t prev_val)
{
uint8_t reg;
/* Clear the bits we want to try and set. */
reg = (prev_val & ~mask);
/* Set the bits we want to set, before writing them to addr */
reg |= (*buffer & mask);
return pm8901_write(&reg, 1, addr);
}
int pm8901_reset_pwr_off(int reset)
{
int rc = 0, i;
uint8_t pmr;
uint8_t pmr_addr[4] = {
SSBI_REG_ADDR_S2_PMR,
SSBI_REG_ADDR_S3_PMR,
SSBI_REG_ADDR_S4_PMR,
SSBI_REG_ADDR_S1_PMR,
};
/* Turn off regulators S1, S2, S3, S4 when shutting down. */
if (!reset) {
for (i = 0; i < 4; i++) {
rc = pm8901_read(&pmr, 1, pmr_addr[i]);
if (rc) {
goto get_out;
}
pmr &= ~REGULATOR_PMR_STATE_MASK;
pmr |= REGULATOR_PMR_STATE_OFF;
rc = pm8901_write(&pmr, 1, pmr_addr[i]);
if (rc) {
goto get_out;
}
}
}
get_out:
return rc;
}
int pm8901_ldo_disable(int ldo_id)
{
int rc = -1;
uint8_t prev_val = 0x0, val = 0x3F, mask = 0x7F;
if(ldo_id >= LDO_START && ldo_id <= LDO_END) {
rc = pm8901_read(&prev_val, 1, PM8901_PMR_REG(ldo_id));
if (rc)
goto get_out;
rc = pm8901_vreg_write(&val, mask, PM8901_PMR_REG(ldo_id), prev_val);
if (rc)
goto get_out;
}
get_out:
return rc;
}
int pm8058_reset_pwr_off(int reset)
{
int rc;
uint8_t pon, ctrl, smpl;
/* Set regulator L22 to 1.225V in high power mode. */
rc = pm8058_read(SSBI_REG_ADDR_L22_CTRL, &ctrl, 1);
if (rc) {
goto get_out3;
}
/* Leave pull-down state intact. */
ctrl &= 0x40;
ctrl |= 0x93;
rc = pm8058_write(SSBI_REG_ADDR_L22_CTRL, &ctrl, 1);
if (rc) {
}
get_out3:
if (!reset) {
/* Only modify the SLEEP_CNTL reg if shutdown is desired. */
rc = pm8058_read(SSBI_REG_ADDR_SLEEP_CNTL, &smpl, 1);
if (rc) {
goto get_out2;
}
smpl &= ~PM8058_SLEEP_SMPL_EN_MASK;
smpl |= PM8058_SLEEP_SMPL_EN_PWR_OFF;
rc = pm8058_write(SSBI_REG_ADDR_SLEEP_CNTL, &smpl, 1);
if (rc) {
}
}
get_out2:
rc = pm8058_read(SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
if (rc) {
goto get_out;
}
pon &= ~PM8058_PON_WD_EN_MASK;
pon |= reset ? PM8058_PON_WD_EN_RESET : PM8058_PON_WD_EN_PWR_OFF;
/* Enable all pullups */
pon |= PM8058_PON_PUP_MASK;
rc = pm8058_write(SSBI_REG_ADDR_PON_CNTL_1, &pon, 1);
if (rc) {
goto get_out;
}
get_out:
return rc;
}
int pm8058_rtc0_alarm_irq_disable(void)
{
int rc;
uint8_t reg;
rc = pm8058_read(PM8058_RTC_CTRL, &reg, 1);
if (rc) {
return rc;
}
reg = (reg & ~PM8058_RTC_ALARM_ENABLE);
rc = pm8058_write(PM8058_RTC_CTRL, &reg, 1);
if (rc) {
return rc;
}
return rc;
}
int pm8901_mpp_enable()
{
uint8_t prevval = 0x0;
uint16_t mask;
uint8_t conf;
int ret = 0;
conf = PM8901_MPP0_CTRL_VAL;
mask = PM8901_MPP_TYPE_MASK | PM8901_MPP_CONFIG_LVL_MASK |
PM8901_MPP_CONFIG_CTL_MASK;
if (ret = pm8901_vreg_write(&conf, mask, SSBI_MPP_CNTRL(0), prevval)) {
dprintf(SPEW, "PM8901 MPP failed\n");
}
return ret;
}
int pm8901_vs_enable()
{
uint8_t val = VREG_PMR_STATE_HPM;
int prevval = 0x0;
int ret = 0;
if (ret =
pm8901_vreg_write(&val, VREG_PMR_STATE_HPM, PM8901_HDMI_MVS_PMR,
prevval)) {
dprintf(SPEW,
"pm8901_vreg_write failed for MVS PMR register\n");
return ret;
}
val = VS_CTRL_USE_PMR;
if (ret =
pm8901_vreg_write(&val, VS_CTRL_ENABLE_MASK, PM8901_HDMI_MVS_CTRL,
prevval)) {
dprintf(SPEW,
"pm8901_vreg_write failed for MVS ctrl register\n");
return ret;
}
return ret;
}
@@ -0,0 +1,466 @@
/*
* * Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <debug.h>
#include <platform/pmic_batt_alarm.h>
static struct pm_batt_alarm_device battdev;
/*
* Function to set threshold voltages for battery alarm
*/
static int pm_batt_alarm_threshold_set(uint32_t lower_threshold_mV,
uint32_t upper_threshold_mV)
{
uint32_t step, fine_step, rc = -1;
uint8_t reg_threshold = 0, reg_ctrl2 = 0;
if (lower_threshold_mV < THRESHOLD_MIN_MV
|| lower_threshold_mV > THRESHOLD_MAX_MV) {
dprintf(CRITICAL,
"lower threshold value, %d mV, is outside of allowable "
"range: [%d, %d] mV\n", lower_threshold_mV,
THRESHOLD_MIN_MV, THRESHOLD_MAX_MV);
goto bail;
}
if (upper_threshold_mV < THRESHOLD_MIN_MV
|| upper_threshold_mV > THRESHOLD_MAX_MV) {
dprintf(CRITICAL,
"upper threshold value, %d mV, is outside of allowable "
"range: [%d, %d] mV\n", upper_threshold_mV,
THRESHOLD_MIN_MV, THRESHOLD_MAX_MV);
goto bail;
}
if (upper_threshold_mV < lower_threshold_mV) {
dprintf(CRITICAL,
"lower threshold value, %d mV, must be <= upper "
"threshold value, %d mV\n", lower_threshold_mV,
upper_threshold_mV);
goto bail;
}
/* Determine register settings for lower threshold. */
if (lower_threshold_mV < THRESHOLD_BASIC_MIN_MV) {
/* Extended low range */
reg_ctrl2 |= CTRL2_RANGE_EXT_LOWER_MASK;
step = (lower_threshold_mV - THRESHOLD_MIN_MV)
/ THRESHOLD_STEP_MV;
fine_step = step & 0x3;
/* Extended low range is for steps 0 to 2 */
step >>= 2;
} else if (lower_threshold_mV >= THRESHOLD_EXT_MIN_MV) {
/* Extended high range */
reg_ctrl2 |= CTRL2_RANGE_EXT_LOWER_MASK;
step = (lower_threshold_mV - THRESHOLD_EXT_MIN_MV)
/ THRESHOLD_STEP_MV;
fine_step = step & 0x3;
/* Extended high range is for steps 3 to 15 */
step = (step >> 2) + 3;
} else {
/* Basic range */
step = (lower_threshold_mV - THRESHOLD_BASIC_MIN_MV)
/ THRESHOLD_STEP_MV;
fine_step = step & 0x3;
step >>= 2;
}
reg_threshold |= (step << THRESHOLD_LOWER_SHIFT);
reg_ctrl2 |= (fine_step << CTRL2_FINE_STEP_LOWER_SHIFT);
/* Determine register settings for upper threshold. */
if (upper_threshold_mV < THRESHOLD_BASIC_MIN_MV) {
/* Extended low range */
reg_ctrl2 |= CTRL2_RANGE_EXT_UPPER_MASK;
step = (upper_threshold_mV - THRESHOLD_MIN_MV)
/ THRESHOLD_STEP_MV;
fine_step = step & 0x3;
/* Extended low range is for steps 0 to 2 */
step >>= 2;
} else if (upper_threshold_mV >= THRESHOLD_EXT_MIN_MV) {
/* Extended high range */
reg_ctrl2 |= CTRL2_RANGE_EXT_UPPER_MASK;
step = (upper_threshold_mV - THRESHOLD_EXT_MIN_MV)
/ THRESHOLD_STEP_MV;
fine_step = step & 0x3;
/* Extended high range is for steps 3 to 15 */
step = (step >> 2) + 3;
} else {
/* Basic range */
step = (upper_threshold_mV - THRESHOLD_BASIC_MIN_MV)
/ THRESHOLD_STEP_MV;
fine_step = step & 0x3;
step >>= 2;
}
reg_threshold |= (step << THRESHOLD_UPPER_SHIFT);
reg_ctrl2 |= (fine_step << CTRL2_FINE_STEP_UPPER_SHIFT);
rc = pm8058_mwrite(PM8058_REG_THRESHOLD, reg_threshold,
THRESHOLD_LOWER_MASK | THRESHOLD_UPPER_MASK,
&battdev.reg_threshold);
if (rc) {
dprintf(CRITICAL, "Error in pm8058_mwrite THRESHOLD\n");
goto bail;
}
rc = pm8058_mwrite(PM8058_REG_CTRL2, reg_ctrl2,
CTRL2_FINE_STEP_LOWER_MASK |
CTRL2_FINE_STEP_UPPER_MASK |
CTRL2_RANGE_EXT_LOWER_MASK |
CTRL2_RANGE_EXT_UPPER_MASK, &battdev.reg_ctrl2);
if (rc)
dprintf(CRITICAL, "Error in pm8058_mwrite CTRL2\n");
bail:
return rc;
}
/*
* Function to set hold time (hysteresis) for battery alarm
*/
static int pm_batt_alarm_hold_time_set(pm_batt_alarm_hold_time hold_time)
{
int rc = -1;
uint8_t reg_ctrl1 = 0;
if (hold_time < CTRL1_HOLD_TIME_MIN || hold_time > CTRL1_HOLD_TIME_MAX) {
dprintf(CRITICAL,
"hold time, %d, is outside of allowable range: "
"[%d, %d]\n", hold_time, CTRL1_HOLD_TIME_MIN,
CTRL1_HOLD_TIME_MAX);
goto bail;
}
reg_ctrl1 = hold_time << CTRL1_HOLD_TIME_SHIFT;
rc = pm8058_mwrite(PM8058_REG_CTRL1, reg_ctrl1,
CTRL1_HOLD_TIME_MASK, &battdev.reg_ctrl1);
if (rc)
dprintf(CRITICAL, "Error in pm8058_mwrite CTRL1\n");
bail:
return rc;
}
/*
* Function to set PWM clock rate for battery alarm
*/
static int pm_batt_alarm_pwm_rate_set(pm_batt_alarm_pwm_ctrl pwm_ctrl_select,
uint32_t clock_scaler,
uint32_t clock_divider)
{
int rc = -1;
uint8_t reg_pwm_ctrl = 0, mask = 0;
if (pwm_ctrl_select == ALARM_EN_PWM) {
if (clock_scaler < PWM_CTRL_PRE_INPUT_MIN
|| clock_scaler > PWM_CTRL_PRE_INPUT_MAX) {
dprintf(CRITICAL,
"PWM clock scaler, %d, is outside of allowable range: "
"[%d, %d]\n", clock_scaler,
PWM_CTRL_PRE_INPUT_MIN, PWM_CTRL_PRE_INPUT_MAX);
goto bail;
}
if (clock_divider < PWM_CTRL_DIV_INPUT_MIN
|| clock_divider > PWM_CTRL_DIV_INPUT_MAX) {
dprintf(CRITICAL,
"PWM clock divider, %d, is outside of allowable range: "
"[%d, %d]\n", clock_divider,
PWM_CTRL_DIV_INPUT_MIN, PWM_CTRL_DIV_INPUT_MAX);
goto bail;
}
/* Use PWM control. */
reg_pwm_ctrl = PWM_CTRL_ALARM_EN_PWM;
mask = PWM_CTRL_ALARM_EN_MASK | PWM_CTRL_PRE_MASK
| PWM_CTRL_DIV_MASK;
clock_scaler -= PWM_CTRL_PRE_INPUT_MIN - PWM_CTRL_PRE_MIN;
clock_divider -= PWM_CTRL_DIV_INPUT_MIN - PWM_CTRL_DIV_MIN;
reg_pwm_ctrl |= (clock_scaler << PWM_CTRL_PRE_SHIFT);
reg_pwm_ctrl |= (clock_divider << PWM_CTRL_DIV_SHIFT);
} else {
if (pwm_ctrl_select == ALARM_EN_ALWAYS) {
reg_pwm_ctrl = PWM_CTRL_ALARM_EN_ALWAYS;
} else if (pwm_ctrl_select == ALARM_EN_NEVER) {
reg_pwm_ctrl = PWM_CTRL_ALARM_EN_NEVER;
}
mask = PWM_CTRL_ALARM_EN_MASK;
}
rc = pm8058_mwrite(PM8058_REG_PWM_CTRL, reg_pwm_ctrl,
mask, &battdev.reg_pwm_ctrl);
if (rc)
dprintf(CRITICAL, "Error in pm8058_mwrite PWM_CTRL\n");
bail:
return rc;
}
/*
* Function to enable/disable alarm comparators for battery alarm
*/
static int pm_batt_alarm_state_set(uint8_t enable_lower_comparator,
uint8_t enable_upper_comparator)
{
int rc = -1;
uint8_t reg_ctrl1 = 0, reg_ctrl2 = 0;
if (!enable_lower_comparator)
reg_ctrl2 |= CTRL2_COMP_LOWER_DISABLE_MASK;
if (!enable_upper_comparator)
reg_ctrl2 |= CTRL2_COMP_UPPER_DISABLE_MASK;
if (enable_lower_comparator || enable_upper_comparator)
reg_ctrl1 = CTRL1_BATT_ALARM_EN_MASK;
rc = pm8058_mwrite(PM8058_REG_CTRL1, reg_ctrl1,
CTRL1_BATT_ALARM_EN_MASK, &battdev.reg_ctrl1);
if (rc) {
dprintf(CRITICAL, "Error in pm8058_mwrite CTRL1\n");
goto bail;
}
rc = pm8058_mwrite(PM8058_REG_CTRL2, reg_ctrl2,
CTRL2_COMP_LOWER_DISABLE_MASK |
CTRL2_COMP_UPPER_DISABLE_MASK, &battdev.reg_ctrl2);
if (rc)
dprintf(CRITICAL, "Error in pm8058_mwrite CTRL2\n");
bail:
return rc;
}
/*
* Function to read alarm status for battery alarm
*/
int pm_batt_alarm_status_read(uint8_t * status)
{
int rc = -1;
rc = pm8058_read(PM8058_REG_CTRL1, &battdev.reg_ctrl1, 1);
if (rc) {
dprintf(CRITICAL, "Error in reading CTRL1\n");
goto bail;
}
*status = ((battdev.reg_ctrl1 & CTRL1_STATUS_LOWER_MASK)
? PM_BATT_ALARM_STATUS_BELOW_LOWER : 0)
| ((battdev.reg_ctrl1 & CTRL1_STATUS_UPPER_MASK)
? PM_BATT_ALARM_STATUS_ABOVE_UPPER : 0);
/* Disabling Battery alarm below just for power savings. This can be
* removed if this does not matter
*/
/* After reading, disabling the comparators and BATT_ALARM_EN */
rc = pm_batt_alarm_state_set(LOWER_COMP_DISABLE, UPPER_COMP_DISABLE);
if (rc) {
dprintf(CRITICAL, "state_set failed, rc=%d\n", rc);
goto bail;
}
rc = pm_batt_alarm_pwm_rate_set(ALARM_EN_NEVER, DEFAULT_PWM_SCALER,
DEFAULT_PWM_DIVIDER);
if (rc) {
dprintf(CRITICAL, "state_set failed, rc=%d\n", rc);
goto bail;
}
bail:
return rc;
}
/*
* Function to read and print battery alarm registers for debugging
*/
int pm_batt_alarm_read_regs(struct pm_batt_alarm_device *battdev)
{
int rc = -1;
if (battdev) {
rc = pm8058_read(PM8058_REG_THRESHOLD, &battdev->reg_threshold,
1);
if (rc)
goto done;
rc = pm8058_read(PM8058_REG_CTRL1, &battdev->reg_ctrl1, 1);
if (rc)
goto done;
rc = pm8058_read(PM8058_REG_CTRL2, &battdev->reg_ctrl2, 1);
if (rc)
goto done;
rc = pm8058_read(PM8058_REG_PWM_CTRL, &battdev->reg_pwm_ctrl,
1);
if (rc)
goto done;
}
done:
if (rc)
dprintf(CRITICAL, "pm_batt_alarm_read_regs read error\n");
return rc;
}
/*
* Function for battery alarm initialization
*/
int pm_batt_alarm_init()
{
int rc = -1;
rc = pm_batt_alarm_read_regs(&battdev);
if (rc) {
dprintf(CRITICAL, "read_regs failed, rc=%d\n", rc);
goto bail;
}
rc = pm_batt_alarm_threshold_set(DEFAULT_THRESHOLD_LOWER,
DEFAULT_THRESHOLD_UPPER);
if (rc) {
dprintf(CRITICAL, "threshold_set failed, rc=%d\n", rc);
goto bail;
}
rc = pm_batt_alarm_hold_time_set(DEFAULT_HOLD_TIME);
if (rc) {
dprintf(CRITICAL, "hold_time_set failed, rc=%d\n", rc);
goto bail;
}
rc = pm_batt_alarm_pwm_rate_set(ALARM_EN_NEVER, DEFAULT_PWM_SCALER,
DEFAULT_PWM_DIVIDER);
if (rc) {
dprintf(CRITICAL, "pwm_rate_set failed, rc=%d\n", rc);
goto bail;
}
rc = pm_batt_alarm_state_set(LOWER_COMP_DISABLE, UPPER_COMP_DISABLE);
if (rc)
dprintf(CRITICAL, "state_set failed, rc=%d\n", rc);
bail:
return rc;
}
/*
* Function to configure voltages and change alarm state
*/
int pm_batt_alarm_set_voltage(uint32_t lower_threshold,
uint32_t upper_threshold)
{
int rc = -1;
rc = pm_batt_alarm_threshold_set(lower_threshold, upper_threshold);
if (rc) {
dprintf(CRITICAL, "threshold_set failed, rc=%d\n", rc);
goto bail;
}
rc = pm_batt_alarm_pwm_rate_set(ALARM_EN_ALWAYS, DEFAULT_PWM_SCALER,
DEFAULT_PWM_DIVIDER);
if (rc) {
dprintf(CRITICAL, "pwm_rate_set failed, rc=%d\n", rc);
goto bail;
}
rc = pm_batt_alarm_state_set(LOWER_COMP_ENABLE, UPPER_COMP_ENABLE);
if (rc)
dprintf(CRITICAL, "state_set failed, rc=%d\n", rc);
bail:
return rc;
}
/*
* Function to test battery alarms
*/
void pm_ba_test(void)
{
int rc = 0;
uint8_t batt_status = 0;
rc = pm_batt_alarm_init();
if (rc)
dprintf(CRITICAL, "pm_batt_alarm_init error\n");
/* wait till hold time */
mdelay(16);
/* 0xe74-> 3700mV, 0x1004-> 4100mv */
rc = pm_batt_alarm_set_voltage(0xe74, 0x1004);
if (rc)
dprintf(CRITICAL, "pm_batt_alarm_set_voltage error\n");
/* wait till hold time */
mdelay(16);
rc = pm_batt_alarm_status_read(&batt_status);
if (rc)
dprintf(CRITICAL, "pm_batt_alarm_status_read error\n");
else
dprintf(ALWAYS, "batt status: %d\n", batt_status);
}
@@ -0,0 +1,282 @@
/*
* * Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <debug.h>
#include <platform/pmic.h>
#include <platform/pmic_pwm.h>
static char *clks[NUM_CLOCKS] = {
"1K", "32768", "19.2M"
};
static unsigned pre_div[NUM_PRE_DIVIDE] = {
PRE_DIVIDE_0, PRE_DIVIDE_1, PRE_DIVIDE_2
};
static unsigned int pt_t[NUM_PRE_DIVIDE][NUM_CLOCKS] = {
{PRE_DIVIDE_0 * NSEC_1000HZ,
PRE_DIVIDE_0 * NSEC_32768HZ,
PRE_DIVIDE_0 * NSEC_19P2MHZ,
},
{PRE_DIVIDE_1 * NSEC_1000HZ,
PRE_DIVIDE_1 * NSEC_32768HZ,
PRE_DIVIDE_1 * NSEC_19P2MHZ,
},
{PRE_DIVIDE_2 * NSEC_1000HZ,
PRE_DIVIDE_2 * NSEC_32768HZ,
PRE_DIVIDE_2 * NSEC_19P2MHZ,
},
};
static uint16_t duty_msec[PM_PWM_1KHZ_COUNT_MAX + 1] = {
0, 1, 2, 3, 4, 6, 8, 16, 18, 24, 32, 36, 64, 128, 256, 512
};
static uint16_t pause_count[PM_PWM_PAUSE_COUNT_MAX + 1] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
23, 28, 31, 42, 47, 56, 63, 83, 94, 111, 125, 167, 188, 222, 250, 333,
375, 500, 667, 750, 800, 900, 1000, 1100,
1200, 1300, 1400, 1500, 1600, 1800, 2000, 2500,
3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500,
7000
};
/* Function to get the PWM size, divider, clock for the given period */
static void pm_pwm_calc_period(uint32_t period_us,
struct pm_pwm_config *pwm_conf)
{
int n, m, clk, div;
int best_m, best_div, best_clk;
int last_err, cur_err, better_err, better_m;
uint32_t tmp_p, last_p, min_err, period_n;
/* PWM Period / N : handle underflow or overflow */
if (period_us < (PM_PWM_PERIOD_MAX / NSEC_PER_USEC))
period_n = (period_us * NSEC_PER_USEC) >> 6;
else
period_n = (period_us >> 6) * NSEC_PER_USEC;
if (period_n >= MAX_MPT) {
n = 9;
period_n >>= 3;
} else
n = 6;
min_err = MAX_MPT;
best_m = 0;
best_clk = 0;
best_div = 0;
for (clk = 0; clk < NUM_CLOCKS; clk++) {
for (div = 0; div < NUM_PRE_DIVIDE; div++) {
tmp_p = period_n;
last_p = tmp_p;
for (m = 0; m <= PM_PWM_M_MAX; m++) {
if (tmp_p <= pt_t[div][clk]) {
/* Found local best */
if (!m) {
better_err =
pt_t[div][clk] - tmp_p;
better_m = m;
} else {
last_err =
last_p - pt_t[div][clk];
cur_err =
pt_t[div][clk] - tmp_p;
if (cur_err < last_err) {
better_err = cur_err;
better_m = m;
} else {
better_err = last_err;
better_m = m - 1;
}
}
if (better_err < min_err) {
min_err = better_err;
best_m = better_m;
best_clk = clk;
best_div = div;
}
break;
} else {
last_p = tmp_p;
tmp_p >>= 1;
}
}
}
}
pwm_conf->pwm_size = n;
pwm_conf->clk = best_clk;
pwm_conf->pre_div = best_div;
pwm_conf->pre_div_exp = best_m;
}
/* Function to configure PWM control registers with clock, divider values */
static int pm_pwm_configure(uint8_t pwm_id, struct pm_pwm_config *pwm_conf)
{
int i, len, rc = -1;
uint8_t reg;
reg = (pwm_conf->pwm_size > 6) ? PM_PWM_SIZE_9_BIT : 0;
pwm_conf->pwm_ctl[5] = reg;
reg = ((pwm_conf->clk + 1) << PM_PWM_CLK_SEL_SHIFT)
& PM_PWM_CLK_SEL_MASK;
reg |= (pwm_conf->pre_div << PM_PWM_PREDIVIDE_SHIFT)
& PM_PWM_PREDIVIDE_MASK;
reg |= pwm_conf->pre_div_exp & PM_PWM_M_MASK;
pwm_conf->pwm_ctl[4] = reg;
/* Just to let know we bypass LUT */
if (pwm_conf->bypass_lut) {
/* CTL0 is set in pwm_enable() */
pwm_conf->pwm_ctl[0] &= PM_PWM_PWM_START;
pwm_conf->pwm_ctl[1] = PM_PWM_BYPASS_LUT;
pwm_conf->pwm_ctl[2] = 0;
if (pwm_conf->pwm_size > 6) {
pwm_conf->pwm_ctl[3] = pwm_conf->pwm_value
& PM_PWM_VALUE_BIT7_0;
pwm_conf->pwm_ctl[4] |= (pwm_conf->pwm_value >> 1)
& PM_PWM_VALUE_BIT8;
} else {
pwm_conf->pwm_ctl[3] = pwm_conf->pwm_value
& PM_PWM_VALUE_BIT5_0;
}
len = 6;
} else {
/* Right now, we are not using LUT */
goto bail_out;
}
/* Selecting the bank */
rc = pm8058_write(PM8058_LPG_BANK_SEL, &pwm_id, 1);
if (rc)
goto bail_out;
for (i = 0; i < len; i++) {
rc = pm8058_write(PM8058_LPG_CTL(i), &pwm_conf->pwm_ctl[i], 1);
if (rc) {
dprintf(CRITICAL,
"pm8058_write() failed in pwm_configure %d\n",
rc);
break;
}
}
bail_out:
if (rc)
dprintf(CRITICAL, "Error in pm_pwm_configure()\n");
return rc;
}
/* Top level function for configuring PWM */
int pm_pwm_config(uint8_t pwm_id, uint32_t duty_us, uint32_t period_us)
{
struct pm_pwm_config pwm_conf;
uint32_t max_pwm_value, tmp;
int rc = -1;
if ((duty_us > period_us) || (period_us > PM_PWM_PERIOD_MAX) ||
(period_us < PM_PWM_PERIOD_MIN)) {
dprintf(CRITICAL, "Error in duty cycle and period\n");
return -1;
}
pm_pwm_calc_period(period_us, &pwm_conf);
/* Figure out pwm_value with overflow handling */
if (period_us > (1 << pwm_conf.pwm_size)) {
tmp = period_us;
tmp >>= pwm_conf.pwm_size;
pwm_conf.pwm_value = duty_us / tmp;
} else {
tmp = duty_us;
tmp <<= pwm_conf.pwm_size;
pwm_conf.pwm_value = tmp / period_us;
}
max_pwm_value = (1 << pwm_conf.pwm_size) - 1;
if (pwm_conf.pwm_value > max_pwm_value)
pwm_conf.pwm_value = max_pwm_value;
/* Bypassing LUT */
pwm_conf.bypass_lut = 1;
dprintf(SPEW, "duty/period=%u/%u usec: pwm_value=%d (of %d)\n",
duty_us, period_us, pwm_conf.pwm_value, 1 << pwm_conf.pwm_size);
rc = pm_pwm_configure(pwm_id, &pwm_conf);
if (rc)
dprintf(CRITICAL, "Error in pwm_config()\n");
return rc;
}
/* Top level function to enable PWM with specified id */
int pm_pwm_enable(uint8_t pwm_id)
{
int rc = -1;
uint8_t reg;
/* Read it before enabling other bank */
rc = pm8058_read(PM8058_LPG_BANK_ENABLE, &reg, 1);
if (rc)
goto bail_out;
reg |= (1 << pwm_id);
rc = pm8058_write(PM8058_LPG_BANK_ENABLE, &reg, 1);
if (rc)
goto bail_out;
/* Selecting the bank */
rc = pm8058_write(PM8058_LPG_BANK_SEL, &pwm_id, 1);
if (rc)
goto bail_out;
/* Read it before setting PWM start */
rc = pm8058_read(PM8058_LPG_CTL(0), &reg, 1);
if (rc)
goto bail_out;
reg |= PM_PWM_PWM_START;
reg &= ~PM_PWM_RAMP_GEN_START;
rc = pm8058_write(PM8058_LPG_CTL(0), &reg, 1);
bail_out:
if (rc)
dprintf(CRITICAL, "Error in pwm_enable()\n");
return rc;
}
@@ -0,0 +1,38 @@
LOCAL_DIR := $(GET_LOCAL_DIR)
ARCH := arm
ARM_CPU := cortex-a8
CPU := generic
DEFINES += ARM_CPU_CORE_SCORPION
MMC_SLOT := 1
DEFINES += WITH_CPU_EARLY_INIT=0 WITH_CPU_WARM_BOOT=0 \
MMC_SLOT=$(MMC_SLOT) MDP4=1 \
SSD_ENABLE TZ_TAMPER_FUSE
DEFINES += QT_8660_KEYPAD_HW_BUG=1
INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared/include
DEVS += fbcon
MODULES += dev/fbcon
OBJS += \
$(LOCAL_DIR)/platform.o \
$(LOCAL_DIR)/acpuclock.o \
$(LOCAL_DIR)/gpio.o \
$(LOCAL_DIR)/panel.o \
$(LOCAL_DIR)/panel_auo_wvga.o \
$(LOCAL_DIR)/pmic.o \
$(LOCAL_DIR)/pmic_pwm.o \
$(LOCAL_DIR)/pmic_batt_alarm.o \
$(LOCAL_DIR)/scm-io.o \
$(LOCAL_DIR)/hdmi_core.o
LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld
include platform/msm_shared/rules.mk
@@ -0,0 +1,77 @@
/* Copyright (c) 2011, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <reg.h>
#include <platform/clock.h>
#include <platform/scm-io.h>
#include <platform/iomap.h>
#pragma GCC optimize ("O0")
#define SCM_IO_READ ((((0x5 << 10) | 0x1) << 12) | (0x2 << 8) | 0x1)
#define SCM_IO_WRITE ((((0x5 << 10) | 0x2) << 12) | (0x2 << 8) | 0x2)
#define BETWEEN(p, st, sz) ((p) >= (void *)(st) && \
(p) < ((void *)(st) + (sz)))
extern void dmb(void);
uint32_t secure_readl(uint32_t c)
{
if ((BETWEEN((void *)c, MSM_MMSS_CLK_CTL_BASE, MSM_MMSS_CLK_CTL_SIZE))
|| (BETWEEN((void *)c, MSM_TCSR_BASE, MSM_TCSR_SIZE))) {
uint32_t context_id;
register uint32_t r0 __asm__("r0") = SCM_IO_READ;
register uint32_t r1 __asm__("r1") = (uint32_t) & context_id;
register uint32_t r2 __asm__("r2") = c;
__asm__("smc #0 @ switch to secure world\n":"=r"(r0)
: "r"(r0), "r"(r1), "r"(r2)
);
dmb();
return r0;
}
return readl(c);
}
void secure_writel(uint32_t v, uint32_t c)
{
if ((BETWEEN((void *)c, MSM_MMSS_CLK_CTL_BASE, MSM_MMSS_CLK_CTL_SIZE))
|| (BETWEEN((void *)c, MSM_TCSR_BASE, MSM_TCSR_SIZE))) {
uint32_t context_id;
register uint32_t r0 __asm__("r0") = SCM_IO_WRITE;
register uint32_t r1 __asm__("r1") = (uint32_t) & context_id;
register uint32_t r2 __asm__("r2") = c;
register uint32_t r3 __asm__("r3") = v;
dmb();
__asm__("smc #0 @ switch to secure world\n": /* No return value */
:"r"(r0), "r"(r1), "r"(r2), "r"(r3)
);
} else
writel(v, c);
}