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

Commit 3aa31230 authored by Asish Bhattacharya's avatar Asish Bhattacharya Committed by Laxminath Kasam
Browse files

avtimer: msm: allow driver to register to SSR framework



Sub System Restart[SSR] framework allows driver to handle
unexpected crash in middle of operation.
Also, adding support clk_div dtsi entry to calculate
avtimer_lsw value.

CRs-Fixed: 689849
Change-Id: I521e3c010dadd00a06a0fe8998a1759b2eb81b55
Signed-off-by: default avatarLaxminath Kasam <lkasam@codeaurora.org>
parent 548e7c28
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -12,10 +12,15 @@ Required properties:
  "avtimer_msb_addr" : AVtimer msb physical address
- compatible : Must be "qcom,avtimer"

Optional properties:
- clk_div : For 8916 the clk is at 27MHz and hence ticks are to be
 divided by 27 to achive the msec value.

Example:
	qcom,avtimer {
		compatible = "qcom,avtimer";
		reg = <0xfe053008 0x4>,
			<0xfe05300c 0x4>;
		reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
		qcom,clk_div = <27>;
	};
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
#include <linux/io.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/avtimer.h>
#include <linux/avtimer_kernel.h>
#include <media/v4l2-subdev.h>
#include <media/msmb_isp.h>
#include <linux/msm-bus.h>
+48 −5
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.

* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,8 @@
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/qdsp6v2/apr.h>
#include <soc/qcom/subsystem_notif.h>
#include <sound/q6core.h>

#define DEVICE_NAME "avtimer"
#define TIMEOUT_MS 1000
@@ -58,6 +60,8 @@ struct avtimer_t {
	int timer_handle;
	void __iomem *p_avtimer_msw;
	void __iomem *p_avtimer_lsw;
	uint32_t clk_div;
	atomic_t adsp_ready;
};

static struct avtimer_t avtimer;
@@ -102,6 +106,7 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
		pr_debug("%s: Reset event received in AV timer\n", __func__);
		apr_reset(avtimer.core_handle_q);
		avtimer.core_handle_q = NULL;
		atomic_set(&avtimer.adsp_ready, 0);
		break;
	}

@@ -239,8 +244,10 @@ int avcs_core_disable_power_collapse(int enable)
			goto done;
		}
		rc = avcs_core_enable_avtimer("timer");
		if (!rc)
		if (!rc) {
			avtimer.avtimer_open_cnt++;
			atomic_set(&avtimer.adsp_ready, 1);
		}
	} else {
		if (avtimer.avtimer_open_cnt > 0) {
			avtimer.avtimer_open_cnt--;
@@ -257,6 +264,31 @@ done:
}
EXPORT_SYMBOL(avcs_core_disable_power_collapse);

int avcs_core_query_timer(uint64_t *avtimer_tick)
{
	int ret = 0;
	uint32_t avtimer_msw = 0, avtimer_lsw = 0;

	if (!atomic_read(&avtimer.adsp_ready)) {
		if (q6core_is_adsp_ready()) {
			ret = avcs_core_disable_power_collapse(1);
			if (ret)
				return ret;
		} else {
			return -ENETRESET;
		}
	}
	avtimer_msw = ioread32(avtimer.p_avtimer_msw);
	avtimer_lsw = ioread32(avtimer.p_avtimer_lsw);

	avtimer_lsw = avtimer_lsw/avtimer.clk_div;
	*avtimer_tick =
		(uint64_t)((uint64_t)avtimer_msw << 32)
			| avtimer_lsw;
	return 0;
}
EXPORT_SYMBOL(avcs_core_query_timer);

static int avtimer_open(struct inode *inode, struct file *file)
{
	return avcs_core_disable_power_collapse(1);
@@ -285,6 +317,7 @@ static long avtimer_ioctl(struct file *file, unsigned int ioctl_num,
			avtimer_msw_2nd = ioread32(avtimer.p_avtimer_msw);
		} while (avtimer_msw_1st != avtimer_msw_2nd);

		avtimer_lsw = avtimer_lsw/avtimer.clk_div;
		avtimer_tick =
		((uint64_t) avtimer_msw_1st << 32) | avtimer_lsw;

@@ -317,6 +350,7 @@ static int dev_avtimer_probe(struct platform_device *pdev)
	dev_t dev = MKDEV(major, 0);
	struct device *device_handle;
	struct resource *reg_lsb = NULL, *reg_msb = NULL;
	uint32_t clk_div_val;

	if (!pdev) {
		pr_err("%s: Invalid params\n", __func__);
@@ -360,14 +394,15 @@ static int dev_avtimer_probe(struct platform_device *pdev)
	}

	if (result < 0) {
		pr_err("%s: Registering avtimer device failed\n", __func__);
		dev_err(&pdev->dev, "%s: Registering avtimer device failed\n",
			__func__);
		goto unmap;
	}

	avtimer.avtimer_class = class_create(THIS_MODULE, "avtimer");
	if (IS_ERR(avtimer.avtimer_class)) {
		result = PTR_ERR(avtimer.avtimer_class);
		pr_err("%s: Error creating avtimer class: %d\n",
		dev_err(&pdev->dev, "%s: Error creating avtimer class: %d\n",
			__func__, result);
		goto unregister_chrdev_region;
	}
@@ -376,7 +411,8 @@ static int dev_avtimer_probe(struct platform_device *pdev)
	result = cdev_add(&avtimer.myc, dev, 1);

	if (result < 0) {
		pr_err("%s: Registering file operations failed\n", __func__);
		dev_err(&pdev->dev, "%s: Registering file operations failed\n",
			__func__);
		goto class_destroy;
	}

@@ -394,6 +430,13 @@ static int dev_avtimer_probe(struct platform_device *pdev)
	pr_debug("%s: Device create done for avtimer major=%d\n",
			__func__, major);

	if (of_property_read_u32(pdev->dev.of_node,
			"qcom,clk_div", &clk_div_val))
		avtimer.clk_div = 1;
	else
		avtimer.clk_div = clk_div_val;

	pr_debug("avtimer.clk_div = %d\n", avtimer.clk_div);
	return 0;

class_destroy:
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#ifndef _AVTIMER_H
#define _AVTIMER_H

#include <uapi/linux/avtimer.h>

int avcs_core_open(void);
int avcs_core_disable_power_collapse(int disable);/* true or flase */
int avcs_core_query_timer(uint64_t *avtimer_tick);

#endif
+0 −3
Original line number Diff line number Diff line
@@ -15,8 +15,5 @@ struct dev_avtimer_data {
	uint32_t avtimer_msw_phy_addr;
	uint32_t avtimer_lsw_phy_addr;
};
int avcs_core_open(void);
int avcs_core_disable_power_collapse(int disable);/* true or flase */
uint64_t avcs_core_query_timer(void);

#endif