* [GIT PULL v3] Fixes/cleanup for vt8500 serial
From: Greg KH @ 2013-01-18 1:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358363143-7154-1-git-send-email-linux@prisktech.co.nz>
On Thu, Jan 17, 2013 at 08:05:39AM +1300, Tony Prisk wrote:
> Hi Greg,
>
> This should be the final pull request for this series, unless there are
> other review comments. Changelog included.
>
> v2:
> Restore the setting of vt8500_port->uart.uartclk which was dropped in v1.
> Corrected the return-on-fail of devm_request_and_ioremap to -EADDRNOTAVAIL.
>
> v3:
> Corrected the commit message for patch 3
>
>
> The following changes since commit 9931faca02c604c22335f5a935a501bb2ace6e20:
>
> Linux 3.8-rc3 (2013-01-09 18:59:55 -0800)
>
> are available in the git repository at:
>
> git://server.prisktech.co.nz/git/linuxwmt.git tags/vt8500/serial-fixes
I don't take git pull requests for tiny stuff like this, sorry, only
patches through email.
But 2 of these patches had checkpatch issues, so I didn't take patches 3
and 4, please redo them.
thanks,
greg k-h
^ permalink raw reply
* [PATCH 4/4 v3] serial: vt8500: Cleanup code using devm_ function
From: Greg KH @ 2013-01-18 1:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358363143-7154-5-git-send-email-linux@prisktech.co.nz>
On Thu, Jan 17, 2013 at 08:05:43AM +1300, Tony Prisk wrote:
> Convert the last memory allocation (vt8500_port) to use devm_kzalloc
> and remove the fail path cleanup code from vt8500_serial_probe.
>
> Reorder iomem mapping above clk_enable to simplify fail code. The
> clock is only enabled if all other resources are available.
>
> Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
> ---
> drivers/tty/serial/vt8500_serial.c | 13 ++++---------
> 1 file changed, 4 insertions(+), 9 deletions(-)
As I dropped patch 3, I can't take this one either.
greg k-h
^ permalink raw reply
* [PATCH 3/4 v3] serial: vt8500: UART uses gated clock rather than 24Mhz reference
From: Greg KH @ 2013-01-18 1:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358363143-7154-4-git-send-email-linux@prisktech.co.nz>
On Thu, Jan 17, 2013 at 08:05:42AM +1300, Tony Prisk wrote:
> UART modules on Wondermedia SoCs are connected via a gated clock
> source, rather than directly to the 24Mhz reference clock. While
> uboot enables UART0 for debugging, other UART ports are unavailable
> until the clock is enabled.
>
> This patch checks that a valid clock is actually passed from devicetree,
> enables the clock in probe. This change removes the fallback when a
> clock was not specified as it doesn't apply any longer (and would only
> work if the UART clock was already enabled).
>
> DTSI files are updated for VT8500, WM8505 and WM8650.
>
> Signed-off-by: Tony Prisk <linux@prisktech.co.nz>
> ---
> arch/arm/boot/dts/vt8500.dtsi | 40 +++++++++++++++++++++---
> arch/arm/boot/dts/wm8505.dtsi | 60 ++++++++++++++++++++++++++++++++----
> arch/arm/boot/dts/wm8650.dtsi | 20 ++++++++++--
> drivers/tty/serial/vt8500_serial.c | 34 +++++++++++---------
> 4 files changed, 127 insertions(+), 27 deletions(-)
PLEASE always use checkpatch.pl on your patches before sending them, so
people don't have to write emails saying "why didn't you fix the
checkpatch.pl errors in your patch" much like this one.
Sorry, not applied.
greg k-h
^ permalink raw reply
* [PATCH v7] usb: phy: samsung: Add support to set pmu isolation
From: Kukjin Kim @ 2013-01-18 1:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358230225-2770-1-git-send-email-gautam.vivek@samsung.com>
Vivek Gautam wrote:
>
> Adding support to parse device node data in order to get
> required properties to set pmu isolation for usb-phy.
>
> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Reviewed-by: Doug Anderson <dianders@chromium.org>
This looks good to me,
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Vivek, could you please re-send following in one series?
- [PATCH v9 1/2] usb: phy: samsung: Introducing usb phy driver for hsotg
- [PATCH v8 2/2] usb: s3c-hsotg: Adding phy driver support
As I know, this should be applied on top of above patches.
Thanks.
- Kukjin
^ permalink raw reply
* [GIT PULL] Samsung cleanup-header for v3.9
From: Kukjin Kim @ 2013-01-18 0:26 UTC (permalink / raw)
To: linux-arm-kernel
Hi, Arnd, Olof
Here is cleanup headers for Samsung stuff.
AS I commented, this makes <mach/*.h> local so that they could be removed.
Please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
next/cleanup-header
If any problems, please kindly let me know.
Thanks
- Kukjin
The following changes since commit a49f0d1ea3ec94fc7cf33a7c36a16343b74bd565:
Linux 3.8-rc1 (2012-12-21 17:19:00 -0800)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
next/cleanup-header
for you to fetch changes up to 3a71c5c375e29fc9c1493b5ead1cf36572139c3e:
ARM: S3C64XX: Fix missing header error with CONFIG_CPU_IDLE enabled
(2013-01-10 10:45:41 -0800)
----------------------------------------------------------------
Kukjin Kim (25):
cpufreq: exynos: cleanup exynos-cpufreq header
ARM: S5P64X0: remove gpiolib.c file in mach-s5p64x0
ARM: S5P64X0: move i2c.h into local directory
ARM: S5P64X0: move s5p64x0-clock.h into local directory
ARM: S5PV210: move regs-sys.h into setup-usb-phy.c file
ARM: EXYNOS: move mach/pmu.h file into common.h
ARM: SAMSUNG: cleanup mach/regs-audss.h file
ARM: SAMSUNG: cleanup mach/gpio-fns.h gpio-track.h and gpio-nrs.h
ARM: S3C24XX: make anubis-cpld, anubis-irq and anubis-map local
ARM: S3C24XX: make bast-cpld.h, bast-irq.h and bast-map.h local
ARM: S3C24XX: make gta02.h local
ARM: S3C24XX: make h1940.h and h1940-latch.h local
ARM: S3C24XX: make osiris-cpld.h and osiris-map.h local
ARM: S3C24XX: make otom-map.h local
ARM: S3C24XX: make vr1000-cpld.h, vr1000-irq.h and vr1000-map.h local
ARM: S3C2416: remove regs-s3c2416-mem.h and regs-s3c2416.h
ARM: S3C2412: cleanup regs-s3c2412.h
ARM: S3C24XX: remove idle.h
ARM: S3C24XX: remove dsc.c and make regs-dsc.h local
ARM: S3C64XX: make crag6410.h local
ARM: S3C64XX: make regs-gpio-memport.h local
ARM: S3C64XX: make regs-modem.h local
ARM: S3C64XX: make regs-srom.h local
ARM: S3C64XX: make regs-sys.h local
ARM: S3C64XX: make regs-syscon-power.h local
Tomasz Figa (1):
ARM: S3C64XX: Fix missing header error with CONFIG_CPU_IDLE enabled
arch/arm/mach-exynos/common.c | 1 -
arch/arm/mach-exynos/common.h | 20 +
arch/arm/mach-exynos/cpuidle.c | 3 +-
arch/arm/mach-exynos/dev-audio.c | 3 +-
arch/arm/mach-exynos/include/mach/pmu.h | 34 --
arch/arm/mach-exynos/include/mach/regs-audss.h | 18 -
arch/arm/mach-exynos/pm.c | 3 +-
arch/arm/mach-exynos/pmu.c | 3 +-
arch/arm/mach-s3c2440/Makefile | 2 -
arch/arm/mach-s3c2440/dsc.c | 54 ---
arch/arm/mach-s3c24xx/anubis.h | 53 ++
arch/arm/mach-s3c24xx/bast-ide.c | 18 +-
arch/arm/mach-s3c24xx/bast-irq.c | 19 +-
arch/arm/mach-s3c24xx/bast.h | 197 ++++++++
arch/arm/mach-s3c24xx/{include/mach => }/gta02.h | 14 +-
arch/arm/mach-s3c24xx/h1940-bluetooth.c | 6 +-
.../{include/mach/h1940-latch.h => h1940.h} | 22 +-
arch/arm/mach-s3c24xx/include/mach/anubis-cpld.h | 25 -
arch/arm/mach-s3c24xx/include/mach/anubis-irq.h | 21 -
arch/arm/mach-s3c24xx/include/mach/anubis-map.h | 38 --
arch/arm/mach-s3c24xx/include/mach/bast-cpld.h | 53 --
arch/arm/mach-s3c24xx/include/mach/bast-irq.h | 29 --
arch/arm/mach-s3c24xx/include/mach/bast-map.h | 146 ------
arch/arm/mach-s3c24xx/include/mach/gpio-fns.h | 1 -
arch/arm/mach-s3c24xx/include/mach/gpio-nrs.h | 97 ----
arch/arm/mach-s3c24xx/include/mach/gpio-track.h | 33 --
arch/arm/mach-s3c24xx/include/mach/gpio.h | 87 +++-
arch/arm/mach-s3c24xx/include/mach/h1940.h | 24 -
arch/arm/mach-s3c24xx/include/mach/idle.h | 24 -
arch/arm/mach-s3c24xx/include/mach/osiris-cpld.h | 30 --
arch/arm/mach-s3c24xx/include/mach/regs-gpio.h | 2 -
arch/arm/mach-s3c24xx/include/mach/regs-s3c2412.h | 23 -
.../mach-s3c24xx/include/mach/regs-s3c2416-mem.h | 30 --
arch/arm/mach-s3c24xx/include/mach/regs-s3c2416.h | 24 -
arch/arm/mach-s3c24xx/include/mach/vr1000-cpld.h | 18 -
arch/arm/mach-s3c24xx/include/mach/vr1000-irq.h | 26 -
arch/arm/mach-s3c24xx/include/mach/vr1000-map.h | 110 -----
arch/arm/mach-s3c24xx/mach-anubis.c | 13 +-
arch/arm/mach-s3c24xx/mach-at2440evb.c | 1 +
arch/arm/mach-s3c24xx/mach-bast.c | 52 +-
arch/arm/mach-s3c24xx/mach-gta02.c | 59 ++-
arch/arm/mach-s3c24xx/mach-h1940.c | 37 +-
arch/arm/mach-s3c24xx/mach-osiris.c | 27 +-
arch/arm/mach-s3c24xx/mach-otom.c | 20 +-
arch/arm/mach-s3c24xx/mach-rx1950.c | 31 +-
arch/arm/mach-s3c24xx/mach-rx3715.c | 16 +-
arch/arm/mach-s3c24xx/mach-smdk2413.c | 1 -
arch/arm/mach-s3c24xx/mach-smdk2416.c | 1 -
arch/arm/mach-s3c24xx/mach-smdk2440.c | 1 -
arch/arm/mach-s3c24xx/mach-smdk2443.c | 1 -
arch/arm/mach-s3c24xx/mach-vr1000.c | 37 +-
arch/arm/mach-s3c24xx/mach-vstms.c | 1 -
.../{include/mach/osiris-map.h => osiris.h} | 23 +-
.../{include/mach/otom-map.h => otom.h} | 20 +-
arch/arm/mach-s3c24xx/pm-s3c2410.c | 6 +-
arch/arm/mach-s3c24xx/pm-s3c2412.c | 8 +-
.../arm/mach-s3c24xx/{include/mach => }/regs-dsc.h | 0
arch/arm/mach-s3c24xx/s3c2412.c | 29 +-
arch/arm/mach-s3c24xx/s3c244x.c | 3 +-
arch/arm/mach-s3c24xx/simtec-audio.c | 5 +-
arch/arm/mach-s3c24xx/simtec-nor.c | 3 +-
arch/arm/mach-s3c24xx/simtec-usb.c | 8 +-
arch/arm/mach-s3c24xx/vr1000.h | 118 +++++
arch/arm/mach-s3c64xx/clock.c | 3 +-
arch/arm/mach-s3c64xx/cpuidle.c | 4 +-
.../arm/mach-s3c64xx/{include/mach => }/crag6410.h | 0
arch/arm/mach-s3c64xx/dma.c | 4 +-
arch/arm/mach-s3c64xx/include/mach/regs-sys.h | 31 --
arch/arm/mach-s3c64xx/mach-anw6410.c | 2 +-
arch/arm/mach-s3c64xx/mach-crag6410-module.c | 2 +-
arch/arm/mach-s3c64xx/mach-crag6410.c | 9 +-
arch/arm/mach-s3c64xx/mach-mini6410.c | 4 +-
arch/arm/mach-s3c64xx/mach-real6410.c | 4 +-
arch/arm/mach-s3c64xx/mach-smartq.c | 2 +-
arch/arm/mach-s3c64xx/mach-smdk6410.c | 6 +-
arch/arm/mach-s3c64xx/pm.c | 9 +-
.../{include/mach => }/regs-gpio-memport.h | 9 +-
.../mach-s3c64xx/{include/mach => }/regs-modem.h | 11 +-
.../mach-s3c64xx/{include/mach => }/regs-srom.h | 11 +-
arch/arm/mach-s3c64xx/regs-sys.h | 30 ++
.../{include/mach => }/regs-syscon-power.h | 9 +-
arch/arm/mach-s3c64xx/setup-usb-phy.c | 3 +-
arch/arm/mach-s5p64x0/clock-s5p6440.c | 2 +-
arch/arm/mach-s5p64x0/clock-s5p6450.c | 2 +-
.../{include/mach/s5p64x0-clock.h => clock.h} | 9 +-
arch/arm/mach-s5p64x0/gpiolib.c | 508
--------------------
arch/arm/mach-s5p64x0/{include/mach => }/i2c.h | 3 +-
arch/arm/mach-s5p64x0/mach-smdk6440.c | 2 +-
arch/arm/mach-s5p64x0/mach-smdk6450.c | 2 +-
arch/arm/mach-s5p64x0/setup-i2c0.c | 2 +-
arch/arm/mach-s5p64x0/setup-i2c1.c | 2 +-
arch/arm/mach-s5pv210/dev-audio.c | 3 +-
arch/arm/mach-s5pv210/include/mach/regs-audss.h | 18 -
arch/arm/mach-s5pv210/include/mach/regs-sys.h | 15 -
arch/arm/mach-s5pv210/setup-usb-phy.c | 7 +-
arch/arm/plat-samsung/include/plat/gpio-core.h | 13 +-
arch/arm/plat-samsung/include/plat/gpio-fns.h | 1 -
drivers/cpufreq/exynos-cpufreq.c | 4 +-
.../cpufreq.h => drivers/cpufreq/exynos-cpufreq.h | 3 +-
drivers/cpufreq/exynos4210-cpufreq.c | 3 +-
drivers/cpufreq/exynos4x12-cpufreq.c | 3 +-
drivers/cpufreq/exynos5250-cpufreq.c | 3 +-
drivers/gpio/gpio-samsung.c | 1 -
sound/soc/samsung/h1940_uda1380.c | 13 +-
sound/soc/samsung/neo1973_wm8753.c | 8 +-
105 files changed, 836 insertions(+), 1776 deletions(-)
delete mode 100644 arch/arm/mach-exynos/include/mach/pmu.h
delete mode 100644 arch/arm/mach-exynos/include/mach/regs-audss.h
delete mode 100644 arch/arm/mach-s3c2440/dsc.c
create mode 100644 arch/arm/mach-s3c24xx/anubis.h
create mode 100644 arch/arm/mach-s3c24xx/bast.h
rename arch/arm/mach-s3c24xx/{include/mach => }/gta02.h (53%)
rename arch/arm/mach-s3c24xx/{include/mach/h1940-latch.h => h1940.h} (70%)
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/anubis-cpld.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/anubis-irq.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/anubis-map.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/bast-cpld.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/bast-irq.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/bast-map.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/gpio-fns.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/gpio-nrs.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/gpio-track.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/h1940.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/idle.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/osiris-cpld.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/regs-s3c2412.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/regs-s3c2416-mem.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/regs-s3c2416.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/vr1000-cpld.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/vr1000-irq.h
delete mode 100644 arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
rename arch/arm/mach-s3c24xx/{include/mach/osiris-map.h => osiris.h} (69%)
rename arch/arm/mach-s3c24xx/{include/mach/otom-map.h => otom.h} (50%)
rename arch/arm/mach-s3c24xx/{include/mach => }/regs-dsc.h (100%)
create mode 100644 arch/arm/mach-s3c24xx/vr1000.h
rename arch/arm/mach-s3c64xx/{include/mach => }/crag6410.h (100%)
delete mode 100644 arch/arm/mach-s3c64xx/include/mach/regs-sys.h
rename arch/arm/mach-s3c64xx/{include/mach => }/regs-gpio-memport.h (71%)
rename arch/arm/mach-s3c64xx/{include/mach => }/regs-modem.h (78%)
rename arch/arm/mach-s3c64xx/{include/mach => }/regs-srom.h (90%)
create mode 100644 arch/arm/mach-s3c64xx/regs-sys.h
rename arch/arm/mach-s3c64xx/{include/mach => }/regs-syscon-power.h (95%)
rename arch/arm/mach-s5p64x0/{include/mach/s5p64x0-clock.h => clock.h}
(87%)
delete mode 100644 arch/arm/mach-s5p64x0/gpiolib.c
rename arch/arm/mach-s5p64x0/{include/mach => }/i2c.h (91%)
delete mode 100644 arch/arm/mach-s5pv210/include/mach/regs-audss.h
delete mode 100644 arch/arm/mach-s5pv210/include/mach/regs-sys.h
delete mode 100644 arch/arm/plat-samsung/include/plat/gpio-fns.h
rename arch/arm/mach-exynos/include/mach/cpufreq.h =>
drivers/cpufreq/exynos-cpufreq.h (94%)
^ permalink raw reply
* [PATCH v2] arch/arm/mach-s5pv210: adding ifdef CONFIG_CPU_S5PV210 to fix compiling issue
From: Kukjin Kim @ 2013-01-18 0:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50EAC016.6090707@asianux.com>
Chen Gang wrote:
>
Firstly, thanks for your posting.
But there are some comments.
For subject:
Please see the git log before your commit, it should be helpful to you.
In this case, 'ARM: S5PV210: ...' is used.
>
> if not define CONFIG_CPU_S5PV210
>
> it will define NULL in common.h for:
> s5pv210_map_io, s5pv210_init_clocks, s5pv210_init,
s5pv210_init_uarts
>
> so need using #ifdef CONFIG_CPU_S5PV210 for them too, in common.c.
> or compiling issue will occur.
>
I don't think so, because common.c in mach-s5pv210 should be built with
selecting CONFIG_CPU_S5PV210, actually it depends on CONFIG_ARCH_S5PV210
though.
Any concerns, please let me know.
>
> Signed-off-by: Chen Gang <gang.chen@asianux.com>
> ---
> arch/arm/mach-s5pv210/common.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-
> s5pv210/common.c
> index 9dfe93e..5c88f88 100644
> --- a/arch/arm/mach-s5pv210/common.c
> +++ b/arch/arm/mach-s5pv210/common.c
> @@ -167,6 +167,8 @@ void __init s5pv210_init_io(struct map_desc
> *mach_desc, int size)
> s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
> }
>
> +#ifdef CONFIG_CPU_S5PV210
> +
> void __init s5pv210_map_io(void)
> {
> /* initialise device information early */
> @@ -209,6 +211,9 @@ void __init s5pv210_init_clocks(int xtal)
> s5pv210_setup_clocks();
> }
>
> +#endif /* CONFIG_CPU_S5PV210 */
> +
> +
Generally, no need double empty lines here.
> void __init s5pv210_init_irq(void)
> {
> u32 vic[4]; /* S5PV210 supports 4 VIC */
> @@ -227,6 +232,8 @@ struct bus_type s5pv210_subsys = {
> .dev_name = "s5pv210-core",
> };
>
> +#ifdef CONFIG_CPU_S5PV210
> +
> static struct device s5pv210_dev = {
> .bus = &s5pv210_subsys,
> };
> @@ -249,3 +256,5 @@ void __init s5pv210_init_uarts(struct s3c2410_uartcfg
> *cfg, int no)
> {
> s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
> }
> +
> +#endif /* CONFIG_CPU_S5PV210 */
> --
> 1.7.10.4
Thanks.
- Kukjin
^ permalink raw reply
* [PATCH] ARM: shmobile: sh73a0: Use generic irqchip_init()
From: Simon Horman @ 2013-01-18 0:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358424013-31306-1-git-send-email-thierry.reding@avionic-design.de>
On Thu, Jan 17, 2013 at 01:00:13PM +0100, Thierry Reding wrote:
> The asm/hardware/gic.h header does no longer exist and the corresponding
> functionality was moved to linux/irqchip.h and linux/irqchip/arm-gic.h
> respectively. gic_handle_irq() and of_irq_init() are no longer available
> either and have been replaced by irqchip_init().
>
> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Thanks.
Due to the hairy upstream requirements of the arm-soc tree
I believe this patch needs to be split in two. A 'board' patch
for board-kzm9g-reference.c. And an 'soc' patch for the
remaining portions.
I'm happy to split the patch myself or for you to do so.
> ---
> arch/arm/mach-shmobile/board-kzm9g-reference.c | 1 -
> arch/arm/mach-shmobile/intc-sh73a0.c | 9 ++-------
> arch/arm/mach-shmobile/setup-sh73a0.c | 2 --
> 3 files changed, 2 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm/mach-shmobile/board-kzm9g-reference.c b/arch/arm/mach-shmobile/board-kzm9g-reference.c
> index 04e9ae5..08c95dd 100644
> --- a/arch/arm/mach-shmobile/board-kzm9g-reference.c
> +++ b/arch/arm/mach-shmobile/board-kzm9g-reference.c
> @@ -90,7 +90,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g-reference")
> .init_early = sh73a0_add_early_devices_dt,
> .nr_irqs = NR_IRQS_LEGACY,
> .init_irq = sh73a0_init_irq_dt,
> - .handle_irq = gic_handle_irq,
> .init_machine = kzm_init,
> .init_late = shmobile_init_late,
> .init_time = shmobile_timer_init,
> diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
> index fc7c8da..91faba6 100644
> --- a/arch/arm/mach-shmobile/intc-sh73a0.c
> +++ b/arch/arm/mach-shmobile/intc-sh73a0.c
> @@ -21,9 +21,9 @@
> #include <linux/interrupt.h>
> #include <linux/module.h>
> #include <linux/irq.h>
> -#include <linux/of_irq.h>
> #include <linux/io.h>
> #include <linux/sh_intc.h>
> +#include <linux/irqchip.h>
> #include <linux/irqchip/arm-gic.h>
> #include <mach/intc.h>
> #include <mach/irqs.h>
> @@ -462,14 +462,9 @@ void __init sh73a0_init_irq(void)
> }
>
> #ifdef CONFIG_OF
> -static const struct of_device_id irq_of_match[] __initconst = {
> - { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
> - { },
> -};
> -
> void __init sh73a0_init_irq_dt(void)
> {
> - of_irq_init(irq_of_match);
> + irqchip_init();
> gic_arch_extn.irq_set_wake = sh73a0_set_wake;
> }
> #endif
> diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
> index abf1eb0..2ecd668 100644
> --- a/arch/arm/mach-shmobile/setup-sh73a0.c
> +++ b/arch/arm/mach-shmobile/setup-sh73a0.c
> @@ -36,7 +36,6 @@
> #include <mach/irqs.h>
> #include <mach/sh73a0.h>
> #include <mach/common.h>
> -#include <asm/hardware/gic.h>
> #include <asm/mach-types.h>
> #include <asm/mach/map.h>
> #include <asm/mach/arch.h>
> @@ -892,7 +891,6 @@ DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
> .init_early = sh73a0_add_early_devices_dt,
> .nr_irqs = NR_IRQS_LEGACY,
> .init_irq = sh73a0_init_irq_dt,
> - .handle_irq = gic_handle_irq,
> .init_machine = sh73a0_add_standard_devices_dt,
> .init_time = shmobile_timer_init,
> .dt_compat = sh73a0_boards_compat_dt,
> --
> 1.8.1.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sh" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH v2] drivers/pinctrl: grab default handles from device core
From: Simon Horman @ 2013-01-17 23:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F82745.6050507@wwwdotorg.org>
On Thu, Jan 17, 2013 at 09:31:01AM -0700, Stephen Warren wrote:
> On 01/16/2013 11:02 PM, Simon Horman wrote:
> > On Wed, Jan 16, 2013 at 10:49:05AM -0700, Stephen Warren wrote:
> >> On 01/11/2013 01:45 PM, Linus Walleij wrote:
> >>> On Fri, Jan 11, 2013 at 9:36 PM, Laurent Pinchart
> >>> <laurent.pinchart@ideasonboard.com> wrote:
> >>>
> >>>> I've sent several patch series for the SH PFC (Pin Function Controller) to the
> >>>> linux-sh mailing list. One of the series included pinctrl core patches for
> >>>> easier testing, but I made it clear that they should *not* be pushed to
> >>>> mainline through the SH tree.
> >>>
> >>> No big deal, what fun is linux-next if we don't break it ;-)
> >>
> >> Hmm. It's causing a lot of engineers here a lot of trouble, since they
> >> all see linux-next won't boot, and haven't been paying enough attention
> >> to know which commit to revert:-(. Lots of lost productivity:-(
> >>
> >> Simon, the offending commit:
> >>
> >> 6d3ef6b drivers/pinctrl: grab default handles from device core
> >>
> >> is still in next-20130116. Can you please remove it?
> >
> > I removed the commit yesterday.
> > Please let me know if it seems to be lingering.
>
> Thanks. I believe it's gone from next-20130117, judging by a quick
> search through "git log" at least.
Thanks and sorry for the mess.
^ permalink raw reply
* [PATCH] ARM: OMAP2: Fix missing omap2xxx_clkt_vps_xxx function calls
From: Paul Walmsley @ 2013-01-17 23:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301172230250.14118@utopia.booyaka.com>
Here's the updated version (at the bottom of this message). Seems to work
based on a quick test on 2430SDP.
# shutdown -r -n now
shutdown: sending all processes the TERM signal...
shutdown: sending all processes the KILL signal.
shutdown: turning off swap
shutdown: unmounting all file systems
umount: /debug: not mounted
umount: /run/shm: not mounted
umount: /dev: not mounted
umount: /tmp: not mounted
umount: /run/lock: not mounted
umount: /run: not mounted
umount: /lib/init/rw: not found
Please stand by while rebooting the system.
[ 79.635925] Disabling non-boot CPUs ...
[ 79.640197] Restarting system.
U-Boot 1.1.4 (Mar 18 2007 - 12:22:00)
OMAP2430C-GP revision 3, PRCM #5A
TI 2430SDP 1.1 Version + mDDR (Boot NOR)
DRAM: 128 MB
Flash: 192 MB
NAND:64 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
... etc. ...
- Paul
From: Jon Hunter <jon-hunter@ti.com>
Date: Thu, 10 Jan 2013 14:53:29 -0600
Subject: [PATCH] ARM: OMAP2: Fix missing omap2xxx_clkt_vps_late_init function
calls
During the migration to the common clock framework, calls to the
functions omap2xxx_clkt_vps_late_init() were not preserved for
OMAP2420 and OMAP2430. This causes the variables "sys_ck_rate" and
"curr_prcm_set" to be uninitialised on boot. On reboot, this causes the
following error message to be displayed because the appropriate MPU
clock frequency (derived from sys_ck_rate) cannot be found.
"Could not set MPU rate to 4294MHz"
Fix this by adding back calls to omap2xxx_clkt_vps_late_init() in the
OMAP2420 and OMAP2430 clock initialisation code.
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
[paul at pwsan.com: dropped the duplicated call to
omap2xxx_clkt_vps_check_bootloader_rates() after consultation with Jon;
updated patch description]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
arch/arm/mach-omap2/cclock2420_data.c | 2 ++
arch/arm/mach-omap2/cclock2430_data.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/arch/arm/mach-omap2/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c
index 7e5febe..ab7e952 100644
--- a/arch/arm/mach-omap2/cclock2420_data.c
+++ b/arch/arm/mach-omap2/cclock2420_data.c
@@ -1935,6 +1935,8 @@ int __init omap2420_clk_init(void)
omap2_init_clk_hw_omap_clocks(c->lk.clk);
}
+ omap2xxx_clkt_vps_late_init();
+
omap2_clk_disable_autoidle_all();
omap2_clk_enable_init_clocks(enable_init_clks,
diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
index eda079b..eb3dab6 100644
--- a/arch/arm/mach-omap2/cclock2430_data.c
+++ b/arch/arm/mach-omap2/cclock2430_data.c
@@ -2050,6 +2050,8 @@ int __init omap2430_clk_init(void)
omap2_init_clk_hw_omap_clocks(c->lk.clk);
}
+ omap2xxx_clkt_vps_late_init();
+
omap2_clk_disable_autoidle_all();
omap2_clk_enable_init_clocks(enable_init_clks,
--
1.7.10.4
^ permalink raw reply related
* [[PATCH v2]] OMAP: omap4-panda: add WiLink shared transport power functions
From: Tony Lindgren @ 2013-01-17 23:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358445456.6252.64.camel@cumari.coelho.fi>
* Luciano Coelho <coelho@ti.com> [130117 10:04]:
> Hi Tony,
>
> On Thu, 2013-01-17 at 09:31 -0800, Tony Lindgren wrote:
> > * Peter Ujfalusi <peter.ujfalusi@ti.com> [130117 02:44]:
> > > On 01/17/2013 11:35 AM, Luciano Coelho wrote:
> > > > This out-of-tree code doesn't explain why we need to do the
> > > > enable/disable in the board file. We just need to do things a bit
> > > > differently in the driver. I'll start cleaning all this stuff up for
> > > > -next pretty soon.
> > > >
> > > > For now, ie. 3.7 (stable) and 3.8, do we agree in taking this patch so
> > > > that TI-ST at least works on Panda? Simply reverting the gpio removal
> > > > patch doesn't help, because we also need to handle the UART2 muxing
> > > > (which my patch does as well).
> > >
> > > I don't see better way to fix this either. In any case, I give you my:
> > >
> > > Reviewed-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
> >
> > So what is actually broken? The horrible bluetooth muxing over serial
> > port? If so, let's rather fix it properly than even attempt to fix
> > it as it seems that it's been broken for two merge windows now.
>
> Yes, it is the horrible Bluetooth muxing over serial that is broken. It
> has been broken for two merge windows, because nobody seemed to care
> until I started looking into it and tried to figure out how to get it to
> work. :)
Heh I see.
> The implementation is really weak and there are loads of things I want
> to start fixing/cleaning up. This patch was just my intention to start
> with a relatively clean table (ie. horrible or not, at least working).
>
>
> > Also, let's just do absolutely minimal board-*.c file fixes now.
> > This thing should be just moved to use DT so we can flip over omap4
> > to be DT only and drop estimated 5k LOC from mach-omap2.
>
> I totally agree, I'll start looking into that next.
>
> But this patch is pretty small and simple, so why not include it to at
> least fix the breakage in 3.7 and 3.8? Whether you take it or not now
> won't make any difference in the 5k LOC in these kernel versions.
Well we are planning to drop the non-DT support for omap4 as soon as it's
usable with DT. For omap4 we are only carrying SDP and panda support to
make this transition easier. The only bindings missing AFAIK are wl12xx and
USB.
If we add this, then it implies we're somehow supporting it, which is not
the way to go IMHO as we need to get rid of these platform callbacks instead.
What's your estimate of having minimal wl12xx WLAN DT binding available?
Regards,
Tony
^ permalink raw reply
* [PATCH v7 19/22] ARM: OMAP3: clock data: get rid of unused USB host clock aliases and dummies
From: Paul Walmsley @ 2013-01-17 22:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130117223138.GN14149@atomide.com>
On Thu, 17 Jan 2013, Tony Lindgren wrote:
> * Paul Walmsley <paul@pwsan.com> [130117 14:33]:
> > On Thu, 17 Jan 2013, Felipe Balbi wrote:
> >
> > > do you mean v3.9 ?
> >
> > It sounds like the other patches need to be merged first before these
> > cleanups can be merged. So rather than adding a merge order dependency
> > during 3.9, it seems best to queue the non-essential clock cleanup side
> > for 3.10.
>
> How about let's do it in a late cleanup branch towards the end of the
> v3.9 merge window?
That's fine with me too if the arm-soc folks are willing.
- Paul
^ permalink raw reply
* [PATCH v7 19/22] ARM: OMAP3: clock data: get rid of unused USB host clock aliases and dummies
From: Felipe Balbi @ 2013-01-17 22:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301172228140.14118@utopia.booyaka.com>
On Thu, Jan 17, 2013 at 10:29:52PM +0000, Paul Walmsley wrote:
> On Thu, 17 Jan 2013, Felipe Balbi wrote:
>
> > do you mean v3.9 ?
>
> It sounds like the other patches need to be merged first before these
> cleanups can be merged. So rather than adding a merge order dependency
> during 3.9, it seems best to queue the non-essential clock cleanup side
> for 3.10.
got it
--
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130118/4ebd110f/attachment.sig>
^ permalink raw reply
* [PATCH v7 19/22] ARM: OMAP3: clock data: get rid of unused USB host clock aliases and dummies
From: Tony Lindgren @ 2013-01-17 22:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301172228140.14118@utopia.booyaka.com>
* Paul Walmsley <paul@pwsan.com> [130117 14:33]:
> On Thu, 17 Jan 2013, Felipe Balbi wrote:
>
> > do you mean v3.9 ?
>
> It sounds like the other patches need to be merged first before these
> cleanups can be merged. So rather than adding a merge order dependency
> during 3.9, it seems best to queue the non-essential clock cleanup side
> for 3.10.
How about let's do it in a late cleanup branch towards the end of the
v3.9 merge window?
Regards,
Tony
^ permalink raw reply
* [PATCH] ARM: OMAP2: Fix missing omap2xxx_clkt_vps_xxx function calls
From: Paul Walmsley @ 2013-01-17 22:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F85087.3060507@ti.com>
Hi Jon,
On Thu, 17 Jan 2013, Jon Hunter wrote:
> Yes I still see it. You don't see it on reboot?
Ah that's probably explains the discrepancy - I missed the part about the
reboot.
> The reason why there is such a large number is because
> omap2_round_to_table_rate() is returning the value -EINVAL. You could
> add a print to omap2_round_to_table_rate() to see what it returns on
> reboot. Or we could add a WARN to the function is sys_ck_rate is 0 for
> testing.
>
> > Also, there's already a call to omap2xxx_clkt_vps_check_bootloader_rates()
> > -- is it necessary to add another one?
>
> Thanks. I see that now and so that is not needed then.
OK, I'll queue your patch for 3.8-rc fixes, dropping the
omap2xxx_clkt_vps_check_bootloader_rates() calls.
- Paul
^ permalink raw reply
* [PATCH] ARM: OMAP AM3517/05: hwmod data: block WFI when EMAC active
From: Mark A. Greer @ 2013-01-17 22:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301171919420.14118@utopia.booyaka.com>
On Thu, Jan 17, 2013 at 07:21:42PM +0000, Paul Walmsley wrote:
> Hi Mark
>
> On Tue, 8 Jan 2013, Mark A. Greer wrote:
>
> > Sorry to nag but I think the comment needs to be updated to remove the
> > sentence about the missing EMAC hwmod.
>
> You are absolutely right, and the correction is very much appreciated.
> Updated patch follows.
>
>
> - Paul
>
> From: Paul Walmsley <paul@pwsan.com>
> Date: Sun, 30 Dec 2012 10:36:36 -0700
> Subject: [PATCH] ARM: OMAP AM3517/05: hwmod data: block WFI when EMAC active
>
> According to Mark Greer, on OMAP AM3517/3505 chips, the EMAC is unable
> to wake the ARM up from WFI:
>
> http://www.spinics.net/lists/arm-kernel/msg174734.html
>
> Further troubleshooting was unable to narrow the problem down. So we
> don't have much choice other than to block WFI when the EMAC is active
> with the HWMOD_BLOCK_WFI flag.
>
> Based on Mark's original patch. We're removing the omap_device-based
> pm_lats code, so a different approach was needed.
>
> This third version contains some corrections thanks to Mark's review.
>
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> Cc: Mark A. Greer <mgreer@animalcreek.com>
> ---
FWIW,
Acked-by: Mark A. Greer <mgreer@animalcreek.com>
^ permalink raw reply
* [PATCH v7 19/22] ARM: OMAP3: clock data: get rid of unused USB host clock aliases and dummies
From: Paul Walmsley @ 2013-01-17 22:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130117210034.GA27671@arwen.pp.htv.fi>
On Thu, 17 Jan 2013, Felipe Balbi wrote:
> do you mean v3.9 ?
It sounds like the other patches need to be merged first before these
cleanups can be merged. So rather than adding a merge order dependency
during 3.9, it seems best to queue the non-essential clock cleanup side
for 3.10.
- Paul
^ permalink raw reply
* [PATCH 1/2] ARM: DT: tegra: Add Colibri T20 512MB COM
From: Lucas Stach @ 2013-01-17 22:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F877A3.5030107@wwwdotorg.org>
Am Donnerstag, den 17.01.2013, 15:13 -0700 schrieb Stephen Warren:
> On 01/17/2013 02:29 PM, Lucas Stach wrote:
> > Am Donnerstag, den 17.01.2013, 13:55 -0700 schrieb Stephen Warren:
> >> On 01/17/2013 04:59 AM, Lucas Stach wrote:
> >>> This adds the device tree include file for the Toradex Colibri T20
> >>> Computer on Module (COM). It's only valid for the 512MB RAM version of
> >>> the module, as the 256MB version needs different EMC tables and flash
> >>> configuration. To make this clear the suffix -512 was added to the board
> >>> compatible string.
> >>>
> >>> The Colibri T20 uses a Tegra2 SoC and has onboard USB Ethernet and AC97
> >>> sound.
> >>>
> >>> Still some things like onboard NAND support missing, but should be a
> >>> good base for further development.
> >>> +
> >>> + sdhci at c8000600 {
> >>> + cd-gpios = <&gpio 23 0>; /* gpio PC7 */
> >>> + vmmc-supply = <&ldo5_reg>;
> >>> + vqmmc-supply = <&vcc_sd_reg>;
> >>> + };
> >>
> >> I assume that all of those nodes are meant to have status="okay"?
> >>
> >> Oh, I see those are in the top-level board .dts file. You may as well
> >> put all the properties there; stuff like the GPIOs and regulators at
> >> least would be purely specific to the individual board, and not the COM.
> >
> > I would like to keep everything that is defined by the COM to reside in
> > the COM dtsi. You are right that the regulator in this case is board
> > specific and should be moved to the board file, I missed this while
> > splitting things out. But at least the GPIO is defined by the fixed COM
> > pinout.
>
> If these are really defined by the COM itself, it does indeed make sense
> for the COM .dtsi file to define those properties. But, I have a hard
> time understanding how the COM design can force the carrier module into
> using a particular GPIO for the SD controller CD functionality; couldn't
> the carrier use any GPIO passed through the COM<->carrier connector for
> any purpose?
>
It's not a GPIO anymore as soon as it hits the COM<->carrier connector.
The connector pin assignment is strictly specified. There are a lot of
freely assignable GPIOs on the connector, everything related to a
specific function is not part of this.
The Colibri specification dictates which pin to use if you want to
realize a SDcard CD. This is done so that modules and carrier boards are
interchangeable. In fact you can just as well run a new Colibri T30
module on a years old carrier designed for the ColibriPXA series of
modules.
> >>> + com_regulators {
> >>
> >> I think just call that "regulators"; the final board .dts file can
> >> easily add more sub-nodes to this node, so there's no need to try and
> >> avoid any naming conflict here. See Cardhu as an example.
> >
> > I don't really see the benefit of merging those nodes. They are separate
> > regulators, some are located on the COM, others on the carrier board. So
> > I would like to keep them in separate nodes, unless you have strong
> > feelings to change this.
>
> The issue here is that if we don't do this, we end up with wierd node
> names; plain "regulators" is a fairly canonical name for what the name
> contains, and purely indicates the type of the node. "com_regulators" is
> unusual, and starts to encode identity into the node name itself, which
> is something not usually done in the node name (differentiation between
> identities is usually done using the unit address; "@nnn"),
Hm, ok. Keeping some space in between module and carrier regulator
addresses should do as well.
^ permalink raw reply
* [PATCH 00/15] OMAP SHAM & AES Crypto Updates
From: Mark A. Greer @ 2013-01-17 22:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301171904070.14118@utopia.booyaka.com>
On Thu, Jan 17, 2013 at 07:13:36PM +0000, Paul Walmsley wrote:
> Hi Mark,
Hi Paul.
> I regret the delay,
>
> On Tue, 8 Jan 2013, Mark A. Greer wrote:
>
> > On Sun, Dec 23, 2012 at 08:40:43AM +0000, Paul Walmsley wrote:
> >
> > > - The patch series causes AM3517/3505 to crash. I'd guess this is due to
> > > the SHAM/AES modules being initialized on those chips, but they probably
> > > don't exist there. Can you change the initialization for those on OMAP3
> > > to only take place on OMAP34xx/36xx GP? I guess you'd need to create new
> > > lists for those in the hwmod init.
> >
> > All am35xx GPs have the SHAM and AES modules except some very old ones.
> > I've been told that there should be very few of the "old" ones around
> > (I don't know how to differentiate them). We're likely safe since the
> > SHAM & AES modules are not enabled in omap2plus_defconfig so nobody
> > should be enabling them on an am35xx unless they know that they have
> > the modules. Do you agree?
>
> Those will presumably only enable or disable the device drivers. The
> hwmod code will probably still try to write to those IP blocks if they are
> listed as present in the hwmod data, during the initial reset-and-idle
> phase.
Um, yeah, good point. :)
> What do you think about adding an am35xx_es11plus_hwmod_ocp_ifs[] array to
> omap_hwmod_3xxx_data.c for these secure hwmods? That carries the implicit
> and possibly wrong assumption that it's likely to be ES1.0 devices that
> are missing the SHAM/AES, but it seems unlikely that TI would have
> multiple silicon revs running around claiming to be ES1.1? Or maybe I'm
> just being na?ve.
Something like that makes sense to me. I'll re-read my email, etc. and
see if I can find something to help us figure it out.
> > The issue that you're likely running into is that 'CK_AM35XX' needs to be
> > added for aes2_ick & sha12_ick in cclock3xxx_data.c. The following
> > patch should fix it (applies to my submitted/crypto/hwmod branch):
> >
> > diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
> > index 582b055..aa5bdf6 100644
> > --- a/arch/arm/mach-omap2/cclock3xxx_data.c
> > +++ b/arch/arm/mach-omap2/cclock3xxx_data.c
> > @@ -3332,10 +3332,10 @@ static struct omap_clk omap3xxx_clks[] = {
> > CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
> > CLK(NULL, "mmchs3_ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
> > CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
> > - CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
> > - CLK(NULL, "aes2_ick", &aes2_ick, CK_34XX | CK_36XX),
> > - CLK("omap-sham", "ick", &sha12_ick, CK_34XX | CK_36XX),
> > - CLK(NULL, "sha12_ick", &sha12_ick, CK_34XX | CK_36XX),
> > + CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_AM35XX | CK_36XX),
> > + CLK(NULL, "aes2_ick", &aes2_ick, CK_34XX | CK_AM35XX | CK_36XX),
> > + CLK("omap-sham", "ick", &sha12_ick, CK_34XX | CK_AM35XX | CK_36XX),
> > + CLK(NULL, "sha12_ick", &sha12_ick, CK_34XX | CK_AM35XX | CK_36XX),
> > CLK(NULL, "des2_ick", &des2_ick, CK_34XX | CK_36XX),
> > CLK("omap_hsmmc.1", "ick", &mmchs2_ick, CK_3XXX),
> > CLK("omap_hsmmc.0", "ick", &mmchs1_ick, CK_3XXX),
> >
> >
> > Please let me know if this patch works for you and, if it does, I'll respin
> > my patches to add those changes.
>
> If those clocks are referenced by the hwmods, that that patch makes sense
> to me. Haven't had the chance to test it yet but maybe tomorrow. On the
> other hand it looks 'obviously correct' so maybe just add that change to
> your patches and repost that one?
Will do.
Mark
--
^ permalink raw reply
* [PATCH] am33xx: cpsw: default to ethernet hwaddr from efuse if not defined in dt
From: Peter Korsgaard @ 2013-01-17 22:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130117174528.GM14149@atomide.com>
>>>>> "Tony" == Tony Lindgren <tony@atomide.com> writes:
Hi,
>> The way I've handled it is similar to how it is done on atleast one
>> other arm subarchicture, see
>> arch/arm/mach-mxs/mach-mxs.c::update_fec_mac_prop()
Tony> Cool this seems like the cleanest way to deal with it so far. Can
Tony> you please resend with also linux-net and DT list Cc:d too?
Tony> Also the arch_initcall should be omap_arch_initcall in linux next
Tony> for consistency if we ever have SoC specific sections for those.
Sure, resent with the initcall change and netdev/devicetree-discuss added.
--
Bye, Peter Korsgaard
^ permalink raw reply
* [PATCH 1/2] ARM: DT: tegra: Add Colibri T20 512MB COM
From: Stephen Warren @ 2013-01-17 22:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358458144.18489.14.camel@tellur>
On 01/17/2013 02:29 PM, Lucas Stach wrote:
> Am Donnerstag, den 17.01.2013, 13:55 -0700 schrieb Stephen Warren:
>> On 01/17/2013 04:59 AM, Lucas Stach wrote:
>>> This adds the device tree include file for the Toradex Colibri T20
>>> Computer on Module (COM). It's only valid for the 512MB RAM version of
>>> the module, as the 256MB version needs different EMC tables and flash
>>> configuration. To make this clear the suffix -512 was added to the board
>>> compatible string.
>>>
>>> The Colibri T20 uses a Tegra2 SoC and has onboard USB Ethernet and AC97
>>> sound.
>>>
>>> Still some things like onboard NAND support missing, but should be a
>>> good base for further development.
>>
>>> diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
>>
>>> + temperature-sensor at 4c {
>>> + compatible = "national,lm95245";
>>
>> You should probably add that compatible value to
>> Documentation/devicetree/bindings/i2c/trivial-devices.txt.
>>
> Yep, will send a separate patch for this.
>
>>> + i2c at 7000c000 {
>>> + clock-frequency = <400000>;
>>> + };
>>> +
>>> + i2c_ddc: i2c at 7000c400 {
>>> + clock-frequency = <100000>;
>>> + };
>>> +
>>> + i2c at 7000c500 {
>>> + clock-frequency = <400000>;
>>> + };
>>
>>> + serial at 70006000 {
>>> + clock-frequency = <216000000>;
>>> + };
>>> +
>>> + serial at 70006300 {
>>> + clock-frequency = <216000000>;
>>> + };
>>> +
>>> + usb at c5000000 {
>>> + dr_mode = "otg";
>>> + };
>>> +
>>> + usb at c5004000 {
>>> + status = "okay";
>>> + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
>>> + };
>>> +
>>> + sdhci at c8000600 {
>>> + cd-gpios = <&gpio 23 0>; /* gpio PC7 */
>>> + vmmc-supply = <&ldo5_reg>;
>>> + vqmmc-supply = <&vcc_sd_reg>;
>>> + };
>>
>> I assume that all of those nodes are meant to have status="okay"?
>>
>> Oh, I see those are in the top-level board .dts file. You may as well
>> put all the properties there; stuff like the GPIOs and regulators at
>> least would be purely specific to the individual board, and not the COM.
>
> I would like to keep everything that is defined by the COM to reside in
> the COM dtsi. You are right that the regulator in this case is board
> specific and should be moved to the board file, I missed this while
> splitting things out. But at least the GPIO is defined by the fixed COM
> pinout.
If these are really defined by the COM itself, it does indeed make sense
for the COM .dtsi file to define those properties. But, I have a hard
time understanding how the COM design can force the carrier module into
using a particular GPIO for the SD controller CD functionality; couldn't
the carrier use any GPIO passed through the COM<->carrier connector for
any purpose?
>>> + com_regulators {
>>
>> I think just call that "regulators"; the final board .dts file can
>> easily add more sub-nodes to this node, so there's no need to try and
>> avoid any naming conflict here. See Cardhu as an example.
>
> I don't really see the benefit of merging those nodes. They are separate
> regulators, some are located on the COM, others on the carrier board. So
> I would like to keep them in separate nodes, unless you have strong
> feelings to change this.
The issue here is that if we don't do this, we end up with wierd node
names; plain "regulators" is a fairly canonical name for what the name
contains, and purely indicates the type of the node. "com_regulators" is
unusual, and starts to encode identity into the node name itself, which
is something not usually done in the node name (differentiation between
identities is usually done using the unit address; "@nnn"),
^ permalink raw reply
* [PATCH] [RFC] ARM: compile fix for DEBUG_LL=y && MMU=n
From: Stephen Warren @ 2013-01-17 22:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130117161433.GL8668@pengutronix.de>
On 01/17/2013 09:14 AM, Uwe Kleine-K?nig wrote:
> On Wed, Jan 16, 2013 at 02:31:44PM -0800, Olof Johansson wrote:
>> On Wed, Jan 16, 2013 at 03:32:06PM +0100, Uwe Kleine-K?nig wrote:
>>> debug_ll_addr is only used on machines with an MMU so it can be #ifdef'ed
>>> out safely. This fixes:
...
>> Adding a defconfig for a !MMU platform seems like a good idea, since there's
>> several of us who make sure that there is build coverage of the defconfigs and
>> follow up on most of the breakage. Feel free to send one in for 3.9.
>
> Jonny just pointed out in irc that there is at91x40_defconfig.
Ah. I have built that a few times recently, but since it doesn't enable
DEBUG_LL, this problem didn't show up.
^ permalink raw reply
* [PATCH v6 1/3] clk: tegra: add Tegra specific clocks
From: Stephen Warren @ 2013-01-17 22:05 UTC (permalink / raw)
To: linux-arm-kernel
From: Prashant Gaikwad <pgaikwad@nvidia.com>
Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
[swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
storing pointers to stack variables, make a timeout loop more idiomatic,
use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
avoid redundant lock operations, unified tegra_clk_periph() and
tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
registration functions so they don't have the same name as the clock
structs, return -EINVAL from clk_plle_enable when matching table rate
not found, pass ops to _tegra_clk_register_pll rather than a bool.]
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
v6:
return -EINVAL from clk_plle_enable when matching table rate not found
pass ops to _tegra_clk_register_pll
This replaces patch 1/3 of the v5 series I posted yesterday. Only patch
1 changed, so I'm only reposting that.
---
drivers/clk/Makefile | 1 +
drivers/clk/tegra/Makefile | 8 +
drivers/clk/tegra/clk-audio-sync.c | 87 +++++
drivers/clk/tegra/clk-divider.c | 187 ++++++++++
drivers/clk/tegra/clk-periph-gate.c | 179 ++++++++++
drivers/clk/tegra/clk-periph.c | 180 ++++++++++
drivers/clk/tegra/clk-pll-out.c | 123 +++++++
drivers/clk/tegra/clk-pll.c | 648 +++++++++++++++++++++++++++++++++++
drivers/clk/tegra/clk-super.c | 154 +++++++++
drivers/clk/tegra/clk.c | 69 ++++
drivers/clk/tegra/clk.h | 490 ++++++++++++++++++++++++++
11 files changed, 2126 insertions(+)
create mode 100644 drivers/clk/tegra/Makefile
create mode 100644 drivers/clk/tegra/clk-audio-sync.c
create mode 100644 drivers/clk/tegra/clk-divider.c
create mode 100644 drivers/clk/tegra/clk-periph-gate.c
create mode 100644 drivers/clk/tegra/clk-periph.c
create mode 100644 drivers/clk/tegra/clk-pll-out.c
create mode 100644 drivers/clk/tegra/clk-pll.c
create mode 100644 drivers/clk/tegra/clk-super.c
create mode 100644 drivers/clk/tegra/clk.c
create mode 100644 drivers/clk/tegra/clk.h
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index ee90e87..f0b269a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_U8500) += ux500/
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
obj-$(CONFIG_ARCH_SUNXI) += clk-sunxi.o
obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o
+obj-$(CONFIG_ARCH_TEGRA) += tegra/
# Chip specific
obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
new file mode 100644
index 0000000..68bd353
--- /dev/null
+++ b/drivers/clk/tegra/Makefile
@@ -0,0 +1,8 @@
+obj-y += clk.o
+obj-y += clk-audio-sync.o
+obj-y += clk-divider.o
+obj-y += clk-periph.o
+obj-y += clk-periph-gate.o
+obj-y += clk-pll.o
+obj-y += clk-pll-out.o
+obj-y += clk-super.o
diff --git a/drivers/clk/tegra/clk-audio-sync.c b/drivers/clk/tegra/clk-audio-sync.c
new file mode 100644
index 0000000..c0f7843
--- /dev/null
+++ b/drivers/clk/tegra/clk-audio-sync.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+static unsigned long clk_sync_source_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
+
+ return sync->rate;
+}
+
+static long clk_sync_source_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
+
+ if (rate > sync->max_rate)
+ return -EINVAL;
+ else
+ return rate;
+}
+
+static int clk_sync_source_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
+
+ sync->rate = rate;
+ return 0;
+}
+
+const struct clk_ops tegra_clk_sync_source_ops = {
+ .round_rate = clk_sync_source_round_rate,
+ .set_rate = clk_sync_source_set_rate,
+ .recalc_rate = clk_sync_source_recalc_rate,
+};
+
+struct clk *tegra_clk_register_sync_source(const char *name,
+ unsigned long rate, unsigned long max_rate)
+{
+ struct tegra_clk_sync_source *sync;
+ struct clk_init_data init;
+ struct clk *clk;
+
+ sync = kzalloc(sizeof(*sync), GFP_KERNEL);
+ if (!sync) {
+ pr_err("%s: could not allocate sync source clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ sync->rate = rate;
+ sync->max_rate = max_rate;
+
+ init.ops = &tegra_clk_sync_source_ops;
+ init.name = name;
+ init.flags = CLK_IS_ROOT;
+ init.parent_names = NULL;
+ init.num_parents = 0;
+
+ /* Data in .init is copied by clk_register(), so stack variable OK */
+ sync->hw.init = &init;
+
+ clk = clk_register(NULL, &sync->hw);
+ if (IS_ERR(clk))
+ kfree(sync);
+
+ return clk;
+}
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
new file mode 100644
index 0000000..4d75b1f
--- /dev/null
+++ b/drivers/clk/tegra/clk-divider.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define pll_out_override(p) (BIT((p->shift - 6)))
+#define div_mask(d) ((1 << (d->width)) - 1)
+#define get_mul(d) (1 << d->frac_width)
+#define get_max_div(d) div_mask(d)
+
+#define PERIPH_CLK_UART_DIV_ENB BIT(24)
+
+static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate,
+ unsigned long parent_rate)
+{
+ s64 divider_ux1 = parent_rate;
+ u8 flags = divider->flags;
+ int mul;
+
+ if (!rate)
+ return 0;
+
+ mul = get_mul(divider);
+
+ if (!(flags & TEGRA_DIVIDER_INT))
+ divider_ux1 *= mul;
+
+ if (flags & TEGRA_DIVIDER_ROUND_UP)
+ divider_ux1 += rate - 1;
+
+ do_div(divider_ux1, rate);
+
+ if (flags & TEGRA_DIVIDER_INT)
+ divider_ux1 *= mul;
+
+ divider_ux1 -= mul;
+
+ if (divider_ux1 < 0)
+ return 0;
+
+ if (divider_ux1 > get_max_div(divider))
+ return -EINVAL;
+
+ return divider_ux1;
+}
+
+static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ u32 reg;
+ int div, mul;
+ u64 rate = parent_rate;
+
+ reg = readl_relaxed(divider->reg) >> divider->shift;
+ div = reg & div_mask(divider);
+
+ mul = get_mul(divider);
+ div += mul;
+
+ rate *= mul;
+ rate += div - 1;
+ do_div(rate, div);
+
+ return rate;
+}
+
+static long clk_frac_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ int div, mul;
+ unsigned long output_rate = *prate;
+
+ if (!rate)
+ return output_rate;
+
+ div = get_div(divider, rate, output_rate);
+ if (div < 0)
+ return *prate;
+
+ mul = get_mul(divider);
+
+ return DIV_ROUND_UP(output_rate * mul, div + mul);
+}
+
+static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+ int div;
+ unsigned long flags = 0;
+ u32 val;
+
+ div = get_div(divider, rate, parent_rate);
+ if (div < 0)
+ return div;
+
+ if (divider->lock)
+ spin_lock_irqsave(divider->lock, flags);
+
+ val = readl_relaxed(divider->reg);
+ val &= ~(div_mask(divider) << divider->shift);
+ val |= div << divider->shift;
+
+ if (divider->flags & TEGRA_DIVIDER_UART) {
+ if (div)
+ val |= PERIPH_CLK_UART_DIV_ENB;
+ else
+ val &= ~PERIPH_CLK_UART_DIV_ENB;
+ }
+
+ if (divider->flags & TEGRA_DIVIDER_FIXED)
+ val |= pll_out_override(divider);
+
+ writel_relaxed(val, divider->reg);
+
+ if (divider->lock)
+ spin_unlock_irqrestore(divider->lock, flags);
+
+ return 0;
+}
+
+const struct clk_ops tegra_clk_frac_div_ops = {
+ .recalc_rate = clk_frac_div_recalc_rate,
+ .set_rate = clk_frac_div_set_rate,
+ .round_rate = clk_frac_div_round_rate,
+};
+
+struct clk *tegra_clk_register_divider(const char *name,
+ const char *parent_name, void __iomem *reg,
+ unsigned long flags, u8 clk_divider_flags, u8 shift, u8 width,
+ u8 frac_width, spinlock_t *lock)
+{
+ struct tegra_clk_frac_div *divider;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ divider = kzalloc(sizeof(*divider), GFP_KERNEL);
+ if (!divider) {
+ pr_err("%s: could not allocate fractional divider clk\n",
+ __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = name;
+ init.ops = &tegra_clk_frac_div_ops;
+ init.flags = flags;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+
+ divider->reg = reg;
+ divider->shift = shift;
+ divider->width = width;
+ divider->frac_width = frac_width;
+ divider->lock = lock;
+ divider->flags = clk_divider_flags;
+
+ /* Data in .init is copied by clk_register(), so stack variable OK */
+ divider->hw.init = &init;
+
+ clk = clk_register(NULL, ÷r->hw);
+ if (IS_ERR(clk))
+ kfree(divider);
+
+ return clk;
+}
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
new file mode 100644
index 0000000..6dd5332
--- /dev/null
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/tegra-soc.h>
+
+#include "clk.h"
+
+static DEFINE_SPINLOCK(periph_ref_lock);
+
+/* Macros to assist peripheral gate clock */
+#define read_enb(gate) \
+ readl_relaxed(gate->clk_base + (gate->regs->enb_reg))
+#define write_enb_set(val, gate) \
+ writel_relaxed(val, gate->clk_base + (gate->regs->enb_set_reg))
+#define write_enb_clr(val, gate) \
+ writel_relaxed(val, gate->clk_base + (gate->regs->enb_clr_reg))
+
+#define read_rst(gate) \
+ readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
+#define write_rst_set(val, gate) \
+ writel_relaxed(val, gate->clk_base + (gate->regs->rst_set_reg))
+#define write_rst_clr(val, gate) \
+ writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
+
+#define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32))
+
+/* Peripheral gate clock ops */
+static int clk_periph_is_enabled(struct clk_hw *hw)
+{
+ struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+ int state = 1;
+
+ if (!(read_enb(gate) & periph_clk_to_bit(gate)))
+ state = 0;
+
+ if (!(gate->flags & TEGRA_PERIPH_NO_RESET))
+ if (read_rst(gate) & periph_clk_to_bit(gate))
+ state = 0;
+
+ return state;
+}
+
+static int clk_periph_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&periph_ref_lock, flags);
+
+ gate->enable_refcnt[gate->clk_num]++;
+ if (gate->enable_refcnt[gate->clk_num] > 1) {
+ spin_unlock_irqrestore(&periph_ref_lock, flags);
+ return 0;
+ }
+
+ write_enb_set(periph_clk_to_bit(gate), gate);
+ udelay(2);
+
+ if (!(gate->flags & TEGRA_PERIPH_NO_RESET) &&
+ !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) {
+ if (read_rst(gate) & periph_clk_to_bit(gate)) {
+ udelay(5); /* reset propogation delay */
+ write_rst_clr(periph_clk_to_bit(gate), gate);
+ }
+ }
+
+ spin_unlock_irqrestore(&periph_ref_lock, flags);
+
+ return 0;
+}
+
+static void clk_periph_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&periph_ref_lock, flags);
+
+ gate->enable_refcnt[gate->clk_num]--;
+ if (gate->enable_refcnt[gate->clk_num] > 0) {
+ spin_unlock_irqrestore(&periph_ref_lock, flags);
+ return;
+ }
+
+ /*
+ * If peripheral is in the APB bus then read the APB bus to
+ * flush the write operation in apb bus. This will avoid the
+ * peripheral access after disabling clock
+ */
+ if (gate->flags & TEGRA_PERIPH_ON_APB)
+ tegra_read_chipid();
+
+ write_enb_clr(periph_clk_to_bit(gate), gate);
+
+ spin_unlock_irqrestore(&periph_ref_lock, flags);
+}
+
+void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert)
+{
+ if (gate->flags & TEGRA_PERIPH_NO_RESET)
+ return;
+
+ if (assert) {
+ /*
+ * If peripheral is in the APB bus then read the APB bus to
+ * flush the write operation in apb bus. This will avoid the
+ * peripheral access after disabling clock
+ */
+ if (gate->flags & TEGRA_PERIPH_ON_APB)
+ tegra_read_chipid();
+
+ write_rst_set(periph_clk_to_bit(gate), gate);
+ } else {
+ write_rst_clr(periph_clk_to_bit(gate), gate);
+ }
+}
+
+const struct clk_ops tegra_clk_periph_gate_ops = {
+ .is_enabled = clk_periph_is_enabled,
+ .enable = clk_periph_enable,
+ .disable = clk_periph_disable,
+};
+
+struct clk *tegra_clk_register_periph_gate(const char *name,
+ const char *parent_name, u8 gate_flags, void __iomem *clk_base,
+ unsigned long flags, int clk_num,
+ struct tegra_clk_periph_regs *pregs, int *enable_refcnt)
+{
+ struct tegra_clk_periph_gate *gate;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ pr_err("%s: could not allocate periph gate clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = name;
+ init.flags = flags;
+ init.parent_names = parent_name ? &parent_name : NULL;
+ init.num_parents = parent_name ? 1 : 0;
+ init.ops = &tegra_clk_periph_gate_ops;
+
+ gate->magic = TEGRA_CLK_PERIPH_GATE_MAGIC;
+ gate->clk_base = clk_base;
+ gate->clk_num = clk_num;
+ gate->flags = gate_flags;
+ gate->enable_refcnt = enable_refcnt;
+ gate->regs = pregs;
+
+ /* Data in .init is copied by clk_register(), so stack variable OK */
+ gate->hw.init = &init;
+
+ clk = clk_register(NULL, &gate->hw);
+ if (IS_ERR(clk))
+ kfree(gate);
+
+ return clk;
+}
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
new file mode 100644
index 0000000..5978e81
--- /dev/null
+++ b/drivers/clk/tegra/clk-periph.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+static u8 clk_periph_get_parent(struct clk_hw *hw)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *mux_ops = periph->mux_ops;
+ struct clk_hw *mux_hw = &periph->mux.hw;
+
+ mux_hw->clk = hw->clk;
+
+ return mux_ops->get_parent(mux_hw);
+}
+
+static int clk_periph_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *mux_ops = periph->mux_ops;
+ struct clk_hw *mux_hw = &periph->mux.hw;
+
+ mux_hw->clk = hw->clk;
+
+ return mux_ops->set_parent(mux_hw, index);
+}
+
+static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *div_ops = periph->div_ops;
+ struct clk_hw *div_hw = &periph->divider.hw;
+
+ div_hw->clk = hw->clk;
+
+ return div_ops->recalc_rate(div_hw, parent_rate);
+}
+
+static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *div_ops = periph->div_ops;
+ struct clk_hw *div_hw = &periph->divider.hw;
+
+ div_hw->clk = hw->clk;
+
+ return div_ops->round_rate(div_hw, rate, prate);
+}
+
+static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *div_ops = periph->div_ops;
+ struct clk_hw *div_hw = &periph->divider.hw;
+
+ div_hw->clk = hw->clk;
+
+ return div_ops->set_rate(div_hw, rate, parent_rate);
+}
+
+static int clk_periph_is_enabled(struct clk_hw *hw)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *gate_ops = periph->gate_ops;
+ struct clk_hw *gate_hw = &periph->gate.hw;
+
+ gate_hw->clk = hw->clk;
+
+ return gate_ops->is_enabled(gate_hw);
+}
+
+static int clk_periph_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *gate_ops = periph->gate_ops;
+ struct clk_hw *gate_hw = &periph->gate.hw;
+
+ gate_hw->clk = hw->clk;
+
+ return gate_ops->enable(gate_hw);
+}
+
+static void clk_periph_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_periph *periph = to_clk_periph(hw);
+ const struct clk_ops *gate_ops = periph->gate_ops;
+ struct clk_hw *gate_hw = &periph->gate.hw;
+
+ gate_ops->disable(gate_hw);
+}
+
+const struct clk_ops tegra_clk_periph_ops = {
+ .get_parent = clk_periph_get_parent,
+ .set_parent = clk_periph_set_parent,
+ .recalc_rate = clk_periph_recalc_rate,
+ .round_rate = clk_periph_round_rate,
+ .set_rate = clk_periph_set_rate,
+ .is_enabled = clk_periph_is_enabled,
+ .enable = clk_periph_enable,
+ .disable = clk_periph_disable,
+};
+
+const struct clk_ops tegra_clk_periph_nodiv_ops = {
+ .get_parent = clk_periph_get_parent,
+ .set_parent = clk_periph_set_parent,
+ .is_enabled = clk_periph_is_enabled,
+ .enable = clk_periph_enable,
+ .disable = clk_periph_disable,
+};
+
+static struct clk *_tegra_clk_register_periph(const char *name,
+ const char **parent_names, int num_parents,
+ struct tegra_clk_periph *periph,
+ void __iomem *clk_base, u32 offset, bool div)
+{
+ struct clk *clk;
+ struct clk_init_data init;
+
+ init.name = name;
+ init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
+ init.flags = div ? 0 : CLK_SET_RATE_PARENT;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+
+ /* Data in .init is copied by clk_register(), so stack variable OK */
+ periph->hw.init = &init;
+ periph->magic = TEGRA_CLK_PERIPH_MAGIC;
+ periph->mux.reg = clk_base + offset;
+ periph->divider.reg = div ? (clk_base + offset) : NULL;
+ periph->gate.clk_base = clk_base;
+
+ clk = clk_register(NULL, &periph->hw);
+ if (IS_ERR(clk))
+ return clk;
+
+ periph->mux.hw.clk = clk;
+ periph->divider.hw.clk = div ? clk : NULL;
+ periph->gate.hw.clk = clk;
+
+ return clk;
+}
+
+struct clk *tegra_clk_register_periph(const char *name,
+ const char **parent_names, int num_parents,
+ struct tegra_clk_periph *periph, void __iomem *clk_base,
+ u32 offset)
+{
+ return _tegra_clk_register_periph(name, parent_names, num_parents,
+ periph, clk_base, offset, true);
+}
+
+struct clk *tegra_clk_register_periph_nodiv(const char *name,
+ const char **parent_names, int num_parents,
+ struct tegra_clk_periph *periph, void __iomem *clk_base,
+ u32 offset)
+{
+ return _tegra_clk_register_periph(name, parent_names, num_parents,
+ periph, clk_base, offset, false);
+}
diff --git a/drivers/clk/tegra/clk-pll-out.c b/drivers/clk/tegra/clk-pll-out.c
new file mode 100644
index 0000000..3598987
--- /dev/null
+++ b/drivers/clk/tegra/clk-pll-out.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define pll_out_enb(p) (BIT(p->enb_bit_idx))
+#define pll_out_rst(p) (BIT(p->rst_bit_idx))
+
+static int clk_pll_out_is_enabled(struct clk_hw *hw)
+{
+ struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
+ u32 val = readl_relaxed(pll_out->reg);
+ int state;
+
+ state = (val & pll_out_enb(pll_out)) ? 1 : 0;
+ if (!(val & (pll_out_rst(pll_out))))
+ state = 0;
+ return state;
+}
+
+static int clk_pll_out_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
+ unsigned long flags = 0;
+ u32 val;
+
+ if (pll_out->lock)
+ spin_lock_irqsave(pll_out->lock, flags);
+
+ val = readl_relaxed(pll_out->reg);
+
+ val |= (pll_out_enb(pll_out) | pll_out_rst(pll_out));
+
+ writel_relaxed(val, pll_out->reg);
+ udelay(2);
+
+ if (pll_out->lock)
+ spin_unlock_irqrestore(pll_out->lock, flags);
+
+ return 0;
+}
+
+static void clk_pll_out_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
+ unsigned long flags = 0;
+ u32 val;
+
+ if (pll_out->lock)
+ spin_lock_irqsave(pll_out->lock, flags);
+
+ val = readl_relaxed(pll_out->reg);
+
+ val &= ~(pll_out_enb(pll_out) | pll_out_rst(pll_out));
+
+ writel_relaxed(val, pll_out->reg);
+ udelay(2);
+
+ if (pll_out->lock)
+ spin_unlock_irqrestore(pll_out->lock, flags);
+}
+
+const struct clk_ops tegra_clk_pll_out_ops = {
+ .is_enabled = clk_pll_out_is_enabled,
+ .enable = clk_pll_out_enable,
+ .disable = clk_pll_out_disable,
+};
+
+struct clk *tegra_clk_register_pll_out(const char *name,
+ const char *parent_name, void __iomem *reg, u8 enb_bit_idx,
+ u8 rst_bit_idx, unsigned long flags, u8 pll_out_flags,
+ spinlock_t *lock)
+{
+ struct tegra_clk_pll_out *pll_out;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ pll_out = kzalloc(sizeof(*pll_out), GFP_KERNEL);
+ if (!pll_out)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &tegra_clk_pll_out_ops;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+ init.flags = flags;
+
+ pll_out->reg = reg;
+ pll_out->enb_bit_idx = enb_bit_idx;
+ pll_out->rst_bit_idx = rst_bit_idx;
+ pll_out->flags = pll_out_flags;
+ pll_out->lock = lock;
+
+ /* Data in .init is copied by clk_register(), so stack variable OK */
+ pll_out->hw.init = &init;
+
+ clk = clk_register(NULL, &pll_out->hw);
+ if (IS_ERR(clk))
+ kfree(pll_out);
+
+ return clk;
+}
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
new file mode 100644
index 0000000..165f247
--- /dev/null
+++ b/drivers/clk/tegra/clk-pll.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define PLL_BASE_BYPASS BIT(31)
+#define PLL_BASE_ENABLE BIT(30)
+#define PLL_BASE_REF_ENABLE BIT(29)
+#define PLL_BASE_OVERRIDE BIT(28)
+
+#define PLL_BASE_DIVP_SHIFT 20
+#define PLL_BASE_DIVP_WIDTH 3
+#define PLL_BASE_DIVN_SHIFT 8
+#define PLL_BASE_DIVN_WIDTH 10
+#define PLL_BASE_DIVM_SHIFT 0
+#define PLL_BASE_DIVM_WIDTH 5
+#define PLLU_POST_DIVP_MASK 0x1
+
+#define PLL_MISC_DCCON_SHIFT 20
+#define PLL_MISC_CPCON_SHIFT 8
+#define PLL_MISC_CPCON_WIDTH 4
+#define PLL_MISC_CPCON_MASK ((1 << PLL_MISC_CPCON_WIDTH) - 1)
+#define PLL_MISC_LFCON_SHIFT 4
+#define PLL_MISC_LFCON_WIDTH 4
+#define PLL_MISC_LFCON_MASK ((1 << PLL_MISC_LFCON_WIDTH) - 1)
+#define PLL_MISC_VCOCON_SHIFT 0
+#define PLL_MISC_VCOCON_WIDTH 4
+#define PLL_MISC_VCOCON_MASK ((1 << PLL_MISC_VCOCON_WIDTH) - 1)
+
+#define OUT_OF_TABLE_CPCON 8
+
+#define PMC_PLLP_WB0_OVERRIDE 0xf8
+#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE BIT(12)
+#define PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE BIT(11)
+
+#define PLL_POST_LOCK_DELAY 50
+
+#define PLLDU_LFCON_SET_DIVN 600
+
+#define PLLE_BASE_DIVCML_SHIFT 24
+#define PLLE_BASE_DIVCML_WIDTH 4
+#define PLLE_BASE_DIVP_SHIFT 16
+#define PLLE_BASE_DIVP_WIDTH 7
+#define PLLE_BASE_DIVN_SHIFT 8
+#define PLLE_BASE_DIVN_WIDTH 8
+#define PLLE_BASE_DIVM_SHIFT 0
+#define PLLE_BASE_DIVM_WIDTH 8
+
+#define PLLE_MISC_SETUP_BASE_SHIFT 16
+#define PLLE_MISC_SETUP_BASE_MASK (0xffff << PLLE_MISC_SETUP_BASE_SHIFT)
+#define PLLE_MISC_LOCK_ENABLE BIT(9)
+#define PLLE_MISC_READY BIT(15)
+#define PLLE_MISC_SETUP_EX_SHIFT 2
+#define PLLE_MISC_SETUP_EX_MASK (3 << PLLE_MISC_SETUP_EX_SHIFT)
+#define PLLE_MISC_SETUP_MASK (PLLE_MISC_SETUP_BASE_MASK | \
+ PLLE_MISC_SETUP_EX_MASK)
+#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)
+
+#define PLLE_SS_CTRL 0x68
+#define PLLE_SS_DISABLE (7 << 10)
+
+#define PMC_SATA_PWRGT 0x1ac
+#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
+#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
+
+#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
+#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
+#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
+
+#define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset)
+#define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p)
+#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p)
+
+#define mask(w) ((1 << (w)) - 1)
+#define divm_mask(p) mask(p->divm_width)
+#define divn_mask(p) mask(p->divn_width)
+#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
+ mask(p->divp_width))
+
+#define divm_max(p) (divm_mask(p))
+#define divn_max(p) (divn_mask(p))
+#define divp_max(p) (1 << (divp_mask(p)))
+
+static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
+{
+ u32 val;
+
+ if (!(pll->flags & TEGRA_PLL_USE_LOCK))
+ return;
+
+ val = pll_readl_misc(pll);
+ val |= BIT(pll->params->lock_enable_bit_idx);
+ pll_writel_misc(val, pll);
+}
+
+static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
+ void __iomem *lock_addr, u32 lock_bit_idx)
+{
+ int i;
+ u32 val;
+
+ if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
+ udelay(pll->params->lock_delay);
+ return 0;
+ }
+
+ for (i = 0; i < pll->params->lock_delay; i++) {
+ val = readl_relaxed(lock_addr);
+ if (val & BIT(lock_bit_idx)) {
+ udelay(PLL_POST_LOCK_DELAY);
+ return 0;
+ }
+ udelay(2); /* timeout = 2 * lock time */
+ }
+
+ pr_err("%s: Timed out waiting for pll %s lock\n", __func__,
+ __clk_get_name(pll->hw.clk));
+
+ return -1;
+}
+
+static int clk_pll_is_enabled(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u32 val;
+
+ if (pll->flags & TEGRA_PLLM) {
+ val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+ if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
+ return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;
+ }
+
+ val = pll_readl_base(pll);
+
+ return val & PLL_BASE_ENABLE ? 1 : 0;
+}
+
+static int _clk_pll_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u32 val;
+
+ clk_pll_enable_lock(pll);
+
+ val = pll_readl_base(pll);
+ val &= ~PLL_BASE_BYPASS;
+ val |= PLL_BASE_ENABLE;
+ pll_writel_base(val, pll);
+
+ if (pll->flags & TEGRA_PLLM) {
+ val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+ val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
+ writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+ }
+
+ clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg,
+ pll->params->lock_bit_idx);
+
+ return 0;
+}
+
+static void _clk_pll_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u32 val;
+
+ val = pll_readl_base(pll);
+ val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+ pll_writel_base(val, pll);
+
+ if (pll->flags & TEGRA_PLLM) {
+ val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+ val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
+ writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+ }
+}
+
+static int clk_pll_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+ int ret;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ ret = _clk_pll_enable(hw);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static void clk_pll_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _clk_pll_disable(hw);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int _get_table_rate(struct clk_hw *hw,
+ struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ struct tegra_clk_pll_freq_table *sel;
+
+ for (sel = pll->freq_table; sel->input_rate != 0; sel++)
+ if (sel->input_rate == parent_rate &&
+ sel->output_rate == rate)
+ break;
+
+ if (sel->input_rate == 0)
+ return -EINVAL;
+
+ BUG_ON(sel->p < 1);
+
+ cfg->input_rate = sel->input_rate;
+ cfg->output_rate = sel->output_rate;
+ cfg->m = sel->m;
+ cfg->n = sel->n;
+ cfg->p = sel->p;
+ cfg->cpcon = sel->cpcon;
+
+ return 0;
+}
+
+static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long cfreq;
+ u32 p_div = 0;
+
+ switch (parent_rate) {
+ case 12000000:
+ case 26000000:
+ cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000;
+ break;
+ case 13000000:
+ cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000;
+ break;
+ case 16800000:
+ case 19200000:
+ cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000;
+ break;
+ case 9600000:
+ case 28800000:
+ /*
+ * PLL_P_OUT1 rate is not listed in PLLA table
+ */
+ cfreq = parent_rate/(parent_rate/1000000);
+ break;
+ default:
+ pr_err("%s Unexpected reference rate %lu\n",
+ __func__, parent_rate);
+ BUG();
+ }
+
+ /* Raise VCO to guarantee 0.5% accuracy */
+ for (cfg->output_rate = rate; cfg->output_rate < 200 * cfreq;
+ cfg->output_rate <<= 1)
+ p_div++;
+
+ cfg->p = 1 << p_div;
+ cfg->m = parent_rate / cfreq;
+ cfg->n = cfg->output_rate / cfreq;
+ cfg->cpcon = OUT_OF_TABLE_CPCON;
+
+ if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
+ cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) {
+ pr_err("%s: Failed to set %s rate %lu\n",
+ __func__, __clk_get_name(hw->clk), rate);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+ u32 divp, val, old_base;
+ int state;
+
+ divp = __ffs(cfg->p);
+
+ if (pll->flags & TEGRA_PLLU)
+ divp ^= 1;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ old_base = val = pll_readl_base(pll);
+ val &= ~((divm_mask(pll) << pll->divm_shift) |
+ (divn_mask(pll) << pll->divn_shift) |
+ (divp_mask(pll) << pll->divp_shift));
+ val |= ((cfg->m << pll->divm_shift) |
+ (cfg->n << pll->divn_shift) |
+ (divp << pll->divp_shift));
+ if (val == old_base) {
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+ return 0;
+ }
+
+ state = clk_pll_is_enabled(hw);
+
+ if (state) {
+ _clk_pll_disable(hw);
+ val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+ }
+ pll_writel_base(val, pll);
+
+ if (pll->flags & TEGRA_PLL_HAS_CPCON) {
+ val = pll_readl_misc(pll);
+ val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
+ val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
+ if (pll->flags & TEGRA_PLL_SET_LFCON) {
+ val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
+ if (cfg->n >= PLLDU_LFCON_SET_DIVN)
+ val |= 0x1 << PLL_MISC_LFCON_SHIFT;
+ } else if (pll->flags & TEGRA_PLL_SET_DCCON) {
+ val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
+ if (rate >= (pll->params->vco_max >> 1))
+ val |= 0x1 << PLL_MISC_DCCON_SHIFT;
+ }
+ pll_writel_misc(val, pll);
+ }
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ if (state)
+ clk_pll_enable(hw);
+
+ return 0;
+}
+
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ struct tegra_clk_pll_freq_table cfg;
+
+ if (pll->flags & TEGRA_PLL_FIXED) {
+ if (rate != pll->fixed_rate) {
+ pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
+ __func__, __clk_get_name(hw->clk),
+ pll->fixed_rate, rate);
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
+ _calc_rate(hw, &cfg, rate, parent_rate))
+ return -EINVAL;
+
+ return _program_pll(hw, &cfg, rate);
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ struct tegra_clk_pll_freq_table cfg;
+ u64 output_rate = *prate;
+
+ if (pll->flags & TEGRA_PLL_FIXED)
+ return pll->fixed_rate;
+
+ /* PLLM is used for memory; we do not change rate */
+ if (pll->flags & TEGRA_PLLM)
+ return __clk_get_rate(hw->clk);
+
+ if (_get_table_rate(hw, &cfg, rate, *prate) &&
+ _calc_rate(hw, &cfg, rate, *prate))
+ return -EINVAL;
+
+ output_rate *= cfg.n;
+ do_div(output_rate, cfg.m * cfg.p);
+
+ return output_rate;
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u32 val = pll_readl_base(pll);
+ u32 divn = 0, divm = 0, divp = 0;
+ u64 rate = parent_rate;
+
+ if (val & PLL_BASE_BYPASS)
+ return parent_rate;
+
+ if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
+ struct tegra_clk_pll_freq_table sel;
+ if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) {
+ pr_err("Clock %s has unknown fixed frequency\n",
+ __clk_get_name(hw->clk));
+ BUG();
+ }
+ return pll->fixed_rate;
+ }
+
+ divp = (val >> pll->divp_shift) & (divp_mask(pll));
+ if (pll->flags & TEGRA_PLLU)
+ divp ^= 1;
+
+ divn = (val >> pll->divn_shift) & (divn_mask(pll));
+ divm = (val >> pll->divm_shift) & (divm_mask(pll));
+ divm *= (1 << divp);
+
+ rate *= divn;
+ do_div(rate, divm);
+ return rate;
+}
+
+static int clk_plle_training(struct tegra_clk_pll *pll)
+{
+ u32 val;
+ unsigned long timeout;
+
+ if (!pll->pmc)
+ return -ENOSYS;
+
+ /*
+ * PLLE is already disabled, and setup cleared;
+ * create falling edge on PLLE IDDQ input.
+ */
+ val = readl(pll->pmc + PMC_SATA_PWRGT);
+ val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
+ writel(val, pll->pmc + PMC_SATA_PWRGT);
+
+ val = readl(pll->pmc + PMC_SATA_PWRGT);
+ val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
+ writel(val, pll->pmc + PMC_SATA_PWRGT);
+
+ val = readl(pll->pmc + PMC_SATA_PWRGT);
+ val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
+ writel(val, pll->pmc + PMC_SATA_PWRGT);
+
+ val = pll_readl_misc(pll);
+
+ timeout = jiffies + msecs_to_jiffies(100);
+ while (1) {
+ val = pll_readl_misc(pll);
+ if (val & PLLE_MISC_READY)
+ break;
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: timeout waiting for PLLE\n", __func__);
+ return -EBUSY;
+ }
+ udelay(300);
+ }
+
+ return 0;
+}
+
+static int clk_plle_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+ struct tegra_clk_pll_freq_table sel;
+ u32 val;
+ int err;
+
+ if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
+ return -EINVAL;
+
+ clk_pll_disable(hw);
+
+ val = pll_readl_misc(pll);
+ val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK);
+ pll_writel_misc(val, pll);
+
+ val = pll_readl_misc(pll);
+ if (!(val & PLLE_MISC_READY)) {
+ err = clk_plle_training(pll);
+ if (err)
+ return err;
+ }
+
+ if (pll->flags & TEGRA_PLLE_CONFIGURE) {
+ /* configure dividers */
+ val = pll_readl_base(pll);
+ val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
+ val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
+ val |= sel.m << pll->divm_shift;
+ val |= sel.n << pll->divn_shift;
+ val |= sel.p << pll->divp_shift;
+ val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
+ pll_writel_base(val, pll);
+ }
+
+ val = pll_readl_misc(pll);
+ val |= PLLE_MISC_SETUP_VALUE;
+ val |= PLLE_MISC_LOCK_ENABLE;
+ pll_writel_misc(val, pll);
+
+ val = readl(pll->clk_base + PLLE_SS_CTRL);
+ val |= PLLE_SS_DISABLE;
+ writel(val, pll->clk_base + PLLE_SS_CTRL);
+
+ val |= pll_readl_base(pll);
+ val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+ pll_writel_base(val, pll);
+
+ clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg,
+ pll->params->lock_bit_idx);
+ return 0;
+}
+
+static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u32 val = pll_readl_base(pll);
+ u32 divn = 0, divm = 0, divp = 0;
+ u64 rate = parent_rate;
+
+ divp = (val >> pll->divp_shift) & (divp_mask(pll));
+ divn = (val >> pll->divn_shift) & (divn_mask(pll));
+ divm = (val >> pll->divm_shift) & (divm_mask(pll));
+ divm *= divp;
+
+ rate *= divn;
+ do_div(rate, divm);
+ return rate;
+}
+
+const struct clk_ops tegra_clk_pll_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .enable = clk_pll_enable,
+ .disable = clk_pll_disable,
+ .recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_round_rate,
+ .set_rate = clk_pll_set_rate,
+};
+
+const struct clk_ops tegra_clk_plle_ops = {
+ .recalc_rate = clk_plle_recalc_rate,
+ .is_enabled = clk_pll_is_enabled,
+ .disable = clk_pll_disable,
+ .enable = clk_plle_enable,
+};
+
+static struct clk *_tegra_clk_register_pll(const char *name,
+ const char *parent_name, void __iomem *clk_base,
+ void __iomem *pmc, unsigned long flags,
+ unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock,
+ const struct clk_ops *ops)
+{
+ struct tegra_clk_pll *pll;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = ops;
+ init.flags = flags;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+
+ pll->clk_base = clk_base;
+ pll->pmc = pmc;
+
+ pll->freq_table = freq_table;
+ pll->params = pll_params;
+ pll->fixed_rate = fixed_rate;
+ pll->flags = pll_flags;
+ pll->lock = lock;
+
+ pll->divp_shift = PLL_BASE_DIVP_SHIFT;
+ pll->divp_width = PLL_BASE_DIVP_WIDTH;
+ pll->divn_shift = PLL_BASE_DIVN_SHIFT;
+ pll->divn_width = PLL_BASE_DIVN_WIDTH;
+ pll->divm_shift = PLL_BASE_DIVM_SHIFT;
+ pll->divm_width = PLL_BASE_DIVM_WIDTH;
+
+ /* Data in .init is copied by clk_register(), so stack variable OK */
+ pll->hw.init = &init;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(clk))
+ kfree(pll);
+
+ return clk;
+}
+
+struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+{
+ return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
+ flags, fixed_rate, pll_params, pll_flags, freq_table,
+ lock, &tegra_clk_pll_ops);
+}
+
+struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+{
+ return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
+ flags, fixed_rate, pll_params, pll_flags, freq_table,
+ lock, &tegra_clk_plle_ops);
+}
diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
new file mode 100644
index 0000000..7ad48a8
--- /dev/null
+++ b/drivers/clk/tegra/clk-super.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define SUPER_STATE_IDLE 0
+#define SUPER_STATE_RUN 1
+#define SUPER_STATE_IRQ 2
+#define SUPER_STATE_FIQ 3
+
+#define SUPER_STATE_SHIFT 28
+#define SUPER_STATE_MASK ((BIT(SUPER_STATE_IDLE) | BIT(SUPER_STATE_RUN) | \
+ BIT(SUPER_STATE_IRQ) | BIT(SUPER_STATE_FIQ)) \
+ << SUPER_STATE_SHIFT)
+
+#define SUPER_LP_DIV2_BYPASS (1 << 16)
+
+#define super_state(s) (BIT(s) << SUPER_STATE_SHIFT)
+#define super_state_to_src_shift(m, s) ((m->width * s))
+#define super_state_to_src_mask(m) (((1 << m->width) - 1))
+
+static u8 clk_super_get_parent(struct clk_hw *hw)
+{
+ struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
+ u32 val, state;
+ u8 source, shift;
+
+ val = readl_relaxed(mux->reg);
+
+ state = val & SUPER_STATE_MASK;
+
+ BUG_ON((state != super_state(SUPER_STATE_RUN)) &&
+ (state != super_state(SUPER_STATE_IDLE)));
+ shift = (state == super_state(SUPER_STATE_IDLE)) ?
+ super_state_to_src_shift(mux, SUPER_STATE_IDLE) :
+ super_state_to_src_shift(mux, SUPER_STATE_RUN);
+
+ source = (val >> shift) & super_state_to_src_mask(mux);
+
+ /*
+ * If LP_DIV2_BYPASS is not set and PLLX is current parent then
+ * PLLX/2 is the input source to CCLKLP.
+ */
+ if ((mux->flags & TEGRA_DIVIDER_2) && !(val & SUPER_LP_DIV2_BYPASS) &&
+ (source == mux->pllx_index))
+ source = mux->div2_index;
+
+ return source;
+}
+
+static int clk_super_set_parent(struct clk_hw *hw, u8 index)
+{
+ struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
+ u32 val, state;
+ u8 parent_index, shift;
+
+ val = readl_relaxed(mux->reg);
+ state = val & SUPER_STATE_MASK;
+ BUG_ON((state != super_state(SUPER_STATE_RUN)) &&
+ (state != super_state(SUPER_STATE_IDLE)));
+ shift = (state == super_state(SUPER_STATE_IDLE)) ?
+ super_state_to_src_shift(mux, SUPER_STATE_IDLE) :
+ super_state_to_src_shift(mux, SUPER_STATE_RUN);
+
+ /*
+ * For LP mode super-clock switch between PLLX direct
+ * and divided-by-2 outputs is allowed only when other
+ * than PLLX clock source is current parent.
+ */
+ if ((mux->flags & TEGRA_DIVIDER_2) && ((index == mux->div2_index) ||
+ (index == mux->pllx_index))) {
+ parent_index = clk_super_get_parent(hw);
+ if ((parent_index == mux->div2_index) ||
+ (parent_index == mux->pllx_index))
+ return -EINVAL;
+
+ val ^= SUPER_LP_DIV2_BYPASS;
+ writel_relaxed(val, mux->reg);
+ udelay(2);
+
+ if (index == mux->div2_index)
+ index = mux->pllx_index;
+ }
+ val &= ~((super_state_to_src_mask(mux)) << shift);
+ val |= (index & (super_state_to_src_mask(mux))) << shift;
+
+ writel_relaxed(val, mux->reg);
+ udelay(2);
+ return 0;
+}
+
+const struct clk_ops tegra_clk_super_ops = {
+ .get_parent = clk_super_get_parent,
+ .set_parent = clk_super_set_parent,
+};
+
+struct clk *tegra_clk_register_super_mux(const char *name,
+ const char **parent_names, u8 num_parents,
+ unsigned long flags, void __iomem *reg, u8 clk_super_flags,
+ u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock)
+{
+ struct tegra_clk_super_mux *super;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ super = kzalloc(sizeof(*super), GFP_KERNEL);
+ if (!super) {
+ pr_err("%s: could not allocate super clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = name;
+ init.ops = &tegra_clk_super_ops;
+ init.flags = flags;
+ init.parent_names = parent_names;
+ init.num_parents = num_parents;
+
+ super->reg = reg;
+ super->pllx_index = pllx_index;
+ super->div2_index = div2_index;
+ super->lock = lock;
+ super->width = width;
+ super->flags = clk_super_flags;
+
+ /* Data in .init is copied by clk_register(), so stack variable OK */
+ super->hw.init = &init;
+
+ clk = clk_register(NULL, &super->hw);
+ if (IS_ERR(clk))
+ kfree(super);
+
+ return clk;
+}
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
new file mode 100644
index 0000000..cf023a9
--- /dev/null
+++ b/drivers/clk/tegra/clk.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
+ struct clk *clks[], int clk_max)
+{
+ struct clk *clk;
+
+ for (; dup_list->clk_id < clk_max; dup_list++) {
+ clk = clks[dup_list->clk_id];
+ dup_list->lookup.clk = clk;
+ clkdev_add(&dup_list->lookup);
+ }
+}
+
+void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
+ struct clk *clks[], int clk_max)
+{
+ struct clk *clk;
+
+ for (; tbl->clk_id < clk_max; tbl++) {
+ clk = clks[tbl->clk_id];
+ if (IS_ERR_OR_NULL(clk))
+ return;
+
+ if (tbl->parent_id < clk_max) {
+ struct clk *parent = clks[tbl->parent_id];
+ if (clk_set_parent(clk, parent)) {
+ pr_err("%s: Failed to set parent %s of %s\n",
+ __func__, __clk_get_name(parent),
+ __clk_get_name(clk));
+ WARN_ON(1);
+ }
+ }
+
+ if (tbl->rate)
+ if (clk_set_rate(clk, tbl->rate)) {
+ pr_err("%s: Failed to set rate %lu of %s\n",
+ __func__, tbl->rate,
+ __clk_get_name(clk));
+ WARN_ON(1);
+ }
+
+ if (tbl->state)
+ if (clk_prepare_enable(clk)) {
+ pr_err("%s: Failed to enable %s\n", __func__,
+ __clk_get_name(clk));
+ WARN_ON(1);
+ }
+ }
+}
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
new file mode 100644
index 0000000..5fcfa51
--- /dev/null
+++ b/drivers/clk/tegra/clk.h
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEGRA_CLK_H
+#define __TEGRA_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+/**
+ * struct tegra_clk_sync_source - external clock source from codec
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @rate: input frequency from source
+ * @max_rate: max rate allowed
+ */
+struct tegra_clk_sync_source {
+ struct clk_hw hw;
+ unsigned long rate;
+ unsigned long max_rate;
+};
+
+#define to_clk_sync_source(_hw) \
+ container_of(_hw, struct tegra_clk_sync_source, hw)
+
+extern const struct clk_ops tegra_clk_sync_source_ops;
+struct clk *tegra_clk_register_sync_source(const char *name,
+ unsigned long fixed_rate, unsigned long max_rate);
+
+/**
+ * struct tegra_clk_frac_div - fractional divider clock
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @reg: register containing divider
+ * @flags: hardware-specific flags
+ * @shift: shift to the divider bit field
+ * @width: width of the divider bit field
+ * @frac_width: width of the fractional bit field
+ * @lock: register lock
+ *
+ * Flags:
+ * TEGRA_DIVIDER_ROUND_UP - This flags indicates to round up the divider value.
+ * TEGRA_DIVIDER_FIXED - Fixed rate PLL dividers has addition override bit, this
+ * flag indicates that this divider is for fixed rate PLL.
+ * TEGRA_DIVIDER_INT - Some modules can not cope with the duty cycle when
+ * fraction bit is set. This flags indicates to calculate divider for which
+ * fracton bit will be zero.
+ * TEGRA_DIVIDER_UART - UART module divider has additional enable bit which is
+ * set when divider value is not 0. This flags indicates that the divider
+ * is for UART module.
+ */
+struct tegra_clk_frac_div {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 flags;
+ u8 shift;
+ u8 width;
+ u8 frac_width;
+ spinlock_t *lock;
+};
+
+#define to_clk_frac_div(_hw) container_of(_hw, struct tegra_clk_frac_div, hw)
+
+#define TEGRA_DIVIDER_ROUND_UP BIT(0)
+#define TEGRA_DIVIDER_FIXED BIT(1)
+#define TEGRA_DIVIDER_INT BIT(2)
+#define TEGRA_DIVIDER_UART BIT(3)
+
+extern const struct clk_ops tegra_clk_frac_div_ops;
+struct clk *tegra_clk_register_divider(const char *name,
+ const char *parent_name, void __iomem *reg,
+ unsigned long flags, u8 clk_divider_flags, u8 shift, u8 width,
+ u8 frac_width, spinlock_t *lock);
+
+/*
+ * Tegra PLL:
+ *
+ * In general, there are 3 requirements for each PLL
+ * that SW needs to be comply with.
+ * (1) Input frequency range (REF).
+ * (2) Comparison frequency range (CF). CF = REF/DIVM.
+ * (3) VCO frequency range (VCO). VCO = CF * DIVN.
+ *
+ * The final PLL output frequency (FO) = VCO >> DIVP.
+ */
+
+/**
+ * struct tegra_clk_pll_freq_table - PLL frequecy table
+ *
+ * @input_rate: input rate from source
+ * @output_rate: output rate from PLL for the input rate
+ * @n: feedback divider
+ * @m: input divider
+ * @p: post divider
+ * @cpcon: charge pump current
+ */
+struct tegra_clk_pll_freq_table {
+ unsigned long input_rate;
+ unsigned long output_rate;
+ u16 n;
+ u16 m;
+ u8 p;
+ u8 cpcon;
+};
+
+/**
+ * struct clk_pll_params - PLL parameters
+ *
+ * @input_min: Minimum input frequency
+ * @input_max: Maximum input frequency
+ * @cf_min: Minimum comparison frequency
+ * @cf_max: Maximum comparison frequency
+ * @vco_min: Minimum VCO frequency
+ * @vco_max: Maximum VCO frequency
+ * @base_reg: PLL base reg offset
+ * @misc_reg: PLL misc reg offset
+ * @lock_reg: PLL lock reg offset
+ * @lock_bit_idx: Bit index for PLL lock status
+ * @lock_enable_bit_idx: Bit index to enable PLL lock
+ * @lock_delay: Delay in us if PLL lock is not used
+ */
+struct tegra_clk_pll_params {
+ unsigned long input_min;
+ unsigned long input_max;
+ unsigned long cf_min;
+ unsigned long cf_max;
+ unsigned long vco_min;
+ unsigned long vco_max;
+
+ u32 base_reg;
+ u32 misc_reg;
+ u32 lock_reg;
+ u32 lock_bit_idx;
+ u32 lock_enable_bit_idx;
+ int lock_delay;
+};
+
+/**
+ * struct tegra_clk_pll - Tegra PLL clock
+ *
+ * @hw: handle between common and hardware-specifix interfaces
+ * @clk_base: address of CAR controller
+ * @pmc: address of PMC, required to read override bits
+ * @freq_table: array of frequencies supported by PLL
+ * @params: PLL parameters
+ * @flags: PLL flags
+ * @fixed_rate: PLL rate if it is fixed
+ * @lock: register lock
+ * @divn_shift: shift to the feedback divider bit field
+ * @divn_width: width of the feedback divider bit field
+ * @divm_shift: shift to the input divider bit field
+ * @divm_width: width of the input divider bit field
+ * @divp_shift: shift to the post divider bit field
+ * @divp_width: width of the post divider bit field
+ *
+ * Flags:
+ * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
+ * PLL locking. If not set it will use lock_delay value to wait.
+ * TEGRA_PLL_HAS_CPCON - This flag indicates that CPCON value needs
+ * to be programmed to change output frequency of the PLL.
+ * TEGRA_PLL_SET_LFCON - This flag indicates that LFCON value needs
+ * to be programmed to change output frequency of the PLL.
+ * TEGRA_PLL_SET_DCCON - This flag indicates that DCCON value needs
+ * to be programmed to change output frequency of the PLL.
+ * TEGRA_PLLU - PLLU has inverted post divider. This flags indicated
+ * that it is PLLU and invert post divider value.
+ * TEGRA_PLLM - PLLM has additional override settings in PMC. This
+ * flag indicates that it is PLLM and use override settings.
+ * TEGRA_PLL_FIXED - We are not supposed to change output frequency
+ * of some plls.
+ * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
+ */
+struct tegra_clk_pll {
+ struct clk_hw hw;
+ void __iomem *clk_base;
+ void __iomem *pmc;
+ u8 flags;
+ unsigned long fixed_rate;
+ spinlock_t *lock;
+ u8 divn_shift;
+ u8 divn_width;
+ u8 divm_shift;
+ u8 divm_width;
+ u8 divp_shift;
+ u8 divp_width;
+ struct tegra_clk_pll_freq_table *freq_table;
+ struct tegra_clk_pll_params *params;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct tegra_clk_pll, hw)
+
+#define TEGRA_PLL_USE_LOCK BIT(0)
+#define TEGRA_PLL_HAS_CPCON BIT(1)
+#define TEGRA_PLL_SET_LFCON BIT(2)
+#define TEGRA_PLL_SET_DCCON BIT(3)
+#define TEGRA_PLLU BIT(4)
+#define TEGRA_PLLM BIT(5)
+#define TEGRA_PLL_FIXED BIT(6)
+#define TEGRA_PLLE_CONFIGURE BIT(7)
+
+extern const struct clk_ops tegra_clk_pll_ops;
+extern const struct clk_ops tegra_clk_plle_ops;
+struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+
+/**
+ * struct tegra_clk_pll_out - PLL divider down clock
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @reg: register containing the PLL divider
+ * @enb_bit_idx: bit to enable/disable PLL divider
+ * @rst_bit_idx: bit to reset PLL divider
+ * @lock: register lock
+ * @flags: hardware-specific flags
+ */
+struct tegra_clk_pll_out {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 enb_bit_idx;
+ u8 rst_bit_idx;
+ spinlock_t *lock;
+ u8 flags;
+};
+
+#define to_clk_pll_out(_hw) container_of(_hw, struct tegra_clk_pll_out, hw)
+
+extern const struct clk_ops tegra_clk_pll_out_ops;
+struct clk *tegra_clk_register_pll_out(const char *name,
+ const char *parent_name, void __iomem *reg, u8 enb_bit_idx,
+ u8 rst_bit_idx, unsigned long flags, u8 pll_div_flags,
+ spinlock_t *lock);
+
+/**
+ * struct tegra_clk_periph_regs - Registers controlling peripheral clock
+ *
+ * @enb_reg: read the enable status
+ * @enb_set_reg: write 1 to enable clock
+ * @enb_clr_reg: write 1 to disable clock
+ * @rst_reg: read the reset status
+ * @rst_set_reg: write 1 to assert the reset of peripheral
+ * @rst_clr_reg: write 1 to deassert the reset of peripheral
+ */
+struct tegra_clk_periph_regs {
+ u32 enb_reg;
+ u32 enb_set_reg;
+ u32 enb_clr_reg;
+ u32 rst_reg;
+ u32 rst_set_reg;
+ u32 rst_clr_reg;
+};
+
+/**
+ * struct tegra_clk_periph_gate - peripheral gate clock
+ *
+ * @magic: magic number to validate type
+ * @hw: handle between common and hardware-specific interfaces
+ * @clk_base: address of CAR controller
+ * @regs: Registers to control the peripheral
+ * @flags: hardware-specific flags
+ * @clk_num: Clock number
+ * @enable_refcnt: array to maintain reference count of the clock
+ *
+ * Flags:
+ * TEGRA_PERIPH_NO_RESET - This flag indicates that reset is not allowed
+ * for this module.
+ * TEGRA_PERIPH_MANUAL_RESET - This flag indicates not to reset module
+ * after clock enable and driver for the module is responsible for
+ * doing reset.
+ * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the
+ * bus to flush the write operation in apb bus. This flag indicates
+ * that this peripheral is in apb bus.
+ */
+struct tegra_clk_periph_gate {
+ u32 magic;
+ struct clk_hw hw;
+ void __iomem *clk_base;
+ u8 flags;
+ int clk_num;
+ int *enable_refcnt;
+ struct tegra_clk_periph_regs *regs;
+};
+
+#define to_clk_periph_gate(_hw) \
+ container_of(_hw, struct tegra_clk_periph_gate, hw)
+
+#define TEGRA_CLK_PERIPH_GATE_MAGIC 0x17760309
+
+#define TEGRA_PERIPH_NO_RESET BIT(0)
+#define TEGRA_PERIPH_MANUAL_RESET BIT(1)
+#define TEGRA_PERIPH_ON_APB BIT(2)
+
+void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
+extern const struct clk_ops tegra_clk_periph_gate_ops;
+struct clk *tegra_clk_register_periph_gate(const char *name,
+ const char *parent_name, u8 gate_flags, void __iomem *clk_base,
+ unsigned long flags, int clk_num,
+ struct tegra_clk_periph_regs *pregs, int *enable_refcnt);
+
+/**
+ * struct clk-periph - peripheral clock
+ *
+ * @magic: magic number to validate type
+ * @hw: handle between common and hardware-specific interfaces
+ * @mux: mux clock
+ * @divider: divider clock
+ * @gate: gate clock
+ * @mux_ops: mux clock ops
+ * @div_ops: divider clock ops
+ * @gate_ops: gate clock ops
+ */
+struct tegra_clk_periph {
+ u32 magic;
+ struct clk_hw hw;
+ struct clk_mux mux;
+ struct tegra_clk_frac_div divider;
+ struct tegra_clk_periph_gate gate;
+
+ const struct clk_ops *mux_ops;
+ const struct clk_ops *div_ops;
+ const struct clk_ops *gate_ops;
+};
+
+#define to_clk_periph(_hw) container_of(_hw, struct tegra_clk_periph, hw)
+
+#define TEGRA_CLK_PERIPH_MAGIC 0x18221223
+
+extern const struct clk_ops tegra_clk_periph_ops;
+struct clk *tegra_clk_register_periph(const char *name,
+ const char **parent_names, int num_parents,
+ struct tegra_clk_periph *periph, void __iomem *clk_base,
+ u32 offset);
+struct clk *tegra_clk_register_periph_nodiv(const char *name,
+ const char **parent_names, int num_parents,
+ struct tegra_clk_periph *periph, void __iomem *clk_base,
+ u32 offset);
+
+#define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags, \
+ _div_shift, _div_width, _div_frac_width, \
+ _div_flags, _clk_num, _enb_refcnt, _regs, \
+ _gate_flags) \
+ { \
+ .mux = { \
+ .flags = _mux_flags, \
+ .shift = _mux_shift, \
+ .width = _mux_width, \
+ }, \
+ .divider = { \
+ .flags = _div_flags, \
+ .shift = _div_shift, \
+ .width = _div_width, \
+ .frac_width = _div_frac_width, \
+ }, \
+ .gate = { \
+ .flags = _gate_flags, \
+ .clk_num = _clk_num, \
+ .enable_refcnt = _enb_refcnt, \
+ .regs = _regs, \
+ }, \
+ .mux_ops = &clk_mux_ops, \
+ .div_ops = &tegra_clk_frac_div_ops, \
+ .gate_ops = &tegra_clk_periph_gate_ops, \
+ }
+
+struct tegra_periph_init_data {
+ const char *name;
+ int clk_id;
+ const char **parent_names;
+ int num_parents;
+ struct tegra_clk_periph periph;
+ u32 offset;
+ const char *con_id;
+ const char *dev_id;
+};
+
+#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \
+ _mux_shift, _mux_width, _mux_flags, _div_shift, \
+ _div_width, _div_frac_width, _div_flags, _regs, \
+ _clk_num, _enb_refcnt, _gate_flags, _clk_id) \
+ { \
+ .name = _name, \
+ .clk_id = _clk_id, \
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width, \
+ _mux_flags, _div_shift, \
+ _div_width, _div_frac_width, \
+ _div_flags, _clk_num, \
+ _enb_refcnt, _regs, \
+ _gate_flags), \
+ .offset = _offset, \
+ .con_id = _con_id, \
+ .dev_id = _dev_id, \
+ }
+
+/**
+ * struct clk_super_mux - super clock
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @reg: register controlling multiplexer
+ * @width: width of the multiplexer bit field
+ * @flags: hardware-specific flags
+ * @div2_index: bit controlling divide-by-2
+ * @pllx_index: PLLX index in the parent list
+ * @lock: register lock
+ *
+ * Flags:
+ * TEGRA_DIVIDER_2 - LP cluster has additional divider. This flag indicates
+ * that this is LP cluster clock.
+ */
+struct tegra_clk_super_mux {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 width;
+ u8 flags;
+ u8 div2_index;
+ u8 pllx_index;
+ spinlock_t *lock;
+};
+
+#define to_clk_super_mux(_hw) container_of(_hw, struct tegra_clk_super_mux, hw)
+
+#define TEGRA_DIVIDER_2 BIT(0)
+
+extern const struct clk_ops tegra_clk_super_ops;
+struct clk *tegra_clk_register_super_mux(const char *name,
+ const char **parent_names, u8 num_parents,
+ unsigned long flags, void __iomem *reg, u8 clk_super_flags,
+ u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock);
+
+/**
+ * struct clk_init_tabel - clock initialization table
+ * @clk_id: clock id as mentioned in device tree bindings
+ * @parent_id: parent clock id as mentioned in device tree bindings
+ * @rate: rate to set
+ * @state: enable/disable
+ */
+struct tegra_clk_init_table {
+ unsigned int clk_id;
+ unsigned int parent_id;
+ unsigned long rate;
+ int state;
+};
+
+/**
+ * struct clk_duplicate - duplicate clocks
+ * @clk_id: clock id as mentioned in device tree bindings
+ * @lookup: duplicate lookup entry for the clock
+ */
+struct tegra_clk_duplicate {
+ int clk_id;
+ struct clk_lookup lookup;
+};
+
+#define TEGRA_CLK_DUPLICATE(_clk_id, _dev, _con) \
+ { \
+ .clk_id = _clk_id, \
+ .lookup = { \
+ .dev_id = _dev, \
+ .con_id = _con, \
+ }, \
+ }
+
+void tegra_init_from_table(struct tegra_clk_init_table *tbl,
+ struct clk *clks[], int clk_max);
+
+void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
+ struct clk *clks[], int clk_max);
+
+#endif /* TEGRA_CLK_H */
--
1.7.10.4
^ permalink raw reply related
* [PATCH V5 1/3] clk: tegra: add Tegra specific clocks
From: Stephen Warren @ 2013-01-17 21:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130117155307.GF4118@tbergstrom-lnx.Nvidia.com>
On 01/17/2013 08:53 AM, Peter De Schrijver wrote:
> On Wed, Jan 16, 2013 at 09:52:53PM +0100, Stephen Warren wrote:
>> From: Prashant Gaikwad <pgaikwad@nvidia.com>
>>
>> Add Tegra specific clocks, pll, pll_out, peripheral, frac_divider, super.
>>
>> Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
>> [swarren: alloc sizeof(*foo) not sizeof(struct foo), add comments re:
>> storing pointers to stack variables, make a timeout loop more idiomatic,
>> use _clk_pll_disable() not clk_disable_pll() from _program_pll() to
>> avoid redundant lock operations, unified tegra_clk_periph() and
>> tegra_clk_periph_nodiv(), unified tegra_clk_pll{,e}, rename all clock
>> registration functions so they don't have the same name as the clock
>> structs.]
>> Signed-off-by: Stephen Warren <swarren@nvidia.com>
>
> ...
>
>> +static int clk_plle_enable(struct clk_hw *hw)
>> +{
>> + struct tegra_clk_pll *pll = to_clk_pll(hw);
>> + unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
>> + struct tegra_clk_pll_freq_table sel;
>> + u32 val;
>> + int err;
>> +
>> + if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
>> + return -EBUSY;
>> +
>
> I think -EINVAL would be more appropriate here?
Yes. I fixed this and the PLL function parameters you mentioned in your
other email.
^ permalink raw reply
* [PATCH 1/2] ARM: DT: tegra: Add Colibri T20 512MB COM
From: Lucas Stach @ 2013-01-17 21:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F86533.9010000@wwwdotorg.org>
Am Donnerstag, den 17.01.2013, 13:55 -0700 schrieb Stephen Warren:
> On 01/17/2013 04:59 AM, Lucas Stach wrote:
> > This adds the device tree include file for the Toradex Colibri T20
> > Computer on Module (COM). It's only valid for the 512MB RAM version of
> > the module, as the 256MB version needs different EMC tables and flash
> > configuration. To make this clear the suffix -512 was added to the board
> > compatible string.
> >
> > The Colibri T20 uses a Tegra2 SoC and has onboard USB Ethernet and AC97
> > sound.
> >
> > Still some things like onboard NAND support missing, but should be a
> > good base for further development.
>
> > diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi
>
> > + temperature-sensor at 4c {
> > + compatible = "national,lm95245";
>
> You should probably add that compatible value to
> Documentation/devicetree/bindings/i2c/trivial-devices.txt.
>
Yep, will send a separate patch for this.
> > + i2c at 7000c000 {
> > + clock-frequency = <400000>;
> > + };
> > +
> > + i2c_ddc: i2c at 7000c400 {
> > + clock-frequency = <100000>;
> > + };
> > +
> > + i2c at 7000c500 {
> > + clock-frequency = <400000>;
> > + };
>
> > + serial at 70006000 {
> > + clock-frequency = <216000000>;
> > + };
> > +
> > + serial at 70006300 {
> > + clock-frequency = <216000000>;
> > + };
> > +
> > + usb at c5000000 {
> > + dr_mode = "otg";
> > + };
> > +
> > + usb at c5004000 {
> > + status = "okay";
> > + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
> > + };
> > +
> > + sdhci at c8000600 {
> > + cd-gpios = <&gpio 23 0>; /* gpio PC7 */
> > + vmmc-supply = <&ldo5_reg>;
> > + vqmmc-supply = <&vcc_sd_reg>;
> > + };
>
> I assume that all of those nodes are meant to have status="okay"?
>
> Oh, I see those are in the top-level board .dts file. You may as well
> put all the properties there; stuff like the GPIOs and regulators at
> least would be purely specific to the individual board, and not the COM.
>
I would like to keep everything that is defined by the COM to reside in
the COM dtsi. You are right that the regulator in this case is board
specific and should be moved to the board file, I missed this while
splitting things out. But at least the GPIO is defined by the fixed COM
pinout.
> I guess we should really move the serial node's clock-frequency property
> in the SoC .dtsi files.
>
Might be a nice cleanup.
> > + com_regulators {
>
> I think just call that "regulators"; the final board .dts file can
> easily add more sub-nodes to this node, so there's no need to try and
> avoid any naming conflict here. See Cardhu as an example.
>
I don't really see the benefit of merging those nodes. They are separate
regulators, some are located on the COM, others on the carrier board. So
I would like to keep them in separate nodes, unless you have strong
feelings to change this.
^ permalink raw reply
* [PATCH v7 19/22] ARM: OMAP3: clock data: get rid of unused USB host clock aliases and dummies
From: Felipe Balbi @ 2013-01-17 21:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301171854280.14118@utopia.booyaka.com>
Hi,
On Thu, Jan 17, 2013 at 07:00:00PM +0000, Paul Walmsley wrote:
> Hi Roger,
>
> On Thu, 17 Jan 2013, Tony Lindgren wrote:
>
> > * Roger Quadros <rogerq@ti.com> [130117 03:34]:
> > > We don't need multiple aliases for the OMAP USB host clocks and neither
> > > the dummy clocks so remove them.
> >
> > It's best that Paul queues this and the next patch as these clock alias
> > clean-up patches can be done separately. That way the dependency between
> > arch/arm/*omap* code is cut away as these files should be moved to live
> > under drivers/clk/omap.
>
> Per Tony's request, I'll queue these two cleanup patches for 3.10 -- or
> whatever Linus will call it.
do you mean v3.9 ?
--
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130117/6f1fd568/attachment.sig>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox