Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7dceff4 authored by Rohit Vaswani's avatar Rohit Vaswani
Browse files

ssbi: Add geni ssbi arbiter changes



These changes are needed to support new geni ssbi arbiter.

Change-Id: Id348e20e131ffba1fd8259b3b89b078dfa9d9ca2
Acked-by: default avatarKaushik Sikdar <ksikdar@qti.qualcomm.com>
Signed-off-by: default avatarRohit Vaswani <rvaswani@codeaurora.org>
parent 4b9914c9
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -10,9 +10,9 @@ These require the following properties:

- qcom,controller-type
  indicates the SSBI bus variant the controller should use to talk
  with the slave device.  This should be one of "ssbi", "ssbi2", or
  "pmic-arbiter".  The type chosen is determined by the attached
  slave.
  with the slave device.  This should be one of "ssbi", "ssbi2",
  "pmic-arbiter", "geni-ssbi-arbiter" or "geni-ssbi2-arbiter".
  The type chosen is determined by the attached slave.

The slave device should be the single child node of the ssbi device
with a compatible field.
+229 −3
Original line number Diff line number Diff line
@@ -65,6 +65,88 @@

#define SSBI_TIMEOUT_US			100

/* GENI SSBI Arbiter command registers */
#define  GENI_SSBI_ARB_CHNL_CMD		0x3800
#define  GENI_SSBI_ARB_CHNL_CONFIG	0x3804
#define  GENI_SSBI_ARB_CHNL_STATUS	0x3808
#define  GENI_SSBI_ARB_CHNL_WDATA0	0x3810
#define  GENI_SSBI_ARB_CHNL_WDATA1	0x3814
#define  GENI_SSBI_ARB_CHNL_RDATA0	0x3818
#define  GENI_SSBI_ARB_CHNL_RDATA1	0x381C

/* GENI SSBI Arbiter CMD fields */
#define GENI_SSBI_CMD_WR		(0 << 27)
#define GENI_SSBI_CMD_RD		(1 << 27)
#define GENI_SSBI2_CMD_WR		(2 << 27)
#define GENI_SSBI2_CMD_RD		(3 << 27)

/* GENI SSBI ARB STATUS fields */
#define GENI_SSBI_STATUS_TRANS_DONE	1
#define GENI_SSBI_STATUS_TRANS_FAILURE  2
#define GENI_SSBI_STATUS_TRANS_DENIED	4
#define GENI_SSBI_STATUS_TRANS_DROPPED	8

#define SSBI_GSA_CMD_ADDR_MASK		0x7fff /* REG_ADDR_7_0, REG_ADDR_8_14*/

#define GENI_OFFSET			  0x4000
#define GENI_CFG_REG0_ADDR		  0x100
#define GENI_RAM_ADDR			  0x200

#define GENI_CLK_CONTROL_ADDR		  0x0
#define GENI_FW_REVISION_ADDR		  0x8
#define GENI_S_FW_REVISION_ADDR		  0xC
#define GENI_FORCE_DEFAULT_REG_ADDR       0x10
#define GENI_OUTPUT_CONTROL_ADDR	  0x14
#define GENI_SER_CLK_CFG_ADDR		  0x34
#define GENI_ARB_MISC_CONFIG_ADDR	  0x3004
#define GENI_ARB_CHNL_CONFIG_ADDDR	  0x3804
#define GENI_FW_VERSION			  0x00000140
#define GENI_DEFAULT			  0x00000001
#define GENI_SOE0_EN			  0x00000001
#define GENI_SER_CLK			  0x00000001
#define GENI_IRQ_DONE			  0x00000001
#define GENI_IRQ_EN			  0x00000001
#define GENI_CLK_SET			  0x00004006
#define GENI_CFG_SIZE			  31
#define GENI_RAM_SIZE			  25
#define GENI_MAX_CHNL			  5

int mode_1_cfg_array[GENI_CFG_SIZE] = {
	0x00004879, 0x0001F178, 0x0000FEEE, 0x00000000, 0x00000000,
	0x108802A8, 0x00000110, 0x00280000, 0x0000001F, 0x000000FF,
	0x00000000, 0x00554515, 0x00555555, 0x00000000, 0x00000000,
	0x001800A4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000001, 0x00000020, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000
};

int mode_1_ram_array[GENI_RAM_SIZE] = {
	0x0000000f, 0x00000000, 0x00014201, 0x001E4880, 0x0001B203,
	0x001E4880, 0x00024201, 0x001E4880, 0x0002D203, 0x001E4880,
	0x00040008, 0x000A2216, 0x00142E08, 0x00040008, 0x000A221C,
	0x0004601A, 0x00005E00, 0x00101000, 0x00041210, 0x000A2226,
	0x00041017, 0x00101000, 0x00001200, 0x0008201C, 0x00000000
};

int mode_2_cfg_array[GENI_CFG_SIZE] = {
	0x00004879, 0x00027978, 0x0000FEEE, 0x00000000, 0x00000000,
	0x108802A8, 0x00000110, 0x00280000, 0x0000001F, 0x000000FF,
	0x00000000, 0x00554515, 0x00555555, 0x00000000, 0x00000000,
	0x001800A4, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000001, 0x00000020, 0x00000000, 0x00000000, 0x00000000,
	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
	0x00000000
};

int mode_2_ram_array[GENI_RAM_SIZE] = {
	0x0000000f, 0x00000000, 0x00014201, 0x001E48C0, 0x0002D203,
	0x001E48C0, 0x00024201, 0x001E48C0, 0x0002D203, 0x001E48C0,
	0x00040008, 0x000A2216, 0x00142E08, 0x00040008, 0x000A221C,
	0x0004601A, 0x00005E00, 0x00101000, 0x00041210, 0x000A2226,
	0x00041017, 0x00101000, 0x00001200, 0x0008201C, 0x00000000
};

struct ssbi {
	struct device		*slave;
	void __iomem		*base;
@@ -78,12 +160,12 @@ struct ssbi {

static inline u32 ssbi_readl(struct ssbi *ssbi, u32 reg)
{
	return readl(ssbi->base + reg);
	return readl_relaxed(ssbi->base + reg);
}

static inline void ssbi_writel(struct ssbi *ssbi, u32 val, u32 reg)
{
	writel(val, ssbi->base + reg);
	writel_relaxed(val, ssbi->base + reg);
}

/*
@@ -235,6 +317,85 @@ err:
	return ret;
}

static inline int
ssbi_gsa_transfer(struct ssbi *ssbi, u32 cmd, u8 *data)
{
	u32 timeout = SSBI_TIMEOUT_US;
	u32 rd_status = 0;

	ssbi_writel(ssbi, cmd, GENI_SSBI_ARB_CHNL_CMD);

	while (timeout--) {
		rd_status = ssbi_readl(ssbi, GENI_SSBI_ARB_CHNL_STATUS);

		if (rd_status & GENI_SSBI_STATUS_TRANS_DENIED)
			return -EPERM;

		if (rd_status & GENI_SSBI_STATUS_TRANS_FAILURE)
			return -EPERM;

		if (rd_status & GENI_SSBI_STATUS_TRANS_DROPPED)
			return -EPERM;

		if (rd_status & GENI_SSBI_STATUS_TRANS_DONE) {
			if (data)
				*data = ssbi_readl(ssbi,
					GENI_SSBI_ARB_CHNL_RDATA0) & 0xff;
			return 0;
		}
		udelay(1);
	}

	return -ETIMEDOUT;
}

static int
ssbi_gsa_read_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
{
	u32 cmd;
	int ret = 0;

	if (ssbi->controller_type == FSM_SBI_CTRL_GENI_SSBI2_ARBITER)
		cmd = GENI_SSBI2_CMD_RD | (addr & SSBI_GSA_CMD_ADDR_MASK) << 8;
	else
		cmd = GENI_SSBI_CMD_RD | (addr & SSBI_GSA_CMD_ADDR_MASK) << 8;

	while (len) {
		ret = ssbi_gsa_transfer(ssbi, cmd, buf);
		if (ret)
			goto err;
		buf++;
		len--;
	}

err:
	return ret;
}

static int
ssbi_gsa_write_bytes(struct ssbi *ssbi, u16 addr, u8 *buf, int len)
{
	u32 cmd;
	int ret = 0;

	while (len) {
		if (ssbi->controller_type == FSM_SBI_CTRL_GENI_SSBI2_ARBITER)
			cmd = GENI_SSBI2_CMD_RD |
				(addr & SSBI_GSA_CMD_ADDR_MASK) << 8 | *buf;
		else
			cmd = (addr & SSBI_GSA_CMD_ADDR_MASK) << 8 | *buf;

		ret = ssbi_gsa_transfer(ssbi, cmd, NULL);
		if (ret)
			goto err;
		buf++;
		len--;
	}

err:
	return ret;
}

int ssbi_read(struct device *dev, u16 addr, u8 *buf, int len)
{
	struct ssbi *ssbi = to_ssbi(dev);
@@ -263,6 +424,60 @@ int ssbi_write(struct device *dev, u16 addr, u8 *buf, int len)
}
EXPORT_SYMBOL_GPL(ssbi_write);

static void  set_ssbi_mode_2(void __iomem *geni_offset)
{
	int i;

	writel_relaxed(GENI_FW_VERSION, geni_offset + GENI_FW_REVISION_ADDR);
	writel_relaxed(GENI_FW_VERSION, geni_offset + GENI_S_FW_REVISION_ADDR);

	for (i = 0; i < GENI_CFG_SIZE; i++)
		writel_relaxed(mode_2_cfg_array[i], geni_offset +
			GENI_CFG_REG0_ADDR + 4 * i);

	for (i = 0; i < GENI_RAM_SIZE; i++)
		writel_relaxed(mode_2_ram_array[i], geni_offset +
			GENI_RAM_ADDR + 4 * i);

	writel_relaxed(GENI_DEFAULT, geni_offset + GENI_FORCE_DEFAULT_REG_ADDR);
	writel_relaxed(GENI_SOE0_EN, geni_offset + GENI_OUTPUT_CONTROL_ADDR);
	writel_relaxed(GENI_SER_CLK, geni_offset + GENI_CLK_CONTROL_ADDR);
	writel_relaxed(GENI_CLK_SET, geni_offset + GENI_SER_CLK_CFG_ADDR);

	writel_relaxed(GENI_IRQ_DONE, geni_offset + GENI_ARB_MISC_CONFIG_ADDR);

	for (i = 0; i < GENI_MAX_CHNL; i++)
		writel_relaxed(GENI_IRQ_EN, geni_offset +
			GENI_ARB_CHNL_CONFIG_ADDDR + 4 * i);
}

static void  set_ssbi_mode_1(void __iomem *geni_offset)
{
	int i;

	writel_relaxed(GENI_FW_VERSION, geni_offset + GENI_FW_REVISION_ADDR);
	writel_relaxed(GENI_FW_VERSION, geni_offset + GENI_S_FW_REVISION_ADDR);

	for (i = 0; i < GENI_CFG_SIZE; i++)
		writel_relaxed(mode_1_cfg_array[i], geni_offset +
			GENI_CFG_REG0_ADDR + 4 * i);

	for (i = 0; i < GENI_RAM_SIZE; i++)
		writel_relaxed(mode_1_ram_array[i], geni_offset +
			GENI_RAM_ADDR + 4 * i);

	writel_relaxed(GENI_DEFAULT, geni_offset + GENI_FORCE_DEFAULT_REG_ADDR);
	writel_relaxed(GENI_SOE0_EN, geni_offset + GENI_OUTPUT_CONTROL_ADDR);
	writel_relaxed(GENI_SER_CLK, geni_offset + GENI_CLK_CONTROL_ADDR);
	writel_relaxed(GENI_CLK_SET, geni_offset + GENI_SER_CLK_CFG_ADDR);

	writel_relaxed(GENI_IRQ_DONE, geni_offset + GENI_ARB_MISC_CONFIG_ADDR);

	for (i = 0; i < GENI_MAX_CHNL; i++)
		writel_relaxed(GENI_IRQ_EN, geni_offset +
			GENI_ARB_CHNL_CONFIG_ADDDR + 4 * i);
}

static int ssbi_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
@@ -290,6 +505,7 @@ static int ssbi_probe(struct platform_device *pdev)
		ret = -EINVAL;
		goto err_ioremap;
	}

	platform_set_drvdata(pdev, ssbi);

	type = of_get_property(np, "qcom,controller-type", NULL);
@@ -305,7 +521,13 @@ static int ssbi_probe(struct platform_device *pdev)
		ssbi->controller_type = MSM_SBI_CTRL_SSBI2;
	else if (strcmp(type, "pmic-arbiter") == 0)
		ssbi->controller_type = MSM_SBI_CTRL_PMIC_ARBITER;
	else {
	else if (strcmp(type, "geni-ssbi-arbiter") == 0) {
		ssbi->controller_type = FSM_SBI_CTRL_GENI_SSBI_ARBITER;
		set_ssbi_mode_1(ssbi->base);
	} else if (strcmp(type, "geni-ssbi2-arbiter") == 0) {
		ssbi->controller_type = FSM_SBI_CTRL_GENI_SSBI2_ARBITER;
		set_ssbi_mode_2(ssbi->base);
	} else {
		pr_err("Unknown qcom,controller-type\n");
		ret = -EINVAL;
		goto err_ssbi_controller;
@@ -314,6 +536,10 @@ static int ssbi_probe(struct platform_device *pdev)
	if (ssbi->controller_type == MSM_SBI_CTRL_PMIC_ARBITER) {
		ssbi->read = ssbi_pa_read_bytes;
		ssbi->write = ssbi_pa_write_bytes;
	} else if ((ssbi->controller_type == FSM_SBI_CTRL_GENI_SSBI_ARBITER) ||
		(ssbi->controller_type == FSM_SBI_CTRL_GENI_SSBI2_ARBITER)) {
		ssbi->read = ssbi_gsa_read_bytes;
		ssbi->write = ssbi_gsa_write_bytes;
	} else {
		ssbi->read = ssbi_read_bytes;
		ssbi->write = ssbi_write_bytes;
+3 −1
Original line number Diff line number Diff line
/* Copyright (C) 2010 Google, Inc.
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (c) 2011,2013, Code Aurora Forum. All rights reserved.
 * Author: Dima Zavin <dima@android.com>
 *
 * This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,8 @@ enum ssbi_controller_type {
	MSM_SBI_CTRL_SSBI = 0,
	MSM_SBI_CTRL_SSBI2,
	MSM_SBI_CTRL_PMIC_ARBITER,
	FSM_SBI_CTRL_GENI_SSBI_ARBITER,
	FSM_SBI_CTRL_GENI_SSBI2_ARBITER,
};

struct ssbi_platform_data {