From: Simon Glass Date: Wed, 15 Apr 2015 03:03:22 +0000 (-0600) Subject: tegra: Move the pwm into tegra-common X-Git-Tag: v2015.07-rc2~245^2~41 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=1c82c2f60a6f5a5c16f1ea7144da479e78760e06;p=u-boot 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 Signed-off-by: Tom Warren --- diff --git a/arch/arm/include/asm/arch-tegra/pwm.h b/arch/arm/include/asm/arch-tegra/pwm.h new file mode 100644 index 0000000000..8e7397d0e5 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/pwm.h @@ -0,0 +1,60 @@ +/* + * Tegra pulse width frequency modulator definitions + * + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_ARCH_TEGRA_PWM_H +#define __ASM_ARCH_TEGRA_PWM_H + +/* This is a single PWM channel */ +struct pwm_ctlr { + uint control; /* Control register */ + uint reserved[3]; /* Space space */ +}; + +#define PWM_NUM_CHANNELS 4 + +/* PWM_CONTROLLER_PWM_CSR_0/1/2/3_0 */ +#define PWM_ENABLE_SHIFT 31 +#define PWM_ENABLE_MASK (0x1 << PWM_ENABLE_SHIFT) + +#define PWM_WIDTH_SHIFT 16 +#define PWM_WIDTH_MASK (0x7FFF << PWM_WIDTH_SHIFT) + +#define PWM_DIVIDER_SHIFT 0 +#define PWM_DIVIDER_MASK (0x1FFF << PWM_DIVIDER_SHIFT) + +/** + * Program the PWM with the given parameters. + * + * @param channel PWM channel to update + * @param rate Clock rate to use for PWM + * @param pulse_width high pulse width: 0=always low, 1=1/256 pulse high, + * n = n/256 pulse high + * @param freq_divider frequency divider value (1 to use rate as is) + */ +void pwm_enable(unsigned channel, int rate, int pulse_width, int freq_divider); + +/** + * Request a pwm channel as referenced by a device tree node. + * + * This channel can then be passed to pwm_enable(). + * + * @param blob Device tree blob + * @param node Node containing reference to pwm + * @param prop_name Property name of pwm reference + * @return channel number, if ok, else -1 + */ +int pwm_request(const void *blob, int node, const char *prop_name); + +/** + * Set up the pwm controller, by looking it up in the fdt. + * + * @return 0 if ok, -1 if the device tree node was not found or invalid. + */ +int pwm_init(const void *blob); + +#endif /* __ASM_ARCH_TEGRA_PWM_H */ diff --git a/arch/arm/include/asm/arch-tegra124/pwm.h b/arch/arm/include/asm/arch-tegra124/pwm.h new file mode 100644 index 0000000000..3d2c4324dc --- /dev/null +++ b/arch/arm/include/asm/arch-tegra124/pwm.h @@ -0,0 +1,14 @@ +/* + * Tegra pulse width frequency modulator definitions + * + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_ARCH_TEGRA124_PWM_H +#define __ASM_ARCH_TEGRA124_PWM_H + +#include + +#endif /* __ASM_ARCH_TEGRA124_PWM_H */ diff --git a/arch/arm/include/asm/arch-tegra20/pwm.h b/arch/arm/include/asm/arch-tegra20/pwm.h index 8e7397d0e5..2207d9cd4d 100644 --- a/arch/arm/include/asm/arch-tegra20/pwm.h +++ b/arch/arm/include/asm/arch-tegra20/pwm.h @@ -6,55 +6,9 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#ifndef __ASM_ARCH_TEGRA_PWM_H -#define __ASM_ARCH_TEGRA_PWM_H +#ifndef __ASM_ARCH_TEGRA20_PWM_H +#define __ASM_ARCH_TEGRA20_PWM_H -/* This is a single PWM channel */ -struct pwm_ctlr { - uint control; /* Control register */ - uint reserved[3]; /* Space space */ -}; +#include -#define PWM_NUM_CHANNELS 4 - -/* PWM_CONTROLLER_PWM_CSR_0/1/2/3_0 */ -#define PWM_ENABLE_SHIFT 31 -#define PWM_ENABLE_MASK (0x1 << PWM_ENABLE_SHIFT) - -#define PWM_WIDTH_SHIFT 16 -#define PWM_WIDTH_MASK (0x7FFF << PWM_WIDTH_SHIFT) - -#define PWM_DIVIDER_SHIFT 0 -#define PWM_DIVIDER_MASK (0x1FFF << PWM_DIVIDER_SHIFT) - -/** - * Program the PWM with the given parameters. - * - * @param channel PWM channel to update - * @param rate Clock rate to use for PWM - * @param pulse_width high pulse width: 0=always low, 1=1/256 pulse high, - * n = n/256 pulse high - * @param freq_divider frequency divider value (1 to use rate as is) - */ -void pwm_enable(unsigned channel, int rate, int pulse_width, int freq_divider); - -/** - * Request a pwm channel as referenced by a device tree node. - * - * This channel can then be passed to pwm_enable(). - * - * @param blob Device tree blob - * @param node Node containing reference to pwm - * @param prop_name Property name of pwm reference - * @return channel number, if ok, else -1 - */ -int pwm_request(const void *blob, int node, const char *prop_name); - -/** - * Set up the pwm controller, by looking it up in the fdt. - * - * @return 0 if ok, -1 if the device tree node was not found or invalid. - */ -int pwm_init(const void *blob); - -#endif /* __ASM_ARCH_TEGRA_PWM_H */ +#endif /* __ASM_ARCH_TEGRA20_PWM_H */ diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 04cef0a252..68eec5c579 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -12,6 +12,7 @@ obj-y += spl.o obj-y += cpu.o else obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o +obj-$(CONFIG_PWM_TEGRA) += pwm.o endif obj-y += ap.o diff --git a/arch/arm/mach-tegra/pwm.c b/arch/arm/mach-tegra/pwm.c new file mode 100644 index 0000000000..8664200430 --- /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 +#include +#include +#include +#include + +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; +} diff --git a/arch/arm/mach-tegra/tegra20/Makefile b/arch/arm/mach-tegra/tegra20/Makefile index d48f9bb325..fc3fb4ae4c 100644 --- a/arch/arm/mach-tegra/tegra20/Makefile +++ b/arch/arm/mach-tegra/tegra20/Makefile @@ -7,7 +7,6 @@ ifdef CONFIG_SPL_BUILD obj-y += cpu.o else -obj-$(CONFIG_PWM_TEGRA) += pwm.o obj-$(CONFIG_VIDEO_TEGRA) += display.o endif diff --git a/arch/arm/mach-tegra/tegra20/pwm.c b/arch/arm/mach-tegra/tegra20/pwm.c deleted file mode 100644 index 5b886363f8..0000000000 --- a/arch/arm/mach-tegra/tegra20/pwm.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Tegra2 pulse width frequency modulator definitions - * - * Copyright (c) 2011 The Chromium OS Authors. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -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; -}