Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib: add support for stmp-style devices

MX23/28 use IP cores which follow a register layout I have first seen on
STMP3xxx SoCs. In this layout, every register actually has four u32:

1.) to store a value directly
2.) a SET register where every 1-bit sets the corresponding bit,
others are unaffected
3.) same with a CLR register
4.) same with a TOG (toggle) register

Also, the 2 MSBs in register 0 are always the same and can be used to reset
the IP core.

All this is strictly speaking not mach-specific (but IP core specific) and,
thus, doesn't need to be in mach-mxs/include. At least mx6 also uses IP cores
following this stmp-style. So:

Introduce a stmp-style device, put the code and defines for that in a public
place (lib/), and let drivers for stmp-style devices select that code.
To avoid regressions and ease reviewing, the actual code is simply copied from
mach-mxs. It definately wants updates, but those need a seperate patch series.

Voila, mach dependency gone, reusable code introduced. Note that I didn't
remove the duplicated code from mach-mxs yet, first the drivers have to be
converted.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Dong Aisheng <dong.aisheng@linaro.org>

+105
+20
include/linux/stmp_device.h
··· 1 + /* 2 + * basic functions for devices following the "stmp" style register layout 3 + * 4 + * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + */ 11 + 12 + #ifndef __STMP_DEVICE_H__ 13 + #define __STMP_DEVICE_H__ 14 + 15 + #define STMP_OFFSET_REG_SET 0x4 16 + #define STMP_OFFSET_REG_CLR 0x8 17 + #define STMP_OFFSET_REG_TOG 0xc 18 + 19 + extern int stmp_reset_block(void __iomem *); 20 + #endif /* __STMP_DEVICE_H__ */
+3
lib/Kconfig
··· 33 33 boolean 34 34 default n 35 35 36 + config STMP_DEVICE 37 + bool 38 + 36 39 config CRC_CCITT 37 40 tristate "CRC-CCITT functions" 38 41 help
+2
lib/Makefile
··· 123 123 124 124 obj-$(CONFIG_CLZ_TAB) += clz_tab.o 125 125 126 + obj-$(CONFIG_STMP_DEVICE) += stmp_device.o 127 + 126 128 hostprogs-y := gen_crc32table 127 129 clean-files := crc32table.h 128 130
+80
lib/stmp_device.c
··· 1 + /* 2 + * Copyright (C) 1999 ARM Limited 3 + * Copyright (C) 2000 Deep Blue Solutions Ltd 4 + * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved. 5 + * Copyright 2008 Juergen Beisert, kernel@pengutronix.de 6 + * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com 7 + * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License as published by 11 + * the Free Software Foundation; either version 2 of the License, or 12 + * (at your option) any later version. 13 + */ 14 + 15 + #include <linux/io.h> 16 + #include <linux/errno.h> 17 + #include <linux/delay.h> 18 + #include <linux/module.h> 19 + #include <linux/stmp_device.h> 20 + 21 + #define STMP_MODULE_CLKGATE (1 << 30) 22 + #define STMP_MODULE_SFTRST (1 << 31) 23 + 24 + /* 25 + * Clear the bit and poll it cleared. This is usually called with 26 + * a reset address and mask being either SFTRST(bit 31) or CLKGATE 27 + * (bit 30). 28 + */ 29 + static int stmp_clear_poll_bit(void __iomem *addr, u32 mask) 30 + { 31 + int timeout = 0x400; 32 + 33 + writel(mask, addr + STMP_OFFSET_REG_CLR); 34 + udelay(1); 35 + while ((readl(addr) & mask) && --timeout) 36 + /* nothing */; 37 + 38 + return !timeout; 39 + } 40 + 41 + int stmp_reset_block(void __iomem *reset_addr) 42 + { 43 + int ret; 44 + int timeout = 0x400; 45 + 46 + /* clear and poll SFTRST */ 47 + ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_SFTRST); 48 + if (unlikely(ret)) 49 + goto error; 50 + 51 + /* clear CLKGATE */ 52 + writel(STMP_MODULE_CLKGATE, reset_addr + STMP_OFFSET_REG_CLR); 53 + 54 + /* set SFTRST to reset the block */ 55 + writel(STMP_MODULE_SFTRST, reset_addr + STMP_OFFSET_REG_SET); 56 + udelay(1); 57 + 58 + /* poll CLKGATE becoming set */ 59 + while ((!(readl(reset_addr) & STMP_MODULE_CLKGATE)) && --timeout) 60 + /* nothing */; 61 + if (unlikely(!timeout)) 62 + goto error; 63 + 64 + /* clear and poll SFTRST */ 65 + ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_SFTRST); 66 + if (unlikely(ret)) 67 + goto error; 68 + 69 + /* clear and poll CLKGATE */ 70 + ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_CLKGATE); 71 + if (unlikely(ret)) 72 + goto error; 73 + 74 + return 0; 75 + 76 + error: 77 + pr_err("%s(%p): module reset timeout\n", __func__, reset_addr); 78 + return -ETIMEDOUT; 79 + } 80 + EXPORT_SYMBOL(stmp_reset_block);