From 89208653320c099e3c4489a43f792633d99cf4c1 Mon Sep 17 00:00:00 2001 From: Sourabh Banerjee Date: Thu, 19 Feb 2015 16:43:26 +0530 Subject: ipq806x: extend GSBI driver to support i2c on any GSBI block The GSBI driver is extended to be able to program the CTRL reg for any given GSBI block. The NS and MD registers programming is made more readable by programming the M, N, D and other bits of the registers individually. Defined configure structs for each QUP block to be able to track the init status for each qup. Configured GPIO8 and GPIO9 for I2C fuction. BRANCH=chromeos-2013.04 BUG=chrome-os-partner:36722 TEST=Booted up storm P0.2, verified that the TPM on GSBI1 still works. Change-Id: I17906beedef5c80267cf114892080b121902210a Signed-off-by: Patrick Georgi Original-Commit-Id: 07bc79211770decc1070c3a88874a4e452b8f5bc Original-Change-Id: I841d0d419f7339f5e5cb3385da98786eb18252ad Original-Signed-off-by: Sourabh Banerjee Original-Reviewed-on: https://chromium-review.googlesource.com/250763 Original-Reviewed-by: Vadim Bendebury Original-Trybot-Ready: Vadim Bendebury Original-Commit-Queue: Vadim Bendebury Original-Tested-by: Vadim Bendebury Reviewed-on: http://review.coreboot.org/9759 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/mainboard/google/storm/gsbi.c | 8 +- src/soc/qualcomm/ipq806x/gsbi.c | 116 +++++++++++++++------------ src/soc/qualcomm/ipq806x/i2c.c | 47 +++++++++-- src/soc/qualcomm/ipq806x/include/soc/iomap.h | 72 +++++++++++++---- src/soc/qualcomm/ipq806x/include/soc/qup.h | 3 +- src/soc/qualcomm/ipq806x/include/soc/spi.h | 17 ++-- src/soc/qualcomm/ipq806x/qup.c | 16 ++-- 7 files changed, 183 insertions(+), 96 deletions(-) diff --git a/src/mainboard/google/storm/gsbi.c b/src/mainboard/google/storm/gsbi.c index 17b74e5f3e..915f317df9 100644 --- a/src/mainboard/google/storm/gsbi.c +++ b/src/mainboard/google/storm/gsbi.c @@ -1,7 +1,7 @@ /* * This file is part of the depthcharge project. * - * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2014 - 2015 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 @@ -36,6 +36,12 @@ int gsbi_init_board(gsbi_id_t gsbi_id) { switch (gsbi_id) { + case GSBI_ID_7: + gpio_tlmm_config_set(8, GPIO_FUNC_I2C, + GPIO_NO_PULL, GPIO_2MA, 1); + gpio_tlmm_config_set(9, GPIO_FUNC_I2C, + GPIO_NO_PULL, GPIO_2MA, 1); + break; case GSBI_ID_4: /* Configure GPIOs 13 - SCL, 12 - SDA, 2mA gpio_en */ gpio_tlmm_config_set(12, GPIO_FUNC_I2C, diff --git a/src/soc/qualcomm/ipq806x/gsbi.c b/src/soc/qualcomm/ipq806x/gsbi.c index 3fc723a555..54adbe8db7 100644 --- a/src/soc/qualcomm/ipq806x/gsbi.c +++ b/src/soc/qualcomm/ipq806x/gsbi.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2014 - 2015 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 @@ -28,68 +28,78 @@ */ #include +#include #include -#include +#include -//TODO: To be implemented as part of the iomap. -static int gsbi_base[] = { - 0x12440000, /*GSBI1*/ - 0x12480000, /*GSBI2*/ - 0x16200000, /*GSBI3*/ - 0x16300000, /*GSBI4*/ - 0x1A200000, /*GSBI5*/ - 0x16500000, /*GSBI6*/ - 0x16600000 /*GSBI7*/ -}; - -#define QUP_APPS_ADDR(N, os) ((void *)((0x009029C8+os)+(32*(N-1)))) -#define GSBI_HCLK_CTL(N) ((void *)(0x009029C0 + (32*(N-1)))) -#define GSBI_RESET(N) ((void *)(0x009029DC + (32*(N-1)))) -#define GSBI_CTL(N) ((void *)(gsbi_base[N-1])) - -#define GSBI_APPS_MD_OFFSET 0x0 -#define GSBI_APPS_NS_OFFSET 0x4 -#define GSBI_APPS_MAX_OFFSET 0xff +static inline void *gsbi_ctl_reg_addr(gsbi_id_t gsbi_id) +{ + switch (gsbi_id) { + case GSBI_ID_1: + return GSBI1_CTL_REG; + case GSBI_ID_2: + return GSBI2_CTL_REG; + case GSBI_ID_3: + return GSBI3_CTL_REG; + case GSBI_ID_4: + return GSBI4_CTL_REG; + case GSBI_ID_5: + return GSBI5_CTL_REG; + case GSBI_ID_6: + return GSBI6_CTL_REG; + case GSBI_ID_7: + return GSBI7_CTL_REG; + default: + printk(BIOS_ERR, "Unsupported GSBI%d\n", gsbi_id); + return 0; + } +} gsbi_return_t gsbi_init(gsbi_id_t gsbi_id, gsbi_protocol_t protocol) { - unsigned i = 0; - unsigned qup_apps_ini[] = { - GSBI_APPS_NS_OFFSET, 0xf80b43, - GSBI_APPS_NS_OFFSET, 0xfc095b, - GSBI_APPS_NS_OFFSET, 0xfc015b, - GSBI_APPS_NS_OFFSET, 0xfc005b, - GSBI_APPS_NS_OFFSET, 0xA05, - GSBI_APPS_NS_OFFSET, 0x185, - GSBI_APPS_MD_OFFSET, 0x100fb, - GSBI_APPS_NS_OFFSET, 0xA05, - GSBI_APPS_NS_OFFSET, 0xfc015b, - GSBI_APPS_NS_OFFSET, 0xfc015b, - GSBI_APPS_NS_OFFSET, 0xfc095b, - GSBI_APPS_NS_OFFSET, 0xfc0b5b, - GSBI_APPS_MAX_OFFSET, 0x0 - }; + unsigned reg_val; + unsigned m = 1; + unsigned n = 4; + unsigned pre_div = 4; + unsigned src = 3; + unsigned mnctr_mode = 2; + void *gsbi_ctl = gsbi_ctl_reg_addr(gsbi_id); - gsbi_return_t ret = GSBI_SUCCESS; + if (!gsbi_ctl) + return GSBI_ID_ERROR; - writel(0, GSBI_RESET(gsbi_id)); + writel((1 << GSBI_HCLK_CTL_GATE_ENA) | (1 << GSBI_HCLK_CTL_BRANCH_ENA), + GSBI_HCLK_CTL(gsbi_id)); - if (gsbi_init_board(gsbi_id)) { - ret = GSBI_UNSUPPORTED; - goto bail_out; - } + if (gsbi_init_board(gsbi_id)) + return GSBI_UNSUPPORTED; - /*Select i2c protocol*/ - writel((2 << 4), GSBI_CTL(gsbi_id)); + writel(0, GSBI_QUP_APSS_NS_REG(gsbi_id)); + writel(0, GSBI_QUP_APSS_MD_REG(gsbi_id)); + + reg_val = ((m & GSBI_QUP_APPS_M_MASK) << GSBI_QUP_APPS_M_SHFT) | + ((~n & GSBI_QUP_APPS_D_MASK) << GSBI_QUP_APPS_D_SHFT); + writel(reg_val, GSBI_QUP_APSS_MD_REG(gsbi_id)); + + reg_val = (((~(n - m)) & GSBI_QUP_APPS_N_MASK) << + GSBI_QUP_APPS_N_SHFT) | + ((mnctr_mode & GSBI_QUP_APPS_MNCTR_MODE_MSK) << + GSBI_QUP_APPS_MNCTR_MODE_SFT) | + (((pre_div - 1) & GSBI_QUP_APPS_PRE_DIV_MSK) << + GSBI_QUP_APPS_PRE_DIV_SFT) | + (src & GSBI_QUP_APPS_SRC_SEL_MSK); + writel(reg_val, GSBI_QUP_APSS_NS_REG(gsbi_id)); - //TODO: Make use of clock API when available instead of the hardcoding. - /* Clock set to 24Mhz */ - for (i = 0; GSBI_APPS_MAX_OFFSET != qup_apps_ini[i]; i += 2) - writel(qup_apps_ini[i+1], - QUP_APPS_ADDR(gsbi_id, qup_apps_ini[i])); + reg_val |= (1 << GSBI_QUP_APPS_ROOT_ENA_SFT) | + (1 << GSBI_QUP_APPS_MNCTR_EN_SFT); + writel(reg_val, GSBI_QUP_APSS_NS_REG(gsbi_id)); - writel(((1 << 6)|(1 << 4)), GSBI_HCLK_CTL(gsbi_id)); + reg_val |= (1 << GSBI_QUP_APPS_BRANCH_ENA_SFT); + writel(reg_val, GSBI_QUP_APSS_NS_REG(gsbi_id)); + + /*Select i2c protocol*/ + writel(((GSBI_CTL_PROTO_I2C & GSBI_CTL_PROTO_CODE_MSK) << + GSBI_CTL_PROTO_CODE_SFT), gsbi_ctl); -bail_out: - return ret; + return GSBI_SUCCESS; } diff --git a/src/soc/qualcomm/ipq806x/i2c.c b/src/soc/qualcomm/ipq806x/i2c.c index a4d1c00856..9aaa173513 100644 --- a/src/soc/qualcomm/ipq806x/i2c.c +++ b/src/soc/qualcomm/ipq806x/i2c.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2014 - 2015 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 @@ -37,11 +37,28 @@ #include #include -static const qup_config_t gsbi4_qup_config = { +static qup_config_t gsbi1_qup_config = { QUP_MINICORE_I2C_MASTER, 100000, 24000000, - QUP_MODE_FIFO + QUP_MODE_FIFO, + 0 +}; + +static qup_config_t gsbi4_qup_config = { + QUP_MINICORE_I2C_MASTER, + 100000, + 24000000, + QUP_MODE_FIFO, + 0 +}; + +static qup_config_t gsbi7_qup_config = { + QUP_MINICORE_I2C_MASTER, + 100000, + 24000000, + QUP_MODE_FIFO, + 0 }; static int i2c_read(uint32_t gsbi_id, uint8_t slave, @@ -84,10 +101,26 @@ static int i2c_write(uint32_t gsbi_id, uint8_t slave, static int i2c_init(unsigned bus) { - static uint8_t initialized = 0; unsigned gsbi_id = bus; + qup_config_t *qup_config; + + switch (gsbi_id) { + case GSBI_ID_1: + qup_config = &gsbi1_qup_config; + break; + case GSBI_ID_4: + qup_config = &gsbi4_qup_config; + break; + case GSBI_ID_7: + qup_config = &gsbi7_qup_config; + break; + default: + printk(BIOS_ERR, "QUP configuration not defind for GSBI%d.\n", + gsbi_id); + return 1; + } - if (initialized) + if (qup_config->initialized) return 0; if (gsbi_init(gsbi_id, GSBI_PROTO_I2C_ONLY)) { @@ -95,7 +128,7 @@ static int i2c_init(unsigned bus) return 1; } - if (qup_init(gsbi_id, &gsbi4_qup_config)) { + if (qup_init(gsbi_id, qup_config)) { printk(BIOS_ERR, "failed to initialize qup\n"); return 1; } @@ -105,7 +138,7 @@ static int i2c_init(unsigned bus) return 1; } - initialized = 1; + qup_config->initialized = 1; return 0; } diff --git a/src/soc/qualcomm/ipq806x/include/soc/iomap.h b/src/soc/qualcomm/ipq806x/include/soc/iomap.h index 76131805d4..412ff77c35 100644 --- a/src/soc/qualcomm/ipq806x/include/soc/iomap.h +++ b/src/soc/qualcomm/ipq806x/include/soc/iomap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved. + * Copyright (c) 2012 - 2013, 2015 The Linux Foundation. All rights reserved. * * Copyright (c) 2008, Google Inc. * All rights reserved. @@ -49,13 +49,13 @@ #define clrsetbits_le32_i(addr, clear, set) \ clrsetbits_le32(((void *)(addr)), (clear), (set)) -#define MSM_CLK_CTL_BASE ((unsigned char *)0x00900000) +#define MSM_CLK_CTL_BASE ((void *)0x00900000) -#define MSM_TMR_BASE ((unsigned char *)0x0200A000) +#define MSM_TMR_BASE ((void *)0x0200A000) #define MSM_GPT_BASE (MSM_TMR_BASE + 0x04) #define MSM_DGT_BASE (MSM_TMR_BASE + 0x24) -#define GPT_REG(off) ((void *)(MSM_GPT_BASE + (off))) +#define GPT_REG(off) (MSM_GPT_BASE + (off)) #define DGT_REG(off) (MSM_DGT_BASE + (off)) #define APCS_WDT0_EN (MSM_TMR_BASE + 0x0040) @@ -88,7 +88,7 @@ #define RPM_SIGNAL_ENTRY ((void *)0x47C24) #define RPM_FW_MAGIC_NUM 0x4D505242 -#define TLMM_BASE_ADDR ((char *)0x00800000) +#define TLMM_BASE_ADDR ((void *)0x00800000) #define GPIO_CONFIG_ADDR(x) (TLMM_BASE_ADDR + 0x1000 + (x)*0x10) #define GPIO_IN_OUT_ADDR(x) (GPIO_CONFIG_ADDR(x) + 4) @@ -100,10 +100,7 @@ #define USB_HOST1_DWC3_BASE 0x1100C100 #define USB_HOST1_PHY_BASE 0x110F8800 -#define GSBI_1 1 -#define GSBI_2 2 #define GSBI_4 4 -#define GSBI_2 2 #define UART1_DM_BASE 0x12450000 #define UART_GSBI1_BASE 0x12440000 #define UART2_DM_BASE 0x12490000 @@ -114,12 +111,55 @@ #define UART2_DM_BASE 0x12490000 #define UART_GSBI2_BASE 0x12480000 -#define GSBI_QUP1_BASE 0x12460000 -#define GSBI_QUP2_BASE 0x124A0000 -#define GSBI_QUP3_BASE 0x16280000 -#define GSBI_QUP4_BASE 0x16380000 -#define GSBI_QUP5_BASE 0x1A280000 -#define GSBI_QUP6_BASE 0x16580000 -#define GSBI_QUP7_BASE 0x16680000 - +#define GSBI1_BASE ((void *)0x12440000) +#define GSBI2_BASE ((void *)0x12480000) +#define GSBI3_BASE ((void *)0x16200000) +#define GSBI4_BASE ((void *)0x16300000) +#define GSBI5_BASE ((void *)0x1A200000) +#define GSBI6_BASE ((void *)0x16500000) +#define GSBI7_BASE ((void *)0x16600000) + +#define GSBI1_CTL_REG (GSBI1_BASE + (0x0)) +#define GSBI2_CTL_REG (GSBI2_BASE + (0x0)) +#define GSBI3_CTL_REG (GSBI3_BASE + (0x0)) +#define GSBI4_CTL_REG (GSBI4_BASE + (0x0)) +#define GSBI5_CTL_REG (GSBI5_BASE + (0x0)) +#define GSBI6_CTL_REG (GSBI6_BASE + (0x0)) +#define GSBI7_CTL_REG (GSBI7_BASE + (0x0)) + +#define GSBI_QUP1_BASE (GSBI1_BASE + 0x20000) +#define GSBI_QUP2_BASE (GSBI2_BASE + 0x20000) +#define GSBI_QUP3_BASE (GSBI3_BASE + 0x80000) +#define GSBI_QUP4_BASE (GSBI4_BASE + 0x80000) +#define GSBI_QUP5_BASE (GSBI5_BASE + 0x80000) +#define GSBI_QUP6_BASE (GSBI6_BASE + 0x80000) +#define GSBI_QUP7_BASE (GSBI7_BASE + 0x80000) + +#define GSBI_CTL_PROTO_I2C 2 +#define GSBI_CTL_PROTO_CODE_SFT 4 +#define GSBI_CTL_PROTO_CODE_MSK 0x7 +#define GSBI_HCLK_CTL_GATE_ENA 6 +#define GSBI_HCLK_CTL_BRANCH_ENA 4 +#define GSBI_QUP_APPS_M_SHFT 16 +#define GSBI_QUP_APPS_M_MASK 0xFF +#define GSBI_QUP_APPS_D_SHFT 0 +#define GSBI_QUP_APPS_D_MASK 0xFF +#define GSBI_QUP_APPS_N_SHFT 16 +#define GSBI_QUP_APPS_N_MASK 0xFF +#define GSBI_QUP_APPS_ROOT_ENA_SFT 11 +#define GSBI_QUP_APPS_BRANCH_ENA_SFT 9 +#define GSBI_QUP_APPS_MNCTR_EN_SFT 8 +#define GSBI_QUP_APPS_MNCTR_MODE_MSK 0x3 +#define GSBI_QUP_APPS_MNCTR_MODE_SFT 5 +#define GSBI_QUP_APPS_PRE_DIV_MSK 0x3 +#define GSBI_QUP_APPS_PRE_DIV_SFT 3 +#define GSBI_QUP_APPS_SRC_SEL_MSK 0x7 + + +#define GSBI_QUP_APSS_MD_REG(gsbi_n) ((MSM_CLK_CTL_BASE + 0x29c8) + \ + (32*(gsbi_n-1))) +#define GSBI_QUP_APSS_NS_REG(gsbi_n) ((MSM_CLK_CTL_BASE + 0x29cc) + \ + (32*(gsbi_n-1))) +#define GSBI_HCLK_CTL(n) ((MSM_CLK_CTL_BASE + 0x29C0) + \ + (32*(n-1))) #endif // __SOC_QUALCOMM_IPQ806X_IOMAP_H_ diff --git a/src/soc/qualcomm/ipq806x/include/soc/qup.h b/src/soc/qualcomm/ipq806x/include/soc/qup.h index 8f6f6bcca9..a12f6c5f86 100644 --- a/src/soc/qualcomm/ipq806x/include/soc/qup.h +++ b/src/soc/qualcomm/ipq806x/include/soc/qup.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2014 - 2015 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 @@ -143,6 +143,7 @@ typedef struct { unsigned clk_frequency; unsigned src_frequency; qup_mode_t mode; + unsigned initialized; } qup_config_t; typedef struct { diff --git a/src/soc/qualcomm/ipq806x/include/soc/spi.h b/src/soc/qualcomm/ipq806x/include/soc/spi.h index f7dda07a51..6d816daf5e 100644 --- a/src/soc/qualcomm/ipq806x/include/soc/spi.h +++ b/src/soc/qualcomm/ipq806x/include/soc/spi.h @@ -7,22 +7,19 @@ #define _IPQ806X_SPI_H_ #include +#include -#define QUP5_BASE 0x1a280000 -#define QUP6_BASE 0x16580000 -#define QUP7_BASE 0x16680000 - -#define GSBI5_BASE 0x1a200000 -#define GSBI6_BASE 0x16500000 -#define GSBI7_BASE 0x16600000 +#define QUP5_BASE ((uint32_t)GSBI_QUP5_BASE) +#define QUP6_BASE ((uint32_t)GSBI_QUP6_BASE) +#define QUP7_BASE ((uint32_t)GSBI_QUP7_BASE) #define GSBI5_QUP5_REG_BASE (QUP5_BASE + 0x00000000) #define GSBI6_QUP6_REG_BASE (QUP6_BASE + 0x00000000) #define GSBI7_QUP7_REG_BASE (QUP7_BASE + 0x00000000) -#define GSBI5_REG_BASE (GSBI5_BASE + 0x00000000) -#define GSBI6_REG_BASE (GSBI6_BASE + 0x00000000) -#define GSBI7_REG_BASE (GSBI7_BASE + 0x00000000) +#define GSBI5_REG_BASE ((uint32_t)(GSBI5_BASE + 0x00000000)) +#define GSBI6_REG_BASE ((uint32_t)(GSBI6_BASE + 0x00000000)) +#define GSBI7_REG_BASE ((uint32_t)(GSBI7_BASE + 0x00000000)) #define BOOT_SPI_PORT5_BASE QUP5_BASE #define BOOT_SPI_PORT6_BASE QUP6_BASE diff --git a/src/soc/qualcomm/ipq806x/qup.c b/src/soc/qualcomm/ipq806x/qup.c index 0ae3990183..72ba724e8b 100644 --- a/src/soc/qualcomm/ipq806x/qup.c +++ b/src/soc/qualcomm/ipq806x/qup.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 The Linux Foundation. All rights reserved. + * Copyright (C) 2014 - 2015 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 @@ -38,13 +38,13 @@ //TODO: refactor the following array to iomap driver. static unsigned gsbi_qup_base[] = { - GSBI_QUP1_BASE, - GSBI_QUP2_BASE, - GSBI_QUP3_BASE, - GSBI_QUP4_BASE, - GSBI_QUP5_BASE, - GSBI_QUP6_BASE, - GSBI_QUP7_BASE, + (unsigned)GSBI_QUP1_BASE, + (unsigned)GSBI_QUP2_BASE, + (unsigned)GSBI_QUP3_BASE, + (unsigned)GSBI_QUP4_BASE, + (unsigned)GSBI_QUP5_BASE, + (unsigned)GSBI_QUP6_BASE, + (unsigned)GSBI_QUP7_BASE, }; #define QUP_ADDR(gsbi_num, reg) ((void *)((gsbi_qup_base[gsbi_num-1]) + (reg))) -- cgit v1.2.3