summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/pwm.c
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-04-14 21:03:22 -0600
committerTom Warren <twarren@nvidia.com>2015-05-13 09:24:06 -0700
commit1c82c2f60a6f5a5c16f1ea7144da479e78760e06 (patch)
treebe02dbd5d47fd856365f360b84ad038ec153f5c8 /arch/arm/mach-tegra/pwm.c
parent12e671142daa5d4dce5961e6f573a8b740b16f88 (diff)
downloadu-boot-imx-1c82c2f60a6f5a5c16f1ea7144da479e78760e06.zip
u-boot-imx-1c82c2f60a6f5a5c16f1ea7144da479e78760e06.tar.gz
u-boot-imx-1c82c2f60a6f5a5c16f1ea7144da479e78760e06.tar.bz2
tegra: Move the pwm into tegra-common
This is needed for tegra124 also, so make it common and add a header file for tegra124. Signed-off-by: Simon Glass <sjg@chromium.org> Signed-off-by: Tom Warren <twarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/pwm.c')
-rw-r--r--arch/arm/mach-tegra/pwm.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/pwm.c b/arch/arm/mach-tegra/pwm.c
new file mode 100644
index 0000000..8664200
--- /dev/null
+++ b/arch/arm/mach-tegra/pwm.c
@@ -0,0 +1,86 @@
+/*
+ * Tegra pulse width frequency modulator definitions
+ *
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pwm.h>
+
+struct pwm_info {
+ struct pwm_ctlr *pwm; /* Registers for our pwm controller */
+ int pwm_node; /* PWM device tree node */
+} local;
+
+void pwm_enable(unsigned channel, int rate, int pulse_width, int freq_divider)
+{
+ u32 reg;
+
+ assert(channel < PWM_NUM_CHANNELS);
+
+ /* TODO: Can we use clock_adjust_periph_pll_div() here? */
+ clock_start_periph_pll(PERIPH_ID_PWM, CLOCK_ID_SFROM32KHZ, rate);
+
+ reg = PWM_ENABLE_MASK;
+ reg |= pulse_width << PWM_WIDTH_SHIFT;
+ reg |= freq_divider << PWM_DIVIDER_SHIFT;
+ writel(reg, &local.pwm[channel].control);
+ debug("%s: channel=%d, rate=%d\n", __func__, channel, rate);
+}
+
+int pwm_request(const void *blob, int node, const char *prop_name)
+{
+ int pwm_node;
+ u32 data[3];
+
+ if (fdtdec_get_int_array(blob, node, prop_name, data,
+ ARRAY_SIZE(data))) {
+ debug("%s: Cannot decode PWM property '%s'\n", __func__,
+ prop_name);
+ return -1;
+ }
+
+ pwm_node = fdt_node_offset_by_phandle(blob, data[0]);
+ if (pwm_node != local.pwm_node) {
+ debug("%s: PWM property '%s' phandle %d not recognised"
+ "- expecting %d\n", __func__, prop_name, data[0],
+ local.pwm_node);
+ return -1;
+ }
+ if (data[1] >= PWM_NUM_CHANNELS) {
+ debug("%s: PWM property '%s': invalid channel %u\n", __func__,
+ prop_name, data[1]);
+ return -1;
+ }
+
+ /*
+ * TODO: We could maintain a list of requests, but it might not be
+ * worth it for U-Boot.
+ */
+ return data[1];
+}
+
+int pwm_init(const void *blob)
+{
+ local.pwm_node = fdtdec_next_compatible(blob, 0,
+ COMPAT_NVIDIA_TEGRA20_PWM);
+ if (local.pwm_node < 0) {
+ debug("%s: Cannot find device tree node\n", __func__);
+ return -1;
+ }
+
+ local.pwm = (struct pwm_ctlr *)fdtdec_get_addr(blob, local.pwm_node,
+ "reg");
+ if (local.pwm == (struct pwm_ctlr *)FDT_ADDR_T_NONE) {
+ debug("%s: Cannot find pwm reg address\n", __func__);
+ return -1;
+ }
+ debug("Tegra PWM at %p, node %d\n", local.pwm, local.pwm_node);
+
+ return 0;
+}