aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-07-03 18:13:18 -0400
committerTejun Heo <tj@kernel.org>2009-07-03 18:13:18 -0400
commitc43768cbb7655ea5ff782ae250f6e2ef4297cf98 (patch)
tree3982e41dde3eecaa3739a5d1a8ed18d04bd74f01 /arch/xtensa
parent1a8dd307cc0a2119be4e578c517795464e6dabba (diff)
parent746a99a5af60ee676afa2ba469ccd1373493c7e7 (diff)
Merge branch 'master' into for-next
Pull linus#master to merge PER_CPU_DEF_ATTRIBUTES and alpha build fix changes. As alpha in percpu tree uses 'weak' attribute instead of inline assembly, there's no need for __used attribute. Conflicts: arch/alpha/include/asm/percpu.h arch/mn10300/kernel/vmlinux.lds.S include/linux/percpu-defs.h
Diffstat (limited to 'arch/xtensa')
-rw-r--r--arch/xtensa/configs/s6105_defconfig105
-rw-r--r--arch/xtensa/include/asm/cacheflush.h95
-rw-r--r--arch/xtensa/include/asm/gpio.h8
-rw-r--r--arch/xtensa/include/asm/irq.h12
-rw-r--r--arch/xtensa/kernel/irq.c2
-rw-r--r--arch/xtensa/platforms/s6105/device.c94
-rw-r--r--arch/xtensa/platforms/s6105/setup.c11
-rw-r--r--arch/xtensa/variants/s6000/Makefile2
-rw-r--r--arch/xtensa/variants/s6000/dmac.c173
-rw-r--r--arch/xtensa/variants/s6000/gpio.c163
-rw-r--r--arch/xtensa/variants/s6000/include/variant/dmac.h387
-rw-r--r--arch/xtensa/variants/s6000/include/variant/gpio.h2
-rw-r--r--arch/xtensa/variants/s6000/include/variant/irq.h6
13 files changed, 1044 insertions, 16 deletions
diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig
index 768bee006037..bb84fbc9921f 100644
--- a/arch/xtensa/configs/s6105_defconfig
+++ b/arch/xtensa/configs/s6105_defconfig
@@ -263,7 +263,54 @@ CONFIG_HAVE_IDE=y
263# CONFIG_SCSI_NETLINK is not set 263# CONFIG_SCSI_NETLINK is not set
264# CONFIG_ATA is not set 264# CONFIG_ATA is not set
265# CONFIG_MD is not set 265# CONFIG_MD is not set
266# CONFIG_NETDEVICES is not set 266CONFIG_NETDEVICES=y
267# CONFIG_DUMMY is not set
268# CONFIG_BONDING is not set
269# CONFIG_MACVLAN is not set
270# CONFIG_EQUALIZER is not set
271# CONFIG_TUN is not set
272# CONFIG_VETH is not set
273CONFIG_PHYLIB=y
274
275#
276# MII PHY device drivers
277#
278# CONFIG_MARVELL_PHY is not set
279# CONFIG_DAVICOM_PHY is not set
280# CONFIG_QSEMI_PHY is not set
281# CONFIG_LXT_PHY is not set
282# CONFIG_CICADA_PHY is not set
283# CONFIG_VITESSE_PHY is not set
284CONFIG_SMSC_PHY=y
285# CONFIG_BROADCOM_PHY is not set
286# CONFIG_ICPLUS_PHY is not set
287# CONFIG_REALTEK_PHY is not set
288# CONFIG_NATIONAL_PHY is not set
289# CONFIG_STE10XP is not set
290# CONFIG_LSI_ET1011C_PHY is not set
291# CONFIG_FIXED_PHY is not set
292# CONFIG_MDIO_BITBANG is not set
293# CONFIG_NET_ETHERNET is not set
294CONFIG_NETDEV_1000=y
295CONFIG_S6GMAC=y
296# CONFIG_NETDEV_10000 is not set
297
298#
299# Wireless LAN
300#
301# CONFIG_WLAN_PRE80211 is not set
302# CONFIG_WLAN_80211 is not set
303# CONFIG_IWLWIFI_LEDS is not set
304
305#
306# Enable WiMAX (Networking options) to see the WiMAX drivers
307#
308# CONFIG_WAN is not set
309# CONFIG_PPP is not set
310# CONFIG_SLIP is not set
311# CONFIG_NETCONSOLE is not set
312# CONFIG_NETPOLL is not set
313# CONFIG_NET_POLL_CONTROLLER is not set
267# CONFIG_ISDN is not set 314# CONFIG_ISDN is not set
268# CONFIG_PHONE is not set 315# CONFIG_PHONE is not set
269 316
@@ -304,8 +351,6 @@ CONFIG_UNIX98_PTYS=y
304# CONFIG_LEGACY_PTYS is not set 351# CONFIG_LEGACY_PTYS is not set
305# CONFIG_IPMI_HANDLER is not set 352# CONFIG_IPMI_HANDLER is not set
306# CONFIG_HW_RANDOM is not set 353# CONFIG_HW_RANDOM is not set
307# CONFIG_RTC is not set
308# CONFIG_GEN_RTC is not set
309# CONFIG_R3964 is not set 354# CONFIG_R3964 is not set
310# CONFIG_RAW_DRIVER is not set 355# CONFIG_RAW_DRIVER is not set
311# CONFIG_TCG_TPM is not set 356# CONFIG_TCG_TPM is not set
@@ -387,7 +432,59 @@ CONFIG_SSB_POSSIBLE=y
387# CONFIG_MEMSTICK is not set 432# CONFIG_MEMSTICK is not set
388# CONFIG_NEW_LEDS is not set 433# CONFIG_NEW_LEDS is not set
389# CONFIG_ACCESSIBILITY is not set 434# CONFIG_ACCESSIBILITY is not set
390# CONFIG_RTC_CLASS is not set 435CONFIG_RTC_LIB=y
436CONFIG_RTC_CLASS=y
437CONFIG_RTC_HCTOSYS=y
438CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
439# CONFIG_RTC_DEBUG is not set
440
441#
442# RTC interfaces
443#
444# CONFIG_RTC_INTF_SYSFS is not set
445# CONFIG_RTC_INTF_PROC is not set
446# CONFIG_RTC_INTF_DEV is not set
447# CONFIG_RTC_DRV_TEST is not set
448
449#
450# I2C RTC drivers
451#
452# CONFIG_RTC_DRV_DS1307 is not set
453# CONFIG_RTC_DRV_DS1374 is not set
454# CONFIG_RTC_DRV_DS1672 is not set
455# CONFIG_RTC_DRV_MAX6900 is not set
456# CONFIG_RTC_DRV_RS5C372 is not set
457# CONFIG_RTC_DRV_ISL1208 is not set
458# CONFIG_RTC_DRV_X1205 is not set
459# CONFIG_RTC_DRV_PCF8563 is not set
460# CONFIG_RTC_DRV_PCF8583 is not set
461CONFIG_RTC_DRV_M41T80=y
462# CONFIG_RTC_DRV_M41T80_WDT is not set
463# CONFIG_RTC_DRV_S35390A is not set
464# CONFIG_RTC_DRV_FM3130 is not set
465# CONFIG_RTC_DRV_RX8581 is not set
466
467#
468# SPI RTC drivers
469#
470
471#
472# Platform RTC drivers
473#
474# CONFIG_RTC_DRV_DS1286 is not set
475# CONFIG_RTC_DRV_DS1511 is not set
476# CONFIG_RTC_DRV_DS1553 is not set
477# CONFIG_RTC_DRV_DS1742 is not set
478# CONFIG_RTC_DRV_STK17TA8 is not set
479# CONFIG_RTC_DRV_M48T86 is not set
480# CONFIG_RTC_DRV_M48T35 is not set
481# CONFIG_RTC_DRV_M48T59 is not set
482# CONFIG_RTC_DRV_BQ4802 is not set
483# CONFIG_RTC_DRV_V3020 is not set
484
485#
486# on-CPU RTC drivers
487#
391# CONFIG_DMADEVICES is not set 488# CONFIG_DMADEVICES is not set
392# CONFIG_UIO is not set 489# CONFIG_UIO is not set
393# CONFIG_STAGING is not set 490# CONFIG_STAGING is not set
diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h
index 8fc1c0c8de07..b7b8fbe47c77 100644
--- a/arch/xtensa/include/asm/cacheflush.h
+++ b/arch/xtensa/include/asm/cacheflush.h
@@ -155,5 +155,100 @@ extern void copy_from_user_page(struct vm_area_struct*, struct page*,
155 155
156#endif 156#endif
157 157
158#define XTENSA_CACHEBLK_LOG2 29
159#define XTENSA_CACHEBLK_SIZE (1 << XTENSA_CACHEBLK_LOG2)
160#define XTENSA_CACHEBLK_MASK (7 << XTENSA_CACHEBLK_LOG2)
161
162#if XCHAL_HAVE_CACHEATTR
163static inline u32 xtensa_get_cacheattr(void)
164{
165 u32 r;
166 asm volatile(" rsr %0, CACHEATTR" : "=a"(r));
167 return r;
168}
169
170static inline u32 xtensa_get_dtlb1(u32 addr)
171{
172 u32 r = addr & XTENSA_CACHEBLK_MASK;
173 return r | ((xtensa_get_cacheattr() >> (r >> (XTENSA_CACHEBLK_LOG2-2)))
174 & 0xF);
175}
176#else
177static inline u32 xtensa_get_dtlb1(u32 addr)
178{
179 u32 r;
180 asm volatile(" rdtlb1 %0, %1" : "=a"(r) : "a"(addr));
181 asm volatile(" dsync");
182 return r;
183}
184
185static inline u32 xtensa_get_cacheattr(void)
186{
187 u32 r = 0;
188 u32 a = 0;
189 do {
190 a -= XTENSA_CACHEBLK_SIZE;
191 r = (r << 4) | (xtensa_get_dtlb1(a) & 0xF);
192 } while (a);
193 return r;
194}
195#endif
196
197static inline int xtensa_need_flush_dma_source(u32 addr)
198{
199 return (xtensa_get_dtlb1(addr) & ((1 << XCHAL_CA_BITS) - 1)) >= 4;
200}
201
202static inline int xtensa_need_invalidate_dma_destination(u32 addr)
203{
204 return (xtensa_get_dtlb1(addr) & ((1 << XCHAL_CA_BITS) - 1)) != 2;
205}
206
207static inline void flush_dcache_unaligned(u32 addr, u32 size)
208{
209 u32 cnt;
210 if (size) {
211 cnt = (size + ((XCHAL_DCACHE_LINESIZE - 1) & addr)
212 + XCHAL_DCACHE_LINESIZE - 1) / XCHAL_DCACHE_LINESIZE;
213 while (cnt--) {
214 asm volatile(" dhwb %0, 0" : : "a"(addr));
215 addr += XCHAL_DCACHE_LINESIZE;
216 }
217 asm volatile(" dsync");
218 }
219}
220
221static inline void invalidate_dcache_unaligned(u32 addr, u32 size)
222{
223 int cnt;
224 if (size) {
225 asm volatile(" dhwbi %0, 0 ;" : : "a"(addr));
226 cnt = (size + ((XCHAL_DCACHE_LINESIZE - 1) & addr)
227 - XCHAL_DCACHE_LINESIZE - 1) / XCHAL_DCACHE_LINESIZE;
228 while (cnt-- > 0) {
229 asm volatile(" dhi %0, %1" : : "a"(addr),
230 "n"(XCHAL_DCACHE_LINESIZE));
231 addr += XCHAL_DCACHE_LINESIZE;
232 }
233 asm volatile(" dhwbi %0, %1" : : "a"(addr),
234 "n"(XCHAL_DCACHE_LINESIZE));
235 asm volatile(" dsync");
236 }
237}
238
239static inline void flush_invalidate_dcache_unaligned(u32 addr, u32 size)
240{
241 u32 cnt;
242 if (size) {
243 cnt = (size + ((XCHAL_DCACHE_LINESIZE - 1) & addr)
244 + XCHAL_DCACHE_LINESIZE - 1) / XCHAL_DCACHE_LINESIZE;
245 while (cnt--) {
246 asm volatile(" dhwbi %0, 0" : : "a"(addr));
247 addr += XCHAL_DCACHE_LINESIZE;
248 }
249 asm volatile(" dsync");
250 }
251}
252
158#endif /* __KERNEL__ */ 253#endif /* __KERNEL__ */
159#endif /* _XTENSA_CACHEFLUSH_H */ 254#endif /* _XTENSA_CACHEFLUSH_H */
diff --git a/arch/xtensa/include/asm/gpio.h b/arch/xtensa/include/asm/gpio.h
index 0763b0763960..a8c9fc46c790 100644
--- a/arch/xtensa/include/asm/gpio.h
+++ b/arch/xtensa/include/asm/gpio.h
@@ -38,14 +38,14 @@ static inline int gpio_cansleep(unsigned int gpio)
38 return __gpio_cansleep(gpio); 38 return __gpio_cansleep(gpio);
39} 39}
40 40
41/*
42 * Not implemented, yet.
43 */
44static inline int gpio_to_irq(unsigned int gpio) 41static inline int gpio_to_irq(unsigned int gpio)
45{ 42{
46 return -ENOSYS; 43 return __gpio_to_irq(gpio);
47} 44}
48 45
46/*
47 * Not implemented, yet.
48 */
49static inline int irq_to_gpio(unsigned int irq) 49static inline int irq_to_gpio(unsigned int irq)
50{ 50{
51 return -EINVAL; 51 return -EINVAL;
diff --git a/arch/xtensa/include/asm/irq.h b/arch/xtensa/include/asm/irq.h
index dfac82dc52ad..4c0ccc9c4f4c 100644
--- a/arch/xtensa/include/asm/irq.h
+++ b/arch/xtensa/include/asm/irq.h
@@ -11,6 +11,7 @@
11#ifndef _XTENSA_IRQ_H 11#ifndef _XTENSA_IRQ_H
12#define _XTENSA_IRQ_H 12#define _XTENSA_IRQ_H
13 13
14#include <linux/init.h>
14#include <platform/hardware.h> 15#include <platform/hardware.h>
15#include <variant/core.h> 16#include <variant/core.h>
16 17
@@ -21,11 +22,20 @@ static inline void variant_irq_enable(unsigned int irq) { }
21static inline void variant_irq_disable(unsigned int irq) { } 22static inline void variant_irq_disable(unsigned int irq) { }
22#endif 23#endif
23 24
25#ifndef VARIANT_NR_IRQS
26# define VARIANT_NR_IRQS 0
27#endif
24#ifndef PLATFORM_NR_IRQS 28#ifndef PLATFORM_NR_IRQS
25# define PLATFORM_NR_IRQS 0 29# define PLATFORM_NR_IRQS 0
26#endif 30#endif
27#define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS 31#define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
28#define NR_IRQS (XTENSA_NR_IRQS + PLATFORM_NR_IRQS) 32#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS)
33
34#if VARIANT_NR_IRQS == 0
35static inline void variant_init_irq(void) { }
36#else
37void variant_init_irq(void) __init;
38#endif
29 39
30static __inline__ int irq_canonicalize(int irq) 40static __inline__ int irq_canonicalize(int irq)
31{ 41{
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index a36c85edd045..a1badb32fcda 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -197,4 +197,6 @@ void __init init_IRQ(void)
197 } 197 }
198 198
199 cached_irq_mask = 0; 199 cached_irq_mask = 0;
200
201 variant_init_irq();
200} 202}
diff --git a/arch/xtensa/platforms/s6105/device.c b/arch/xtensa/platforms/s6105/device.c
index 78b08be5a92d..65333ffefb07 100644
--- a/arch/xtensa/platforms/s6105/device.c
+++ b/arch/xtensa/platforms/s6105/device.c
@@ -5,14 +5,27 @@
5 */ 5 */
6 6
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/gpio.h>
8#include <linux/init.h> 9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/phy.h>
9#include <linux/platform_device.h> 12#include <linux/platform_device.h>
10#include <linux/serial.h> 13#include <linux/serial.h>
11#include <linux/serial_8250.h> 14#include <linux/serial_8250.h>
12 15
13#include <variant/hardware.h> 16#include <variant/hardware.h>
17#include <variant/dmac.h>
14 18
19#include <platform/gpio.h>
20
21#define GPIO3_INTNUM 3
15#define UART_INTNUM 4 22#define UART_INTNUM 4
23#define GMAC_INTNUM 5
24
25static const signed char gpio3_irq_mappings[] = {
26 S6_INTC_GPIO(3),
27 -1
28};
16 29
17static const signed char uart_irq_mappings[] = { 30static const signed char uart_irq_mappings[] = {
18 S6_INTC_UART(0), 31 S6_INTC_UART(0),
@@ -20,8 +33,18 @@ static const signed char uart_irq_mappings[] = {
20 -1, 33 -1,
21}; 34};
22 35
36static const signed char gmac_irq_mappings[] = {
37 S6_INTC_GMAC_STAT,
38 S6_INTC_GMAC_ERR,
39 S6_INTC_DMA_HOSTTERMCNT(0),
40 S6_INTC_DMA_HOSTTERMCNT(1),
41 -1
42};
43
23const signed char *platform_irq_mappings[NR_IRQS] = { 44const signed char *platform_irq_mappings[NR_IRQS] = {
45 [GPIO3_INTNUM] = gpio3_irq_mappings,
24 [UART_INTNUM] = uart_irq_mappings, 46 [UART_INTNUM] = uart_irq_mappings,
47 [GMAC_INTNUM] = gmac_irq_mappings,
25}; 48};
26 49
27static struct plat_serial8250_port serial_platform_data[] = { 50static struct plat_serial8250_port serial_platform_data[] = {
@@ -46,6 +69,66 @@ static struct plat_serial8250_port serial_platform_data[] = {
46 { }, 69 { },
47}; 70};
48 71
72static struct resource s6_gmac_resource[] = {
73 {
74 .name = "mem",
75 .start = (resource_size_t)S6_REG_GMAC,
76 .end = (resource_size_t)S6_REG_GMAC + 0x10000 - 1,
77 .flags = IORESOURCE_MEM,
78 },
79 {
80 .name = "dma",
81 .start = (resource_size_t)
82 DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX),
83 .end = (resource_size_t)
84 DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACTX) + 0x100 - 1,
85 .flags = IORESOURCE_DMA,
86 },
87 {
88 .name = "dma",
89 .start = (resource_size_t)
90 DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX),
91 .end = (resource_size_t)
92 DMA_CHNL(S6_REG_HIFDMA, S6_HIFDMA_GMACRX) + 0x100 - 1,
93 .flags = IORESOURCE_DMA,
94 },
95 {
96 .name = "io",
97 .start = (resource_size_t)S6_MEM_GMAC,
98 .end = (resource_size_t)S6_MEM_GMAC + 0x2000000 - 1,
99 .flags = IORESOURCE_IO,
100 },
101 {
102 .name = "irq",
103 .start = (resource_size_t)GMAC_INTNUM,
104 .flags = IORESOURCE_IRQ,
105 },
106 {
107 .name = "irq",
108 .start = (resource_size_t)PHY_POLL,
109 .flags = IORESOURCE_IRQ,
110 },
111};
112
113static int __init prepare_phy_irq(int pin)
114{
115 int irq;
116 if (gpio_request(pin, "s6gmac_phy") < 0)
117 goto fail;
118 if (gpio_direction_input(pin) < 0)
119 goto free;
120 irq = gpio_to_irq(pin);
121 if (irq < 0)
122 goto free;
123 if (set_irq_type(irq, IRQ_TYPE_LEVEL_LOW) < 0)
124 goto free;
125 return irq;
126free:
127 gpio_free(pin);
128fail:
129 return PHY_POLL;
130}
131
49static struct platform_device platform_devices[] = { 132static struct platform_device platform_devices[] = {
50 { 133 {
51 .name = "serial8250", 134 .name = "serial8250",
@@ -54,12 +137,23 @@ static struct platform_device platform_devices[] = {
54 .platform_data = serial_platform_data, 137 .platform_data = serial_platform_data,
55 }, 138 },
56 }, 139 },
140 {
141 .name = "s6gmac",
142 .id = 0,
143 .resource = s6_gmac_resource,
144 .num_resources = ARRAY_SIZE(s6_gmac_resource),
145 },
146 {
147 I2C_BOARD_INFO("m41t62", S6I2C_ADDR_M41T62),
148 },
57}; 149};
58 150
59static int __init device_init(void) 151static int __init device_init(void)
60{ 152{
61 int i; 153 int i;
62 154
155 s6_gmac_resource[5].start = prepare_phy_irq(GPIO_PHY_IRQ);
156
63 for (i = 0; i < ARRAY_SIZE(platform_devices); i++) 157 for (i = 0; i < ARRAY_SIZE(platform_devices); i++)
64 platform_device_register(&platform_devices[i]); 158 platform_device_register(&platform_devices[i]);
65 return 0; 159 return 0;
diff --git a/arch/xtensa/platforms/s6105/setup.c b/arch/xtensa/platforms/s6105/setup.c
index 855ddeadc43d..86ce730f7913 100644
--- a/arch/xtensa/platforms/s6105/setup.c
+++ b/arch/xtensa/platforms/s6105/setup.c
@@ -35,12 +35,21 @@ void __init platform_setup(char **cmdline)
35{ 35{
36 unsigned long reg; 36 unsigned long reg;
37 37
38 reg = readl(S6_REG_GREG1 + S6_GREG1_PLLSEL);
39 reg &= ~(S6_GREG1_PLLSEL_GMAC_MASK << S6_GREG1_PLLSEL_GMAC |
40 S6_GREG1_PLLSEL_GMII_MASK << S6_GREG1_PLLSEL_GMII);
41 reg |= S6_GREG1_PLLSEL_GMAC_125MHZ << S6_GREG1_PLLSEL_GMAC |
42 S6_GREG1_PLLSEL_GMII_125MHZ << S6_GREG1_PLLSEL_GMII;
43 writel(reg, S6_REG_GREG1 + S6_GREG1_PLLSEL);
44
38 reg = readl(S6_REG_GREG1 + S6_GREG1_CLKGATE); 45 reg = readl(S6_REG_GREG1 + S6_GREG1_CLKGATE);
39 reg &= ~(1 << S6_GREG1_BLOCK_SB); 46 reg &= ~(1 << S6_GREG1_BLOCK_SB);
47 reg &= ~(1 << S6_GREG1_BLOCK_GMAC);
40 writel(reg, S6_REG_GREG1 + S6_GREG1_CLKGATE); 48 writel(reg, S6_REG_GREG1 + S6_GREG1_CLKGATE);
41 49
42 reg = readl(S6_REG_GREG1 + S6_GREG1_BLOCKENA); 50 reg = readl(S6_REG_GREG1 + S6_GREG1_BLOCKENA);
43 reg |= 1 << S6_GREG1_BLOCK_SB; 51 reg |= 1 << S6_GREG1_BLOCK_SB;
52 reg |= 1 << S6_GREG1_BLOCK_GMAC;
44 writel(reg, S6_REG_GREG1 + S6_GREG1_BLOCKENA); 53 writel(reg, S6_REG_GREG1 + S6_GREG1_BLOCKENA);
45 54
46 printk(KERN_NOTICE "S6105 on Stretch S6000 - " 55 printk(KERN_NOTICE "S6105 on Stretch S6000 - "
@@ -49,7 +58,7 @@ void __init platform_setup(char **cmdline)
49 58
50void __init platform_init(bp_tag_t *first) 59void __init platform_init(bp_tag_t *first)
51{ 60{
52 s6_gpio_init(); 61 s6_gpio_init(0);
53 gpio_request(GPIO_LED1_NGREEN, "led1_green"); 62 gpio_request(GPIO_LED1_NGREEN, "led1_green");
54 gpio_request(GPIO_LED1_RED, "led1_red"); 63 gpio_request(GPIO_LED1_RED, "led1_red");
55 gpio_direction_output(GPIO_LED1_NGREEN, 1); 64 gpio_direction_output(GPIO_LED1_NGREEN, 1);
diff --git a/arch/xtensa/variants/s6000/Makefile b/arch/xtensa/variants/s6000/Makefile
index d83f3805130c..3e7ef0a0c498 100644
--- a/arch/xtensa/variants/s6000/Makefile
+++ b/arch/xtensa/variants/s6000/Makefile
@@ -1,4 +1,4 @@
1# s6000 Makefile 1# s6000 Makefile
2 2
3obj-y += irq.o gpio.o 3obj-y += irq.o gpio.o dmac.o
4obj-$(CONFIG_XTENSA_CALIBRATE_CCOUNT) += delay.o 4obj-$(CONFIG_XTENSA_CALIBRATE_CCOUNT) += delay.o
diff --git a/arch/xtensa/variants/s6000/dmac.c b/arch/xtensa/variants/s6000/dmac.c
new file mode 100644
index 000000000000..dc7f7c573518
--- /dev/null
+++ b/arch/xtensa/variants/s6000/dmac.c
@@ -0,0 +1,173 @@
1/*
2 * Authors: Oskar Schirmer <os@emlix.com>
3 * Daniel Gloeckner <dg@emlix.com>
4 * (c) 2008 emlix GmbH http://www.emlix.com
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/io.h>
14#include <linux/types.h>
15#include <linux/errno.h>
16#include <linux/spinlock.h>
17#include <asm/cacheflush.h>
18#include <variant/dmac.h>
19
20/* DMA engine lookup */
21
22struct s6dmac_ctrl s6dmac_ctrl[S6_DMAC_NB];
23
24
25/* DMA control, per engine */
26
27void s6dmac_put_fifo_cache(u32 dmac, int chan, u32 src, u32 dst, u32 size)
28{
29 if (xtensa_need_flush_dma_source(src)) {
30 u32 base = src;
31 u32 span = size;
32 u32 chunk = readl(DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
33 if (chunk && (size > chunk)) {
34 s32 skip =
35 readl(DMA_CHNL(dmac, chan) + S6_DMA_SRCSKIP);
36 u32 gaps = (size+chunk-1)/chunk - 1;
37 if (skip >= 0) {
38 span += gaps * skip;
39 } else if (-skip > chunk) {
40 s32 decr = gaps * (chunk + skip);
41 base += decr;
42 span = chunk - decr;
43 } else {
44 span = max(span + gaps * skip,
45 (chunk + skip) * gaps - skip);
46 }
47 }
48 flush_dcache_unaligned(base, span);
49 }
50 if (xtensa_need_invalidate_dma_destination(dst)) {
51 u32 base = dst;
52 u32 span = size;
53 u32 chunk = readl(DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
54 if (chunk && (size > chunk)) {
55 s32 skip =
56 readl(DMA_CHNL(dmac, chan) + S6_DMA_DSTSKIP);
57 u32 gaps = (size+chunk-1)/chunk - 1;
58 if (skip >= 0) {
59 span += gaps * skip;
60 } else if (-skip > chunk) {
61 s32 decr = gaps * (chunk + skip);
62 base += decr;
63 span = chunk - decr;
64 } else {
65 span = max(span + gaps * skip,
66 (chunk + skip) * gaps - skip);
67 }
68 }
69 invalidate_dcache_unaligned(base, span);
70 }
71 s6dmac_put_fifo(dmac, chan, src, dst, size);
72}
73
74void s6dmac_disable_error_irqs(u32 dmac, u32 mask)
75{
76 unsigned long flags;
77 spinlock_t *spinl = &s6dmac_ctrl[_dmac_addr_index(dmac)].lock;
78 spin_lock_irqsave(spinl, flags);
79 _s6dmac_disable_error_irqs(dmac, mask);
80 spin_unlock_irqrestore(spinl, flags);
81}
82
83u32 s6dmac_int_sources(u32 dmac, u32 channel)
84{
85 u32 mask, ret, tmp;
86 mask = 1 << channel;
87
88 tmp = readl(dmac + S6_DMA_TERMCNTIRQSTAT);
89 tmp &= mask;
90 writel(tmp, dmac + S6_DMA_TERMCNTIRQCLR);
91 ret = tmp >> channel;
92
93 tmp = readl(dmac + S6_DMA_PENDCNTIRQSTAT);
94 tmp &= mask;
95 writel(tmp, dmac + S6_DMA_PENDCNTIRQCLR);
96 ret |= (tmp >> channel) << 1;
97
98 tmp = readl(dmac + S6_DMA_LOWWMRKIRQSTAT);
99 tmp &= mask;
100 writel(tmp, dmac + S6_DMA_LOWWMRKIRQCLR);
101 ret |= (tmp >> channel) << 2;
102
103 tmp = readl(dmac + S6_DMA_INTRAW0);
104 tmp &= (mask << S6_DMA_INT0_OVER) | (mask << S6_DMA_INT0_UNDER);
105 writel(tmp, dmac + S6_DMA_INTCLEAR0);
106
107 if (tmp & (mask << S6_DMA_INT0_UNDER))
108 ret |= 1 << 3;
109 if (tmp & (mask << S6_DMA_INT0_OVER))
110 ret |= 1 << 4;
111
112 tmp = readl(dmac + S6_DMA_MASTERERRINFO);
113 mask <<= S6_DMA_INT1_CHANNEL;
114 if (((tmp >> S6_DMA_MASTERERR_CHAN(0)) & S6_DMA_MASTERERR_CHAN_MASK)
115 == channel)
116 mask |= 1 << S6_DMA_INT1_MASTER;
117 if (((tmp >> S6_DMA_MASTERERR_CHAN(1)) & S6_DMA_MASTERERR_CHAN_MASK)
118 == channel)
119 mask |= 1 << (S6_DMA_INT1_MASTER + 1);
120 if (((tmp >> S6_DMA_MASTERERR_CHAN(2)) & S6_DMA_MASTERERR_CHAN_MASK)
121 == channel)
122 mask |= 1 << (S6_DMA_INT1_MASTER + 2);
123
124 tmp = readl(dmac + S6_DMA_INTRAW1) & mask;
125 writel(tmp, dmac + S6_DMA_INTCLEAR1);
126 ret |= ((tmp >> channel) & 1) << 5;
127 ret |= ((tmp >> S6_DMA_INT1_MASTER) & S6_DMA_INT1_MASTER_MASK) << 6;
128
129 return ret;
130}
131
132void s6dmac_release_chan(u32 dmac, int chan)
133{
134 if (chan >= 0)
135 s6dmac_disable_chan(dmac, chan);
136}
137
138
139/* global init */
140
141static inline void __init dmac_init(u32 dmac, u8 chan_nb)
142{
143 s6dmac_ctrl[S6_DMAC_INDEX(dmac)].dmac = dmac;
144 spin_lock_init(&s6dmac_ctrl[S6_DMAC_INDEX(dmac)].lock);
145 s6dmac_ctrl[S6_DMAC_INDEX(dmac)].chan_nb = chan_nb;
146 writel(S6_DMA_INT1_MASTER_MASK << S6_DMA_INT1_MASTER,
147 dmac + S6_DMA_INTCLEAR1);
148}
149
150static inline void __init dmac_master(u32 dmac,
151 u32 m0start, u32 m0end, u32 m1start, u32 m1end)
152{
153 writel(m0start, dmac + S6_DMA_MASTER0START);
154 writel(m0end - 1, dmac + S6_DMA_MASTER0END);
155 writel(m1start, dmac + S6_DMA_MASTER1START);
156 writel(m1end - 1, dmac + S6_DMA_MASTER1END);
157}
158
159static void __init s6_dmac_init(void)
160{
161 dmac_init(S6_REG_LMSDMA, S6_LMSDMA_NB);
162 dmac_master(S6_REG_LMSDMA,
163 S6_MEM_DDR, S6_MEM_PCIE_APER, S6_MEM_EFI, S6_MEM_GMAC);
164 dmac_init(S6_REG_NIDMA, S6_NIDMA_NB);
165 dmac_init(S6_REG_DPDMA, S6_DPDMA_NB);
166 dmac_master(S6_REG_DPDMA,
167 S6_MEM_DDR, S6_MEM_PCIE_APER, S6_REG_DP, S6_REG_DPDMA);
168 dmac_init(S6_REG_HIFDMA, S6_HIFDMA_NB);
169 dmac_master(S6_REG_HIFDMA,
170 S6_MEM_GMAC, S6_MEM_PCIE_CFG, S6_MEM_PCIE_APER, S6_MEM_AUX);
171}
172
173arch_initcall(s6_dmac_init);
diff --git a/arch/xtensa/variants/s6000/gpio.c b/arch/xtensa/variants/s6000/gpio.c
index 79317fdcf14c..380a70fff756 100644
--- a/arch/xtensa/variants/s6000/gpio.c
+++ b/arch/xtensa/variants/s6000/gpio.c
@@ -4,15 +4,20 @@
4 * Copyright (c) 2009 emlix GmbH 4 * Copyright (c) 2009 emlix GmbH
5 * Authors: Oskar Schirmer <os@emlix.com> 5 * Authors: Oskar Schirmer <os@emlix.com>
6 * Johannes Weiner <jw@emlix.com> 6 * Johannes Weiner <jw@emlix.com>
7 * Daniel Gloeckner <dg@emlix.com>
7 */ 8 */
9#include <linux/bitops.h>
8#include <linux/kernel.h> 10#include <linux/kernel.h>
9#include <linux/module.h> 11#include <linux/module.h>
10#include <linux/init.h> 12#include <linux/init.h>
11#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/irq.h>
12#include <linux/gpio.h> 15#include <linux/gpio.h>
13 16
14#include <variant/hardware.h> 17#include <variant/hardware.h>
15 18
19#define IRQ_BASE XTENSA_NR_IRQS
20
16#define S6_GPIO_DATA 0x000 21#define S6_GPIO_DATA 0x000
17#define S6_GPIO_IS 0x404 22#define S6_GPIO_IS 0x404
18#define S6_GPIO_IBE 0x408 23#define S6_GPIO_IBE 0x408
@@ -52,19 +57,175 @@ static void set(struct gpio_chip *chip, unsigned int off, int val)
52 writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off)); 57 writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off));
53} 58}
54 59
60static int to_irq(struct gpio_chip *chip, unsigned offset)
61{
62 if (offset < 8)
63 return offset + IRQ_BASE;
64 return -EINVAL;
65}
66
55static struct gpio_chip gpiochip = { 67static struct gpio_chip gpiochip = {
56 .owner = THIS_MODULE, 68 .owner = THIS_MODULE,
57 .direction_input = direction_input, 69 .direction_input = direction_input,
58 .get = get, 70 .get = get,
59 .direction_output = direction_output, 71 .direction_output = direction_output,
60 .set = set, 72 .set = set,
73 .to_irq = to_irq,
61 .base = 0, 74 .base = 0,
62 .ngpio = 24, 75 .ngpio = 24,
63 .can_sleep = 0, /* no blocking io needed */ 76 .can_sleep = 0, /* no blocking io needed */
64 .exported = 0, /* no exporting to userspace */ 77 .exported = 0, /* no exporting to userspace */
65}; 78};
66 79
67int s6_gpio_init(void) 80int s6_gpio_init(u32 afsel)
68{ 81{
82 writeb(afsel, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_AFSEL);
83 writeb(afsel >> 8, S6_REG_GPIO + S6_GPIO_BANK(1) + S6_GPIO_AFSEL);
84 writeb(afsel >> 16, S6_REG_GPIO + S6_GPIO_BANK(2) + S6_GPIO_AFSEL);
69 return gpiochip_add(&gpiochip); 85 return gpiochip_add(&gpiochip);
70} 86}
87
88static void ack(unsigned int irq)
89{
90 writeb(1 << (irq - IRQ_BASE), S6_REG_GPIO + S6_GPIO_IC);
91}
92
93static void mask(unsigned int irq)
94{
95 u8 r = readb(S6_REG_GPIO + S6_GPIO_IE);
96 r &= ~(1 << (irq - IRQ_BASE));
97 writeb(r, S6_REG_GPIO + S6_GPIO_IE);
98}
99
100static void unmask(unsigned int irq)
101{
102 u8 m = readb(S6_REG_GPIO + S6_GPIO_IE);
103 m |= 1 << (irq - IRQ_BASE);
104 writeb(m, S6_REG_GPIO + S6_GPIO_IE);
105}
106
107static int set_type(unsigned int irq, unsigned int type)
108{
109 const u8 m = 1 << (irq - IRQ_BASE);
110 irq_flow_handler_t handler;
111 struct irq_desc *desc;
112 u8 reg;
113
114 if (type == IRQ_TYPE_PROBE) {
115 if ((readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_AFSEL) & m)
116 || (readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IE) & m)
117 || readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_DIR
118 + S6_GPIO_MASK(irq - IRQ_BASE)))
119 return 0;
120 type = IRQ_TYPE_EDGE_BOTH;
121 }
122
123 reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IS);
124 if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
125 reg |= m;
126 handler = handle_level_irq;
127 } else {
128 reg &= ~m;
129 handler = handle_edge_irq;
130 }
131 writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IS);
132 desc = irq_to_desc(irq);
133 desc->handle_irq = handler;
134
135 reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IEV);
136 if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING))
137 reg |= m;
138 else
139 reg &= ~m;
140 writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IEV);
141
142 reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IBE);
143 if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
144 reg |= m;
145 else
146 reg &= ~m;
147 writeb(reg, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IBE);
148 return 0;
149}
150
151static struct irq_chip gpioirqs = {
152 .name = "GPIO",
153 .ack = ack,
154 .mask = mask,
155 .unmask = unmask,
156 .set_type = set_type,
157};
158
159static u8 demux_masks[4];
160
161static void demux_irqs(unsigned int irq, struct irq_desc *desc)
162{
163 u8 *mask = get_irq_desc_data(desc);
164 u8 pending;
165 int cirq;
166
167 desc->chip->mask(irq);
168 desc->chip->ack(irq);
169 pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask;
170 cirq = IRQ_BASE - 1;
171 while (pending) {
172 int n = ffs(pending);
173 cirq += n;
174 pending >>= n;
175 generic_handle_irq(cirq);
176 }
177 desc->chip->unmask(irq);
178}
179
180extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS];
181
182void __init variant_init_irq(void)
183{
184 int irq, n;
185 writeb(0, S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IE);
186 for (irq = n = 0; irq < XTENSA_NR_IRQS; irq++) {
187 const signed char *mapping = platform_irq_mappings[irq];
188 int alone = 1;
189 u8 mask;
190 if (!mapping)
191 continue;
192 for(mask = 0; *mapping != -1; mapping++)
193 switch (*mapping) {
194 case S6_INTC_GPIO(0):
195 mask |= 1 << 0;
196 break;
197 case S6_INTC_GPIO(1):
198 mask |= 1 << 1;
199 break;
200 case S6_INTC_GPIO(2):
201 mask |= 1 << 2;
202 break;
203 case S6_INTC_GPIO(3):
204 mask |= 0x1f << 3;
205 break;
206 default:
207 alone = 0;
208 }
209 if (mask) {
210 int cirq, i;
211 if (!alone) {
212 printk(KERN_ERR "chained irq chips can't share"
213 " parent irq %i\n", irq);
214 continue;
215 }
216 demux_masks[n] = mask;
217 cirq = IRQ_BASE - 1;
218 do {
219 i = ffs(mask);
220 cirq += i;
221 mask >>= i;
222 set_irq_chip(cirq, &gpioirqs);
223 set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
224 } while (mask);
225 set_irq_data(irq, demux_masks + n);
226 set_irq_chained_handler(irq, demux_irqs);
227 if (++n == ARRAY_SIZE(demux_masks))
228 break;
229 }
230 }
231}
diff --git a/arch/xtensa/variants/s6000/include/variant/dmac.h b/arch/xtensa/variants/s6000/include/variant/dmac.h
new file mode 100644
index 000000000000..89ab9484fb71
--- /dev/null
+++ b/arch/xtensa/variants/s6000/include/variant/dmac.h
@@ -0,0 +1,387 @@
1/*
2 * include/asm-xtensa/variant-s6000/dmac.h
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2006 Tensilica Inc.
9 * Copyright (C) 2008 Emlix GmbH <info@emlix.com>
10 * Authors: Fabian Godehardt <fg@emlix.com>
11 * Oskar Schirmer <os@emlix.com>
12 * Daniel Gloeckner <dg@emlix.com>
13 */
14
15#ifndef __ASM_XTENSA_S6000_DMAC_H
16#define __ASM_XTENSA_S6000_DMAC_H
17#include <linux/io.h>
18#include <variant/hardware.h>
19
20/* DMA global */
21
22#define S6_DMA_INTSTAT0 0x000
23#define S6_DMA_INTSTAT1 0x004
24#define S6_DMA_INTENABLE0 0x008
25#define S6_DMA_INTENABLE1 0x00C
26#define S6_DMA_INTRAW0 0x010
27#define S6_DMA_INTRAW1 0x014
28#define S6_DMA_INTCLEAR0 0x018
29#define S6_DMA_INTCLEAR1 0x01C
30#define S6_DMA_INTSET0 0x020
31#define S6_DMA_INTSET1 0x024
32#define S6_DMA_INT0_UNDER 0
33#define S6_DMA_INT0_OVER 16
34#define S6_DMA_INT1_CHANNEL 0
35#define S6_DMA_INT1_MASTER 16
36#define S6_DMA_INT1_MASTER_MASK 7
37#define S6_DMA_TERMCNTIRQSTAT 0x028
38#define S6_DMA_TERMCNTIRQCLR 0x02C
39#define S6_DMA_TERMCNTIRQSET 0x030
40#define S6_DMA_PENDCNTIRQSTAT 0x034
41#define S6_DMA_PENDCNTIRQCLR 0x038
42#define S6_DMA_PENDCNTIRQSET 0x03C
43#define S6_DMA_LOWWMRKIRQSTAT 0x040
44#define S6_DMA_LOWWMRKIRQCLR 0x044
45#define S6_DMA_LOWWMRKIRQSET 0x048
46#define S6_DMA_MASTERERRINFO 0x04C
47#define S6_DMA_MASTERERR_CHAN(n) (4*(n))
48#define S6_DMA_MASTERERR_CHAN_MASK 0xF
49#define S6_DMA_DESCRFIFO0 0x050
50#define S6_DMA_DESCRFIFO1 0x054
51#define S6_DMA_DESCRFIFO2 0x058
52#define S6_DMA_DESCRFIFO2_AUTODISABLE 24
53#define S6_DMA_DESCRFIFO3 0x05C
54#define S6_DMA_MASTER0START 0x060
55#define S6_DMA_MASTER0END 0x064
56#define S6_DMA_MASTER1START 0x068
57#define S6_DMA_MASTER1END 0x06C
58#define S6_DMA_NEXTFREE 0x070
59#define S6_DMA_NEXTFREE_CHAN 0
60#define S6_DMA_NEXTFREE_CHAN_MASK 0x1F
61#define S6_DMA_NEXTFREE_ENA 16
62#define S6_DMA_NEXTFREE_ENA_MASK ((1 << 16) - 1)
63#define S6_DMA_DPORTCTRLGRP(p) ((p) * 4 + 0x074)
64#define S6_DMA_DPORTCTRLGRP_FRAMEREP 0
65#define S6_DMA_DPORTCTRLGRP_NRCHANS 1
66#define S6_DMA_DPORTCTRLGRP_NRCHANS_1 0
67#define S6_DMA_DPORTCTRLGRP_NRCHANS_3 1
68#define S6_DMA_DPORTCTRLGRP_NRCHANS_4 2
69#define S6_DMA_DPORTCTRLGRP_NRCHANS_2 3
70#define S6_DMA_DPORTCTRLGRP_ENA 31
71
72
73/* DMA per channel */
74
75#define DMA_CHNL(dmac, n) ((dmac) + 0x1000 + (n) * 0x100)
76#define DMA_INDEX_CHNL(addr) (((addr) >> 8) & 0xF)
77#define DMA_MASK_DMAC(addr) ((addr) & 0xFFFF0000)
78#define S6_DMA_CHNCTRL 0x000
79#define S6_DMA_CHNCTRL_ENABLE 0
80#define S6_DMA_CHNCTRL_PAUSE 1
81#define S6_DMA_CHNCTRL_PRIO 2
82#define S6_DMA_CHNCTRL_PRIO_MASK 3
83#define S6_DMA_CHNCTRL_PERIPHXFER 4
84#define S6_DMA_CHNCTRL_PERIPHENA 5
85#define S6_DMA_CHNCTRL_SRCINC 6
86#define S6_DMA_CHNCTRL_DSTINC 7
87#define S6_DMA_CHNCTRL_BURSTLOG 8
88#define S6_DMA_CHNCTRL_BURSTLOG_MASK 7
89#define S6_DMA_CHNCTRL_DESCFIFODEPTH 12
90#define S6_DMA_CHNCTRL_DESCFIFODEPTH_MASK 0x1F
91#define S6_DMA_CHNCTRL_DESCFIFOFULL 17
92#define S6_DMA_CHNCTRL_BWCONSEL 18
93#define S6_DMA_CHNCTRL_BWCONENA 19
94#define S6_DMA_CHNCTRL_PENDGCNTSTAT 20
95#define S6_DMA_CHNCTRL_PENDGCNTSTAT_MASK 0x3F
96#define S6_DMA_CHNCTRL_LOWWMARK 26
97#define S6_DMA_CHNCTRL_LOWWMARK_MASK 0xF
98#define S6_DMA_CHNCTRL_TSTAMP 30
99#define S6_DMA_TERMCNTNB 0x004
100#define S6_DMA_TERMCNTNB_MASK 0xFFFF
101#define S6_DMA_TERMCNTTMO 0x008
102#define S6_DMA_TERMCNTSTAT 0x00C
103#define S6_DMA_TERMCNTSTAT_MASK 0xFF
104#define S6_DMA_CMONCHUNK 0x010
105#define S6_DMA_SRCSKIP 0x014
106#define S6_DMA_DSTSKIP 0x018
107#define S6_DMA_CUR_SRC 0x024
108#define S6_DMA_CUR_DST 0x028
109#define S6_DMA_TIMESTAMP 0x030
110
111/* DMA channel lists */
112
113#define S6_DPDMA_CHAN(stream, channel) (4 * (stream) + (channel))
114#define S6_DPDMA_NB 16
115
116#define S6_HIFDMA_GMACTX 0
117#define S6_HIFDMA_GMACRX 1
118#define S6_HIFDMA_I2S0 2
119#define S6_HIFDMA_I2S1 3
120#define S6_HIFDMA_EGIB 4
121#define S6_HIFDMA_PCITX 5
122#define S6_HIFDMA_PCIRX 6
123#define S6_HIFDMA_NB 7
124
125#define S6_NIDMA_NB 4
126
127#define S6_LMSDMA_NB 12
128
129/* controller access */
130
131#define S6_DMAC_NB 4
132#define S6_DMAC_INDEX(dmac) (((unsigned)(dmac) >> 18) % S6_DMAC_NB)
133
134struct s6dmac_ctrl {
135 u32 dmac;
136 spinlock_t lock;
137 u8 chan_nb;
138};
139
140extern struct s6dmac_ctrl s6dmac_ctrl[S6_DMAC_NB];
141
142
143/* DMA control, per channel */
144
145static inline int s6dmac_fifo_full(u32 dmac, int chan)
146{
147 return (readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL)
148 & (1 << S6_DMA_CHNCTRL_DESCFIFOFULL)) && 1;
149}
150
151static inline int s6dmac_termcnt_irq(u32 dmac, int chan)
152{
153 u32 m = 1 << chan;
154 int r = (readl(dmac + S6_DMA_TERMCNTIRQSTAT) & m) && 1;
155 if (r)
156 writel(m, dmac + S6_DMA_TERMCNTIRQCLR);
157 return r;
158}
159
160static inline int s6dmac_pendcnt_irq(u32 dmac, int chan)
161{
162 u32 m = 1 << chan;
163 int r = (readl(dmac + S6_DMA_PENDCNTIRQSTAT) & m) && 1;
164 if (r)
165 writel(m, dmac + S6_DMA_PENDCNTIRQCLR);
166 return r;
167}
168
169static inline int s6dmac_lowwmark_irq(u32 dmac, int chan)
170{
171 int r = (readl(dmac + S6_DMA_LOWWMRKIRQSTAT) & (1 << chan)) ? 1 : 0;
172 if (r)
173 writel(1 << chan, dmac + S6_DMA_LOWWMRKIRQCLR);
174 return r;
175}
176
177static inline u32 s6dmac_pending_count(u32 dmac, int chan)
178{
179 return (readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL)
180 >> S6_DMA_CHNCTRL_PENDGCNTSTAT)
181 & S6_DMA_CHNCTRL_PENDGCNTSTAT_MASK;
182}
183
184static inline void s6dmac_set_terminal_count(u32 dmac, int chan, u32 n)
185{
186 n &= S6_DMA_TERMCNTNB_MASK;
187 n |= readl(DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB)
188 & ~S6_DMA_TERMCNTNB_MASK;
189 writel(n, DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB);
190}
191
192static inline u32 s6dmac_get_terminal_count(u32 dmac, int chan)
193{
194 return (readl(DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB))
195 & S6_DMA_TERMCNTNB_MASK;
196}
197
198static inline u32 s6dmac_timestamp(u32 dmac, int chan)
199{
200 return readl(DMA_CHNL(dmac, chan) + S6_DMA_TIMESTAMP);
201}
202
203static inline u32 s6dmac_cur_src(u32 dmac, int chan)
204{
205 return readl(DMA_CHNL(dmac, chan) + S6_DMA_CUR_SRC);
206}
207
208static inline u32 s6dmac_cur_dst(u32 dmac, int chan)
209{
210 return readl(DMA_CHNL(dmac, chan) + S6_DMA_CUR_DST);
211}
212
213static inline void s6dmac_disable_chan(u32 dmac, int chan)
214{
215 u32 ctrl;
216 writel(readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL)
217 & ~(1 << S6_DMA_CHNCTRL_ENABLE),
218 DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
219 do
220 ctrl = readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
221 while (ctrl & (1 << S6_DMA_CHNCTRL_ENABLE));
222}
223
224static inline void s6dmac_set_stride_skip(u32 dmac, int chan,
225 int comchunk, /* 0: disable scatter/gather */
226 int srcskip, int dstskip)
227{
228 writel(comchunk, DMA_CHNL(dmac, chan) + S6_DMA_CMONCHUNK);
229 writel(srcskip, DMA_CHNL(dmac, chan) + S6_DMA_SRCSKIP);
230 writel(dstskip, DMA_CHNL(dmac, chan) + S6_DMA_DSTSKIP);
231}
232
233static inline void s6dmac_enable_chan(u32 dmac, int chan,
234 int prio, /* 0 (highest) .. 3 (lowest) */
235 int periphxfer, /* <0: disable p.req.line, 0..1: mode */
236 int srcinc, int dstinc, /* 0: dont increment src/dst address */
237 int comchunk, /* 0: disable scatter/gather */
238 int srcskip, int dstskip,
239 int burstsize, /* 4 for I2S, 7 for everything else */
240 int bandwidthconserve, /* <0: disable, 0..1: select */
241 int lowwmark, /* 0..15 */
242 int timestamp, /* 0: disable timestamp */
243 int enable) /* 0: disable for now */
244{
245 writel(1, DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTNB);
246 writel(0, DMA_CHNL(dmac, chan) + S6_DMA_TERMCNTTMO);
247 writel(lowwmark << S6_DMA_CHNCTRL_LOWWMARK,
248 DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
249 s6dmac_set_stride_skip(dmac, chan, comchunk, srcskip, dstskip);
250 writel(((enable ? 1 : 0) << S6_DMA_CHNCTRL_ENABLE) |
251 (prio << S6_DMA_CHNCTRL_PRIO) |
252 (((periphxfer > 0) ? 1 : 0) << S6_DMA_CHNCTRL_PERIPHXFER) |
253 (((periphxfer < 0) ? 0 : 1) << S6_DMA_CHNCTRL_PERIPHENA) |
254 ((srcinc ? 1 : 0) << S6_DMA_CHNCTRL_SRCINC) |
255 ((dstinc ? 1 : 0) << S6_DMA_CHNCTRL_DSTINC) |
256 (burstsize << S6_DMA_CHNCTRL_BURSTLOG) |
257 (((bandwidthconserve > 0) ? 1 : 0) << S6_DMA_CHNCTRL_BWCONSEL) |
258 (((bandwidthconserve < 0) ? 0 : 1) << S6_DMA_CHNCTRL_BWCONENA) |
259 (lowwmark << S6_DMA_CHNCTRL_LOWWMARK) |
260 ((timestamp ? 1 : 0) << S6_DMA_CHNCTRL_TSTAMP),
261 DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL);
262}
263
264
265/* DMA control, per engine */
266
267static inline unsigned _dmac_addr_index(u32 dmac)
268{
269 unsigned i = S6_DMAC_INDEX(dmac);
270 if (s6dmac_ctrl[i].dmac != dmac)
271 BUG();
272 return i;
273}
274
275static inline void _s6dmac_disable_error_irqs(u32 dmac, u32 mask)
276{
277 writel(mask, dmac + S6_DMA_TERMCNTIRQCLR);
278 writel(mask, dmac + S6_DMA_PENDCNTIRQCLR);
279 writel(mask, dmac + S6_DMA_LOWWMRKIRQCLR);
280 writel(readl(dmac + S6_DMA_INTENABLE0)
281 & ~((mask << S6_DMA_INT0_UNDER) | (mask << S6_DMA_INT0_OVER)),
282 dmac + S6_DMA_INTENABLE0);
283 writel(readl(dmac + S6_DMA_INTENABLE1) & ~(mask << S6_DMA_INT1_CHANNEL),
284 dmac + S6_DMA_INTENABLE1);
285 writel((mask << S6_DMA_INT0_UNDER) | (mask << S6_DMA_INT0_OVER),
286 dmac + S6_DMA_INTCLEAR0);
287 writel(mask << S6_DMA_INT1_CHANNEL, dmac + S6_DMA_INTCLEAR1);
288}
289
290/*
291 * request channel from specified engine
292 * with chan<0, accept any channel
293 * further parameters see s6dmac_enable_chan
294 * returns < 0 upon error, channel nb otherwise
295 */
296static inline int s6dmac_request_chan(u32 dmac, int chan,
297 int prio,
298 int periphxfer,
299 int srcinc, int dstinc,
300 int comchunk,
301 int srcskip, int dstskip,
302 int burstsize,
303 int bandwidthconserve,
304 int lowwmark,
305 int timestamp,
306 int enable)
307{
308 int r = chan;
309 unsigned long flags;
310 spinlock_t *spinl = &s6dmac_ctrl[_dmac_addr_index(dmac)].lock;
311 spin_lock_irqsave(spinl, flags);
312 if (r < 0) {
313 r = (readl(dmac + S6_DMA_NEXTFREE) >> S6_DMA_NEXTFREE_CHAN)
314 & S6_DMA_NEXTFREE_CHAN_MASK;
315 }
316 if (r >= s6dmac_ctrl[_dmac_addr_index(dmac)].chan_nb) {
317 if (chan < 0)
318 r = -EBUSY;
319 else
320 r = -ENXIO;
321 } else if (((readl(dmac + S6_DMA_NEXTFREE) >> S6_DMA_NEXTFREE_ENA)
322 >> r) & 1) {
323 r = -EBUSY;
324 } else {
325 s6dmac_enable_chan(dmac, r, prio, periphxfer,
326 srcinc, dstinc, comchunk, srcskip, dstskip, burstsize,
327 bandwidthconserve, lowwmark, timestamp, enable);
328 }
329 spin_unlock_irqrestore(spinl, flags);
330 return r;
331}
332
333static inline void s6dmac_put_fifo(u32 dmac, int chan,
334 u32 src, u32 dst, u32 size)
335{
336 unsigned long flags;
337 spinlock_t *spinl = &s6dmac_ctrl[_dmac_addr_index(dmac)].lock;
338 spin_lock_irqsave(spinl, flags);
339 writel(src, dmac + S6_DMA_DESCRFIFO0);
340 writel(dst, dmac + S6_DMA_DESCRFIFO1);
341 writel(size, dmac + S6_DMA_DESCRFIFO2);
342 writel(chan, dmac + S6_DMA_DESCRFIFO3);
343 spin_unlock_irqrestore(spinl, flags);
344}
345
346static inline u32 s6dmac_channel_enabled(u32 dmac, int chan)
347{
348 return readl(DMA_CHNL(dmac, chan) + S6_DMA_CHNCTRL) &
349 (1 << S6_DMA_CHNCTRL_ENABLE);
350}
351
352/*
353 * group 1-4 data port channels
354 * with port=0..3, nrch=1-4 channels,
355 * frrep=0/1 (dis- or enable frame repeat)
356 */
357static inline void s6dmac_dp_setup_group(u32 dmac, int port,
358 int nrch, int frrep)
359{
360 const static u8 mask[4] = {0, 3, 1, 2};
361 BUG_ON(dmac != S6_REG_DPDMA);
362 if ((port < 0) || (port > 3) || (nrch < 1) || (nrch > 4))
363 return;
364 writel((mask[nrch - 1] << S6_DMA_DPORTCTRLGRP_NRCHANS)
365 | ((frrep ? 1 : 0) << S6_DMA_DPORTCTRLGRP_FRAMEREP),
366 dmac + S6_DMA_DPORTCTRLGRP(port));
367}
368
369static inline void s6dmac_dp_switch_group(u32 dmac, int port, int enable)
370{
371 u32 tmp;
372 BUG_ON(dmac != S6_REG_DPDMA);
373 tmp = readl(dmac + S6_DMA_DPORTCTRLGRP(port));
374 if (enable)
375 tmp |= (1 << S6_DMA_DPORTCTRLGRP_ENA);
376 else
377 tmp &= ~(1 << S6_DMA_DPORTCTRLGRP_ENA);
378 writel(tmp, dmac + S6_DMA_DPORTCTRLGRP(port));
379}
380
381extern void s6dmac_put_fifo_cache(u32 dmac, int chan,
382 u32 src, u32 dst, u32 size);
383extern void s6dmac_disable_error_irqs(u32 dmac, u32 mask);
384extern u32 s6dmac_int_sources(u32 dmac, u32 channel);
385extern void s6dmac_release_chan(u32 dmac, int chan);
386
387#endif /* __ASM_XTENSA_S6000_DMAC_H */
diff --git a/arch/xtensa/variants/s6000/include/variant/gpio.h b/arch/xtensa/variants/s6000/include/variant/gpio.h
index 8327f62167eb..8484ab0df461 100644
--- a/arch/xtensa/variants/s6000/include/variant/gpio.h
+++ b/arch/xtensa/variants/s6000/include/variant/gpio.h
@@ -1,6 +1,6 @@
1#ifndef _XTENSA_VARIANT_S6000_GPIO_H 1#ifndef _XTENSA_VARIANT_S6000_GPIO_H
2#define _XTENSA_VARIANT_S6000_GPIO_H 2#define _XTENSA_VARIANT_S6000_GPIO_H
3 3
4extern int s6_gpio_init(void); 4extern int s6_gpio_init(u32 afsel);
5 5
6#endif /* _XTENSA_VARIANT_S6000_GPIO_H */ 6#endif /* _XTENSA_VARIANT_S6000_GPIO_H */
diff --git a/arch/xtensa/variants/s6000/include/variant/irq.h b/arch/xtensa/variants/s6000/include/variant/irq.h
index fa031cb0acc4..97d6fc48deff 100644
--- a/arch/xtensa/variants/s6000/include/variant/irq.h
+++ b/arch/xtensa/variants/s6000/include/variant/irq.h
@@ -1,9 +1,9 @@
1#ifndef __XTENSA_S6000_IRQ_H 1#ifndef _XTENSA_S6000_IRQ_H
2#define __XTENSA_S6000_IRQ_H 2#define _XTENSA_S6000_IRQ_H
3 3
4#define NO_IRQ (-1) 4#define NO_IRQ (-1)
5#define VARIANT_NR_IRQS 8 /* GPIO interrupts */
5 6
6extern void variant_irq_enable(unsigned int irq); 7extern void variant_irq_enable(unsigned int irq);
7extern void variant_irq_disable(unsigned int irq);
8 8
9#endif /* __XTENSA_S6000_IRQ_H */ 9#endif /* __XTENSA_S6000_IRQ_H */