From 020e1720dc926c944479da4ce0edd7508bc82d21 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
Date: Mon, 20 Jul 2015 12:18:36 +0200
Subject: [PATCH 136/171] cpufreq: bcm2835: Use firmware API
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Use the new firmware API instead of the legacy mailbox API.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/cpufreq/bcm2835-cpufreq.c | 117 +++++++++++++++++---------------------
 1 file changed, 53 insertions(+), 64 deletions(-)

--- a/drivers/cpufreq/bcm2835-cpufreq.c
+++ b/drivers/cpufreq/bcm2835-cpufreq.c
@@ -26,7 +26,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/cpufreq.h>
-#include <linux/platform_data/mailbox-bcm2708.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
 
 /* ---------- DEFINES ---------- */
 /*#define CPUFREQ_DEBUG_ENABLE*/		/* enable debugging */
@@ -43,23 +43,6 @@
 #define print_err(fmt,...) pr_err("%s:%s:%d: "fmt, MODULE_NAME, __func__,__LINE__, ##__VA_ARGS__)
 #define print_info(fmt,...) pr_info("%s: "fmt, MODULE_NAME, ##__VA_ARGS__)
 
-/* tag part of the message */
-struct vc_msg_tag {
-	uint32_t tag_id;		/* the message id */
-	uint32_t buffer_size;		/* size of the buffer (which in this case is always 8 bytes) */
-	uint32_t data_size;		/* amount of data being sent or received */
-	uint32_t dev_id;		/* the ID of the clock/voltage to get or set */
-	uint32_t val;			/* the value (e.g. rate (in Hz)) to set */
-};
-
-/* message structure to be sent to videocore */
-struct vc_msg {
-	uint32_t msg_size;		/* simply, sizeof(struct vc_msg) */
-	uint32_t request_code;		/* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */
-	struct vc_msg_tag tag;		/* the tag structure above to make */
-	uint32_t end_tag;		/* an end identifier, should be set to NULL */
-};
-
 /* ---------- GLOBALS ---------- */
 static struct cpufreq_driver bcm2835_cpufreq_driver;	/* the cpufreq driver global */
 
@@ -74,62 +57,63 @@ static struct cpufreq_frequency_table bc
   clk_rate either gets or sets the clock rates.
  ===============================================
 */
-static uint32_t bcm2835_cpufreq_set_clock(int cur_rate, int arm_rate)
+
+static int bcm2835_cpufreq_clock_property(u32 tag, u32 id, u32 *val)
 {
-	int s, actual_rate=0;
-	struct vc_msg msg;
+	struct rpi_firmware *fw = rpi_firmware_get(NULL);
+	struct {
+		u32 id;
+		u32 val;
+	} packet;
+	int ret;
+
+	packet.id = id;
+	packet.val = *val;
+	ret = rpi_firmware_property(fw, tag, &packet, sizeof(packet));
+	if (ret)
+		return ret;
 
-	/* wipe all previous message data */
-	memset(&msg, 0, sizeof msg);
+	*val = packet.val;
 
-	msg.msg_size = sizeof msg;
+	return 0;
+}
 
-	msg.tag.tag_id = VCMSG_SET_CLOCK_RATE;
-	msg.tag.buffer_size = 8;
-	msg.tag.data_size = 8;   /* we're sending the clock ID and the new rates which is a total of 2 words */
-	msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;
-	msg.tag.val = arm_rate * 1000;
+static uint32_t bcm2835_cpufreq_set_clock(int cur_rate, int arm_rate)
+{
+	u32 rate = arm_rate * 1000;
+	int ret;
 
-	/* send the message */
-	s = bcm_mailbox_property(&msg, sizeof msg);
+	ret = bcm2835_cpufreq_clock_property(RPI_FIRMWARE_SET_CLOCK_RATE, VCMSG_ID_ARM_CLOCK, &rate);
+	if (ret) {
+		print_err("Failed to set clock: %d (%d)\n", arm_rate, ret);
+		return 0;
+	}
 
-	/* check if it was all ok and return the rate in KHz */
-	if (s == 0 && (msg.request_code & 0x80000000))
-		actual_rate = msg.tag.val/1000;
+	rate /= 1000;
+	print_debug("Setting new frequency = %d -> %d (actual %d)\n", cur_rate, arm_rate, rate);
 
-	print_debug("Setting new frequency = %d -> %d (actual %d)\n", cur_rate, arm_rate, actual_rate);
-	return actual_rate;
+	return rate;
 }
 
 static uint32_t bcm2835_cpufreq_get_clock(int tag)
 {
-	int s;
-	int arm_rate = 0;
-	struct vc_msg msg;
-
-	/* wipe all previous message data */
-	memset(&msg, 0, sizeof msg);
-
-	msg.msg_size = sizeof msg;
-	msg.tag.tag_id = tag;
-	msg.tag.buffer_size = 8;
-	msg.tag.data_size = 4; /* we're just sending the clock ID which is one word long */
-	msg.tag.dev_id = VCMSG_ID_ARM_CLOCK;
-
-	/* send the message */
-	s = bcm_mailbox_property(&msg, sizeof msg);
-
-	/* check if it was all ok and return the rate in KHz */
-	if (s == 0 && (msg.request_code & 0x80000000))
-		arm_rate = msg.tag.val/1000;
-
-	print_debug("%s frequency = %d\n",
-		tag == VCMSG_GET_CLOCK_RATE ? "Current":
-		tag == VCMSG_GET_MIN_CLOCK ? "Min":
-		tag == VCMSG_GET_MAX_CLOCK ? "Max":
-		"Unexpected", arm_rate);
+	u32 rate;
+	int ret;
+
+	ret = bcm2835_cpufreq_clock_property(tag, VCMSG_ID_ARM_CLOCK, &rate);
+	if (ret) {
+		print_err("Failed to get clock (%d)\n", ret);
+		return 0;
+	}
+
+	rate /= 1000;
+	print_debug("%s frequency = %u\n",
+		tag == RPI_FIRMWARE_GET_CLOCK_RATE ? "Current":
+		tag == RPI_FIRMWARE_GET_MIN_CLOCK_RATE ? "Min":
+		tag == RPI_FIRMWARE_GET_MAX_CLOCK_RATE ? "Max":
+		"Unexpected", rate);
 
-	return arm_rate;
+	return rate;
 }
 
 /*
@@ -165,9 +149,14 @@ static int bcm2835_cpufreq_driver_init(s
 	/* measured value of how long it takes to change frequency */
 	const unsigned int transition_latency = 355000; /* ns */
 
+	if (!rpi_firmware_get(NULL)) {
+		print_err("Firmware is not available\n");
+		return -ENODEV;
+	}
+
 	/* now find out what the maximum and minimum frequencies are */
-	bcm2835_freq_table[0].frequency = bcm2835_cpufreq_get_clock(VCMSG_GET_MIN_CLOCK);
-	bcm2835_freq_table[1].frequency = bcm2835_cpufreq_get_clock(VCMSG_GET_MAX_CLOCK);
+	bcm2835_freq_table[0].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE);
+	bcm2835_freq_table[1].frequency = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE);
 
 	print_info("min=%d max=%d\n", bcm2835_freq_table[0].frequency, bcm2835_freq_table[1].frequency);
 	return cpufreq_generic_init(policy, bcm2835_freq_table, transition_latency);
@@ -201,8 +190,8 @@ static int bcm2835_cpufreq_driver_target
 
 static unsigned int bcm2835_cpufreq_driver_get(unsigned int cpu)
 {
-	unsigned int actual_rate = bcm2835_cpufreq_get_clock(VCMSG_GET_CLOCK_RATE);
-	print_debug("%d: freq=%d\n", cpu, actual_rate);
+	unsigned int actual_rate = bcm2835_cpufreq_get_clock(RPI_FIRMWARE_GET_CLOCK_RATE);
+	print_debug("cpu%d: freq=%d\n", cpu, actual_rate);
 	return actual_rate <= bcm2835_freq_table[0].frequency ? bcm2835_freq_table[0].frequency : bcm2835_freq_table[1].frequency;
 }