Merge "mmc: fix for cmd6 failure"
diff --git a/dev/pmic/pm8x41/include/pm8x41.h b/dev/pmic/pm8x41/include/pm8x41.h
new file mode 100644
index 0000000..411a063
--- /dev/null
+++ b/dev/pmic/pm8x41/include/pm8x41.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, 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 "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 _PM8x41_H_
+#define _PM8x41_H_
+
+void pm8x41_set_boot_done();
+
+#endif
diff --git a/dev/pmic/pm8x41/include/pm8x41_hw.h b/dev/pmic/pm8x41/include/pm8x41_hw.h
new file mode 100644
index 0000000..36dd422
--- /dev/null
+++ b/dev/pmic/pm8x41/include/pm8x41_hw.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, 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 "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 _PM8x41_HW_H_
+#define _PM8x41_HW_H_
+
+/* Slave IDs */
+#define PM8x41_SMBB_SLAVE_ID 0
+
+/* Peripheral Base Addresses */
+#define PM8x41_SMBB_PERIPHERAL_ID_BASE 0x1600
+
+/* Register Offsets */
+#define SMBB_MISC_BOOT_DONE 0x42
+#define BOOT_DONE_SHIFT 7
+
+#endif
diff --git a/dev/pmic/pm8x41/pm8x41.c b/dev/pmic/pm8x41/pm8x41.c
new file mode 100644
index 0000000..d3b6cd1
--- /dev/null
+++ b/dev/pmic/pm8x41/pm8x41.c
@@ -0,0 +1,53 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, 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 "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 <spmi.h>
+#include <pm8x41_hw.h>
+
+/* Function to set the boot done flag */
+void pm8x41_set_boot_done()
+{
+ struct pmic_arb_cmd cmd;
+ struct pmic_arb_param param;
+ uint8_t boot_done;
+
+ cmd.address = ((uint16_t)(PM8x41_SMBB_PERIPHERAL_ID_BASE) >> 8);
+ cmd.offset = SMBB_MISC_BOOT_DONE;
+ cmd.priority = 0;
+ cmd.slave_id = PM8x41_SMBB_SLAVE_ID;
+
+ /* Enable the module */
+ boot_done = 1 << BOOT_DONE_SHIFT;
+ param.buffer = &boot_done;
+ param.size = 1;
+
+ pmic_arb_write_cmd(&cmd,¶m);
+
+}
diff --git a/dev/pmic/pm8x41/rules.mk b/dev/pmic/pm8x41/rules.mk
new file mode 100644
index 0000000..1c3bbc1
--- /dev/null
+++ b/dev/pmic/pm8x41/rules.mk
@@ -0,0 +1,6 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+INCLUDES += -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/pm8x41.o
diff --git a/platform/copper/include/platform/iomap.h b/platform/copper/include/platform/iomap.h
index 176cc2c..f29cccd 100644
--- a/platform/copper/include/platform/iomap.h
+++ b/platform/copper/include/platform/iomap.h
@@ -59,8 +59,12 @@
#define MSM_USB_BASE (PERIPH_SS_BASE + 0x00255000)
#define CLK_CTL_BASE 0xFC400000
-#define TLMM_BASE_ADDR 0xFD500000
+#define SPMI_BASE 0xFC4C0000
+#define SPMI_GENI_BASE (SPMI_BASE + 0xA000)
+#define SPMI_PIC_BASE (SPMI_BASE + 0xB000)
+
+#define TLMM_BASE_ADDR 0xFD500000
#define GPIO_CONFIG_ADDR(x) (TLMM_BASE_ADDR + 0x1000 + (x)*0x10)
#define GPIO_IN_OUT_ADDR(x) (TLMM_BASE_ADDR + 0x1004 + (x)*0x10)
diff --git a/platform/copper/include/platform/irqs.h b/platform/copper/include/platform/irqs.h
index 2f162b8..909c2c5 100644
--- a/platform/copper/include/platform/irqs.h
+++ b/platform/copper/include/platform/irqs.h
@@ -53,6 +53,8 @@
/* Retrofit universal macro names */
#define INT_USB_HS USB1_HS_IRQ
+#define EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ (GIC_SPI_START + 190)
+
#define NR_MSM_IRQS 256
#define NR_GPIO_IRQS 173
#define NR_BOARD_IRQS 0
diff --git a/platform/msm8960/gpio.c b/platform/msm8960/gpio.c
index 7b3f808..c185ca6 100644
--- a/platform/msm8960/gpio.c
+++ b/platform/msm8960/gpio.c
@@ -129,6 +129,15 @@
GPIO_8MA, GPIO_DISABLE);
break;
+ case GSBI_ID_8:
+ /* configure rx gpio */
+ gpio_tlmm_config(35, 1, GPIO_INPUT, GPIO_NO_PULL,
+ GPIO_8MA, GPIO_DISABLE);
+ /* configure tx gpio */
+ gpio_tlmm_config(34, 1, GPIO_OUTPUT, GPIO_NO_PULL,
+ GPIO_8MA, GPIO_DISABLE);
+ break;
+
default:
ASSERT(0);
}
diff --git a/platform/msm_shared/include/spmi.h b/platform/msm_shared/include/spmi.h
new file mode 100644
index 0000000..d6a0b74
--- /dev/null
+++ b/platform/msm_shared/include/spmi.h
@@ -0,0 +1,140 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, 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 "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 __SPMI_H
+#define __SPMI_H
+
+#define SPMI_MSM8974_MASTER_ID 0
+
+#define SPMI_GENI_REG(x) (SPMI_GENI_BASE + (x))
+#define SPMI_GENI_CFG_REG_BASE SPMI_GENI_REG(0x100)
+#define SPMI_GENI_CFG_RAM_BASE SPMI_GENI_REG(0x200)
+
+#define SPMI_GENI_CFG_REGn(x) (SPMI_GENI_CFG_REG_BASE + 4 * (x))
+#define SPMI_GENI_CFG_RAM_REGn(x) (SPMI_GENI_CFG_RAM_BASE + 4 * (x))
+
+#define SPMI_GENI_CLK_CTRL_REG SPMI_GENI_REG(0x00)
+#define SPMI_GENI_OUTPUT_CTRL_REG SPMI_GENI_REG(0x10)
+#define SPMI_GENI_FORCE_DEFAULT_REG SPMI_GENI_REG(0x0C)
+#define SPMI_MID_REG SPMI_GENI_REG(0xF00)
+#define SPMI_CFG_REG SPMI_GENI_REG(0xF04)
+#define SPMI_SEC_DISABLE_REG SPMI_GENI_REG(0xF08)
+
+#define SPMI_GENI_IRQ_ENABLE (SPMI_GENI_BASE + 0x24)
+#define SPMI_GENI_IRQ_CLEAR (SPMI_GENI_BASE + 0x28)
+#define SPMI_GENI_TX_FIFO_BASE (SPMI_GENI_BASE + 0x40)
+#define SPMI_GENI_RX_FIFO_BASE (SPMI_GENI_BASE + 0x80)
+
+#define SPMI_GENI_TX_FIFOn(x) (SPMI_GENI_TX_FIFO_BASE + 4 * (x))
+#define SPMI_GENI_RX_FIFOn(x) (SPMI_GENI_RX_FIFO_BASE + 4 * (x))
+
+#define PMIC_ARB_CHNLn_CMD0(x) (SPMI_BASE + 0xF800 + (x) * 0x80)
+#define PMIC_ARB_CMD_OPCODE_SHIFT 27
+#define PMIC_ARB_CMD_PRIORITY_SHIFT 26
+#define PMIC_ARB_CMD_SLAVE_ID_SHIFT 20
+#define PMIC_ARB_CMD_ADDR_SHIFT 12
+#define PMIC_ARB_CMD_ADDR_OFFSET_SHIFT 4
+#define PMIC_ARB_CMD_BYTE_CNT_SHIFT 0
+
+#define PMIC_ARB_CHNLn_CONFIG(x) (SPMI_BASE + 0xF804 + (x) * 0x80)
+#define PMIC_ARB_CHNLn_STATUS(x) (SPMI_BASE + 0xF808 + (x) * 0x80)
+#define PMIC_ARB_CHNLn_WDATA(x, n) (SPMI_BASE + 0xF810 + \
+ (x) * 0x80 + (n) * 4)
+#define PMIC_ARB_CHNLn_RDATA(x,n) (SPMI_BASE + 0xF818 + \
+ (x) * 0x80 + (n) * 4)
+
+/* PIC Registers */
+#define SPMI_PIC_OWNERm_ACC_STATUSn(m, n) (SPMI_PIC_BASE + 32 * (m) + 4 * (n))
+#define SPMI_PIC_ACC_ENABLEn(n) (SPMI_PIC_BASE + 0x200 + 4 * (n))
+#define SPMI_PIC_IRQ_STATUSn(n) (SPMI_PIC_BASE + 0x600 + 0x4 * (n))
+#define SPMI_PIC_IRQ_CLEARn(n) (SPMI_PIC_BASE + 0xA00 + 0x4 * (n))
+
+/* SPMI Commands */
+#define SPMI_CMD_EXT_REG_WRTIE_LONG 0x00
+#define SPMI_CMD_EXT_REG_READ_LONG 0x01
+#define SPMI_CMD_EXT_REG_READ_LONG_DELAYED 0x02
+#define SPMI_CMD_TRANSFER_BUS_OWNERSHIP 0x03
+
+/* The commands below are not yet supported */
+#define SPMI_CMD_RESET 0x04
+#define SPMI_CMD_SLEEP 0x05
+#define SPMI_CMD_SHUTDOWN 0x06
+#define SPMI_CMD_WAKEUP 0x07
+#define SPMI_CMD_EXT_REG_WRITE 0x08
+#define SPMI_CMD_EXT_REG_READ 0x09
+#define SPMI_CMD_REG_WRITE 0x0A
+#define SPMI_CMD_REG_READ 0x0B
+#define SPMI_CMD_REG_0_WRITE 0x0C
+#define SPMI_CMD_AUTH 0x0D
+#define SPMI_CMD_MASTER_WRITE 0x0E
+#define SPMI_CMD_MASTER_READ 0x0F
+#define SPMI_CMD_DEV_DESC_BLK_MASTER_READ 0x10
+#define SPMI_CMD_DEV_DESC_BLK_SLAVE_READ 0x11
+
+enum spmi_geni_cmd_return_value{
+ SPMI_CMD_DONE,
+ SMPI_CMD_DENIED,
+ SPMI_CMD_FAILURE,
+ SPMI_ILLEGAL_CMD,
+ SPMI_CMD_OVERRUN = 6,
+ SPMI_TX_FIFO_RD_ERR,
+ SPMI_TX_FIFO_WR_ERR,
+ SPMI_RX_FIFO_RD_ERR,
+ SPMI_RX_FIFO_WR_ERR
+};
+
+enum pmic_arb_chnl_return_values{
+ PMIC_ARB_CMD_DONE,
+ PMIC_ARB_CMD_FAILURE,
+ PMIC_ARB_CMD_DENIED,
+ PMIC_ARB_CMD_DROPPED,
+};
+
+struct pmic_arb_cmd{
+ uint8_t opcode;
+ uint8_t priority;
+ uint8_t slave_id;
+ uint8_t address;
+ uint8_t offset;
+ uint8_t byte_cnt;
+};
+
+struct pmic_arb_param{
+ uint8_t *buffer;
+ uint8_t size;
+};
+
+typedef void (*spmi_callback)();
+
+void spmi_init(uint32_t, uint32_t);
+unsigned int pmic_arb_write_cmd(struct pmic_arb_cmd *cmd,
+ struct pmic_arb_param *param);
+unsigned int pmic_arb_read_cmd(struct pmic_arb_cmd *cmd,
+ struct pmic_arb_param *param);
+
+#endif
diff --git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk
index 8abd230..a7f6c93 100644
--- a/platform/msm_shared/rules.mk
+++ b/platform/msm_shared/rules.mk
@@ -65,7 +65,8 @@
$(LOCAL_DIR)/clock.o \
$(LOCAL_DIR)/clock_pll.o \
$(LOCAL_DIR)/clock_lib2.o \
- $(LOCAL_DIR)/uart_dm.o
+ $(LOCAL_DIR)/uart_dm.o \
+ $(LOCAL_DIR)/spmi.o
endif
ifeq ($(PLATFORM),msm7x27a)
diff --git a/platform/msm_shared/spmi.c b/platform/msm_shared/spmi.c
new file mode 100644
index 0000000..b361a30
--- /dev/null
+++ b/platform/msm_shared/spmi.c
@@ -0,0 +1,317 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, 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 "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 <spmi.h>
+#include <platform/iomap.h>
+#include <platform/irqs.h>
+#include <platform/interrupts.h>
+
+static uint32_t pmic_arb_chnl_num;
+static uint32_t pmic_arb_owner_id;
+static uint8_t pmic_irq_perph_id;
+static spmi_callback callback;
+
+/* Function to initialize SPMI controller.
+ * chnl_num : Channel number to be used by this EE.
+ */
+void spmi_init(uint32_t chnl_num, uint32_t owner_id)
+{
+ /* Initialize PMIC Arbiter Channel Number */
+ pmic_arb_chnl_num = chnl_num;
+ pmic_arb_owner_id = owner_id;
+}
+
+static void write_wdata_from_array(uint8_t *array,
+ uint8_t reg_num,
+ uint8_t array_size,
+ uint8_t* bytes_written)
+{
+ uint32_t shift_value[] = {0, 8, 16, 24};
+ int i;
+ int j;
+ uint32_t val = 0;
+
+ /* Write to WDATA */
+ for (i = 0; (*bytes_written < array_size) && (i < 4); i++)
+ {
+ val |= (uint32_t)(array[*bytes_written]) << shift_value[i];
+ (*bytes_written)++;
+ }
+
+ writel(val, PMIC_ARB_CHNLn_WDATA(pmic_arb_chnl_num, reg_num));
+}
+
+
+/* Initiate a write cmd by writing to cmd register.
+ * Commands are written according to cmd parameters
+ * cmd->opcode : SPMI opcode for the command
+ * cmd->priority : Priority of the command
+ * High priority : 1
+ * Low Priority : 0
+ * cmd->address : SPMI Peripheral Address.
+ * cmd->offset : Offset Address for the command.
+ * cmd->bytecnt : Number of bytes to be written.
+ *
+ * param is the parameter to the command
+ * param->buffer : Value to be written
+ * param->size : Size of the buffer.
+ *
+ * return value : 0 if success, the error bit set on error
+ */
+unsigned int pmic_arb_write_cmd(struct pmic_arb_cmd *cmd,
+ struct pmic_arb_param *param)
+{
+ uint32_t bytes_written = 0;
+ uint32_t error;
+ uint32_t val = 0;
+
+ /* Disable IRQ mode for the current channel*/
+ writel(0x0, PMIC_ARB_CHNLn_CONFIG(pmic_arb_chnl_num));
+
+ /* Write parameters for the cmd */
+ if (cmd == NULL)
+ {
+ dprintf(CRITICAL,"PMIC arbiter error, no command provided\n");
+ return 1;
+ }
+
+ /* Write the data bytes according to the param->size
+ * Can write upto 8 bytes.
+ */
+
+ /* Write first 4 bytes to WDATA0 */
+ write_wdata_from_array(param->buffer, 0, param->size, &bytes_written);
+
+ if (bytes_written < param->size)
+ {
+ /* Write next 4 bytes to WDATA1 */
+ write_wdata_from_array(param->buffer, 1, param->size, &bytes_written);
+ }
+
+ /* Fill in the byte count for the command
+ * Note: Byte count is one less than the number of bytes transferred.
+ */
+ cmd->byte_cnt = param->size - 1;
+ /* Fill in the Write cmd opcode. */
+ cmd->opcode = SPMI_CMD_EXT_REG_WRTIE_LONG;
+
+ /* Write the command */
+ val = 0;
+ val |= ((uint32_t)(cmd->opcode) << PMIC_ARB_CMD_OPCODE_SHIFT);
+ val |= ((uint32_t)(cmd->priority) << PMIC_ARB_CMD_PRIORITY_SHIFT);
+ val |= ((uint32_t)(cmd->slave_id) << PMIC_ARB_CMD_SLAVE_ID_SHIFT);
+ val |= ((uint32_t)(cmd->address) << PMIC_ARB_CMD_ADDR_SHIFT);
+ val |= ((uint32_t)(cmd->offset) << PMIC_ARB_CMD_ADDR_OFFSET_SHIFT);
+ val |= ((uint32_t)(cmd->byte_cnt));
+
+ writel(val, PMIC_ARB_CHNLn_CMD0(pmic_arb_chnl_num));
+
+ /* Wait till CMD DONE status */
+ while (!(val = readl(PMIC_ARB_CHNLn_STATUS(pmic_arb_chnl_num))));
+
+ /* Check for errors */
+ error = val ^ (1 << PMIC_ARB_CMD_DONE);
+ if (error)
+ {
+ dprintf(CRITICAL, "SPMI write command failure: \
+ cmd_id = %u, error = %u\n", cmd->opcode, error);
+ return error;
+ }
+ else
+ return 0;
+}
+
+static void read_rdata_into_array(uint8_t *array,
+ uint8_t reg_num,
+ uint8_t array_size,
+ uint8_t* bytes_read)
+{
+ uint32_t val = 0;
+ uint32_t mask_value[] = {0xFF, 0xFF00, 0xFF0000, 0xFF000000};
+ uint8_t shift_value[] = {0, 8, 16, 24};
+ int i;
+
+ val = readl(PMIC_ARB_CHNLn_RDATA(pmic_arb_chnl_num, reg_num));
+
+ /* Read at most 4 bytes */
+ for (i = 0; (i < 4) && (*bytes_read < array_size); i++)
+ {
+ array[*bytes_read] = (val & mask_value[i]) >> shift_value[i];
+ (*bytes_read)++;
+ }
+}
+
+/* Initiate a read cmd by writing to cmd register.
+ * Commands are written according to cmd parameters
+ * cmd->opcode : SPMI opcode for the command
+ * cmd->priority : Priority of the command
+ * High priority : 1
+ * Low Priority : 0
+ * cmd->address : SPMI Peripheral Address.
+ * cmd->offset : Offset Address for the command.
+ * cmd->bytecnt : Number of bytes to be read.
+ *
+ * param is the buffer to the save command data.
+ * param->buffer : Buffer to store the bytes returned.
+ * param->size : Size of the buffer.
+ *
+ * return value : 0 if success, the error bit set on error
+ */
+unsigned int pmic_arb_read_cmd(struct pmic_arb_cmd *cmd,
+ struct pmic_arb_param *param)
+{
+ uint32_t val = 0;
+ uint32_t error;
+ uint32_t addr;
+ uint8_t bytes_read = 0;
+
+ /* Disable IRQ mode for the current channel*/
+ writel(0x0, PMIC_ARB_CHNLn_CONFIG(pmic_arb_chnl_num));
+
+ /* Fill in the byte count for the command
+ * Note: Byte count is one less than the number of bytes transferred.
+ */
+ cmd->byte_cnt = param->size - 1;
+ /* Fill in the Write cmd opcode. */
+ cmd->opcode = SPMI_CMD_EXT_REG_READ_LONG;
+
+ val |= ((uint32_t)(cmd->opcode) << PMIC_ARB_CMD_OPCODE_SHIFT);
+ val |= ((uint32_t)(cmd->priority) << PMIC_ARB_CMD_PRIORITY_SHIFT);
+ val |= ((uint32_t)(cmd->slave_id) << PMIC_ARB_CMD_SLAVE_ID_SHIFT);
+ val |= ((uint32_t)(cmd->address) << PMIC_ARB_CMD_ADDR_SHIFT);
+ val |= ((uint32_t)(cmd->offset) << PMIC_ARB_CMD_ADDR_OFFSET_SHIFT);
+ val |= ((uint32_t)(cmd->byte_cnt));
+
+ writel(val, PMIC_ARB_CHNLn_CMD0(pmic_arb_chnl_num));
+
+ /* Wait till CMD DONE status */
+ while (!(val = readl(PMIC_ARB_CHNLn_STATUS(pmic_arb_chnl_num))));
+
+ /* Check for errors */
+ error = val ^ (1 << PMIC_ARB_CMD_DONE);
+
+ if (error)
+ {
+ dprintf(CRITICAL, "SPMI read command failure: \
+ cmd_id = %u, error = %u\n", cmd->opcode, error);
+ return error;
+ }
+
+ /* Read the RDATA0 */
+ read_rdata_into_array(param->buffer, 0, param->size , &bytes_read);
+
+ if (bytes_read < param->size)
+ {
+ /* Read the RDATA1 */
+ read_rdata_into_array(param->buffer, 1, param->size , &bytes_read);
+
+ }
+
+ if (bytes_read < param->size)
+ {
+ /* Read the RDATA2 */
+ read_rdata_into_array(param->buffer, 2, param->size , &bytes_read);
+
+ }
+
+ return 0;
+}
+
+
+/* Funtion to determine if the peripheral that caused the interrupt
+ * is of interest.
+ * Also handles callback function and interrupt clearing if the
+ * correct interrupt is fired.
+ * periph_acc_irq: SPMI_PIC_OWNERm_ACC_STATUSn register id.
+ * status: Bits of the periph_acc_irq.
+ * return 1 if the peripheral is of interest,
+ * 0 otherwise.
+ */
+int spmi_acc_irq(uint32_t periph_acc_irq, uint32_t status)
+{
+ uint8_t reg_id;
+ uint8_t offset;
+
+ /* Narrow down the correct register for the peripheral*/
+ reg_id = pmic_irq_perph_id / 32;
+ if (periph_acc_irq * 8 != reg_id)
+ return 0;
+
+ /* Narrow down the correct interrupt within the register */
+ offset = pmic_irq_perph_id & 31;
+ if ((status & offset))
+ {
+ /* Clear the interrupt */
+ writel(offset ^ status, SPMI_PIC_IRQ_CLEARn(reg_id));
+
+ /* Confirm that the interrupt has been cleared */
+ while(readl(SPMI_PIC_IRQ_STATUSn(reg_id)) & offset);
+
+ /* Call the callback */
+ callback();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void spmi_irq()
+{
+ int i;
+ uint32_t status;
+
+ /* Go through the Peripheral list to figure out the periperal
+ * that caused the interrupt
+ */
+ for (i = 0; i < 8; i++)
+ {
+ status = readl(SPMI_PIC_OWNERm_ACC_STATUSn(pmic_arb_owner_id, i));
+ if (status)
+ if (!spmi_acc_irq(i, status))
+ /* Not the correct interrupt, continue to wait */
+ return;
+ }
+ mask_interrupt(EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ);
+}
+
+/* Enable interrupts on a particular peripheral: periph_id */
+void spmi_enable_periph_interrupts(uint8_t periph_id)
+{
+ pmic_irq_perph_id = periph_id;
+
+ register_int_handler(EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ , spmi_irq, 0);
+ unmask_interrupt(EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ);
+
+}
+
+void spmi_uninit()
+{
+ mask_interrupt(EE0_KRAIT_HLOS_SPMI_PERIPH_IRQ);
+}
diff --git a/target/copper/init.c b/target/copper/init.c
index 2630ad1..a2f3f14 100644
--- a/target/copper/init.c
+++ b/target/copper/init.c
@@ -35,13 +35,17 @@
#include <platform.h>
#include <uart_dm.h>
#include <mmc.h>
+#include <spmi.h>
+
static unsigned int target_id;
-extern void dmb(void);
static void target_detect(void);
-#define COPPER_TARGET_ID 3999
+#define COPPER_TARGET_ID 0xffffffff
+#define PMIC_ARB_CHANNEL_NUM 0
+#define PMIC_ARB_OWNER_ID 0
+
static uint32_t mmc_sdc_base[] =
{ MSM_SDC1_BASE, MSM_SDC2_BASE, MSM_SDC3_BASE, MSM_SDC4_BASE };
@@ -60,6 +64,7 @@
dprintf(INFO, "target_init()\n");
target_id = COPPER_TARGET_ID;
+ spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
/* Trying Slot 1*/
slot = 1;
diff --git a/target/copper/rules.mk b/target/copper/rules.mk
index b6eba33..0f6a21f 100644
--- a/target/copper/rules.mk
+++ b/target/copper/rules.mk
@@ -16,7 +16,8 @@
MODULES += \
dev/keys \
- lib/ptable
+ lib/ptable \
+ dev/pmic/pm8x41
DEFINES += \
MEMSIZE=$(MEMSIZE) \
diff --git a/target/msm8960/init.c b/target/msm8960/init.c
index b803f32..c87652a 100644
--- a/target/msm8960/init.c
+++ b/target/msm8960/init.c
@@ -255,7 +255,14 @@
case LINUX_MACHTYPE_8960_APQ:
case LINUX_MACHTYPE_8960_LIQUID:
- uart_dm_init(5, 0x16400000, 0x16440000);
+ if(board_baseband() == BASEBAND_SGLTE)
+ {
+ uart_dm_init(8, 0x1A000000, 0x1A040000);;
+ }
+ else
+ {
+ uart_dm_init(5, 0x16400000, 0x16440000);
+ }
break;
case LINUX_MACHTYPE_8930_CDP: