diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2007-06-22 10:22:06 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-07-10 12:33:03 -0400 |
commit | f74cf6ff99a49741b0f243996b621777b2d610d4 (patch) | |
tree | 5812f82646aadcbd451e528379548866c5ca790d /arch/mips/tx4938 | |
parent | 3896b05418b9b8548a678231db754206b3ebe56e (diff) |
[MIPS] rbtx4938: Convert SPI codes to use generic SPI drivers
Use rtc-rs5c348 and at25 spi protocol driver and spi_txx9 spi
controller driver instead of platform dependent codes.
This patch also removes dependencies to old RTC interfaces such as
rtc_mips_get_time, etc.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/tx4938')
-rw-r--r-- | arch/mips/tx4938/common/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/tx4938/common/rtc_rx5c348.c | 192 | ||||
-rw-r--r-- | arch/mips/tx4938/toshiba_rbtx4938/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/tx4938/toshiba_rbtx4938/irq.c | 6 | ||||
-rw-r--r-- | arch/mips/tx4938/toshiba_rbtx4938/setup.c | 171 | ||||
-rw-r--r-- | arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c | 261 | ||||
-rw-r--r-- | arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c | 164 |
7 files changed, 167 insertions, 631 deletions
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile index 2033ae77f632..83cda518f204 100644 --- a/arch/mips/tx4938/common/Makefile +++ b/arch/mips/tx4938/common/Makefile | |||
@@ -6,6 +6,6 @@ | |||
6 | # unless it's something special (ie not a .c file). | 6 | # unless it's something special (ie not a .c file). |
7 | # | 7 | # |
8 | 8 | ||
9 | obj-y += prom.o setup.o irq.o rtc_rx5c348.o | 9 | obj-y += prom.o setup.o irq.o |
10 | obj-$(CONFIG_KGDB) += dbgio.o | 10 | obj-$(CONFIG_KGDB) += dbgio.o |
11 | 11 | ||
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c deleted file mode 100644 index 07f782fc0725..000000000000 --- a/arch/mips/tx4938/common/rtc_rx5c348.c +++ /dev/null | |||
@@ -1,192 +0,0 @@ | |||
1 | /* | ||
2 | * RTC routines for RICOH Rx5C348 SPI chip. | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/rtc.h> | ||
16 | #include <linux/time.h> | ||
17 | #include <linux/bcd.h> | ||
18 | #include <asm/time.h> | ||
19 | #include <asm/tx4938/spi.h> | ||
20 | |||
21 | #define EPOCH 2000 | ||
22 | |||
23 | /* registers */ | ||
24 | #define Rx5C348_REG_SECOND 0 | ||
25 | #define Rx5C348_REG_MINUTE 1 | ||
26 | #define Rx5C348_REG_HOUR 2 | ||
27 | #define Rx5C348_REG_WEEK 3 | ||
28 | #define Rx5C348_REG_DAY 4 | ||
29 | #define Rx5C348_REG_MONTH 5 | ||
30 | #define Rx5C348_REG_YEAR 6 | ||
31 | #define Rx5C348_REG_ADJUST 7 | ||
32 | #define Rx5C348_REG_ALARM_W_MIN 8 | ||
33 | #define Rx5C348_REG_ALARM_W_HOUR 9 | ||
34 | #define Rx5C348_REG_ALARM_W_WEEK 10 | ||
35 | #define Rx5C348_REG_ALARM_D_MIN 11 | ||
36 | #define Rx5C348_REG_ALARM_D_HOUR 12 | ||
37 | #define Rx5C348_REG_CTL1 14 | ||
38 | #define Rx5C348_REG_CTL2 15 | ||
39 | |||
40 | /* register bits */ | ||
41 | #define Rx5C348_BIT_PM 0x20 /* REG_HOUR */ | ||
42 | #define Rx5C348_BIT_Y2K 0x80 /* REG_MONTH */ | ||
43 | #define Rx5C348_BIT_24H 0x20 /* REG_CTL1 */ | ||
44 | #define Rx5C348_BIT_XSTP 0x10 /* REG_CTL2 */ | ||
45 | |||
46 | /* commands */ | ||
47 | #define Rx5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */ | ||
48 | #define Rx5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */ | ||
49 | #define Rx5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */ | ||
50 | #define Rx5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */ | ||
51 | |||
52 | static struct spi_dev_desc srtc_dev_desc = { | ||
53 | .baud = 1000000, /* 1.0Mbps @ Vdd 2.0V */ | ||
54 | .tcss = 31, | ||
55 | .tcsh = 1, | ||
56 | .tcsr = 62, | ||
57 | /* 31us for Tcss (62us for Tcsr) is required for carry operation) */ | ||
58 | .byteorder = 1, /* MSB-First */ | ||
59 | .polarity = 0, /* High-Active */ | ||
60 | .phase = 1, /* Shift-Then-Sample */ | ||
61 | |||
62 | }; | ||
63 | static int srtc_chipid; | ||
64 | static int srtc_24h; | ||
65 | |||
66 | static inline int | ||
67 | spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count) | ||
68 | { | ||
69 | unsigned char *inbufs[1], *outbufs[1]; | ||
70 | unsigned int incounts[2], outcounts[2]; | ||
71 | inbufs[0] = inbuf; | ||
72 | incounts[0] = count; | ||
73 | incounts[1] = 0; | ||
74 | outbufs[0] = outbuf; | ||
75 | outcounts[0] = count; | ||
76 | outcounts[1] = 0; | ||
77 | return txx9_spi_io(srtc_chipid, &srtc_dev_desc, | ||
78 | inbufs, incounts, outbufs, outcounts, 0); | ||
79 | } | ||
80 | |||
81 | /* RTC-dependent code for time.c */ | ||
82 | |||
83 | static int | ||
84 | rtc_rx5c348_set_time(unsigned long t) | ||
85 | { | ||
86 | unsigned char inbuf[8]; | ||
87 | struct rtc_time tm; | ||
88 | u8 year, month, day, hour, minute, second, century; | ||
89 | |||
90 | /* convert */ | ||
91 | to_tm(t, &tm); | ||
92 | |||
93 | year = tm.tm_year % 100; | ||
94 | month = tm.tm_mon+1; /* tm_mon starts from 0 to 11 */ | ||
95 | day = tm.tm_mday; | ||
96 | hour = tm.tm_hour; | ||
97 | minute = tm.tm_min; | ||
98 | second = tm.tm_sec; | ||
99 | century = tm.tm_year / 100; | ||
100 | |||
101 | inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND); | ||
102 | BIN_TO_BCD(second); | ||
103 | inbuf[1] = second; | ||
104 | BIN_TO_BCD(minute); | ||
105 | inbuf[2] = minute; | ||
106 | |||
107 | if (srtc_24h) { | ||
108 | BIN_TO_BCD(hour); | ||
109 | inbuf[3] = hour; | ||
110 | } else { | ||
111 | /* hour 0 is AM12, noon is PM12 */ | ||
112 | inbuf[3] = 0; | ||
113 | if (hour >= 12) | ||
114 | inbuf[3] = Rx5C348_BIT_PM; | ||
115 | hour = (hour + 11) % 12 + 1; | ||
116 | BIN_TO_BCD(hour); | ||
117 | inbuf[3] |= hour; | ||
118 | } | ||
119 | inbuf[4] = 0; /* ignore week */ | ||
120 | BIN_TO_BCD(day); | ||
121 | inbuf[5] = day; | ||
122 | BIN_TO_BCD(month); | ||
123 | inbuf[6] = month; | ||
124 | if (century >= 20) | ||
125 | inbuf[6] |= Rx5C348_BIT_Y2K; | ||
126 | BIN_TO_BCD(year); | ||
127 | inbuf[7] = year; | ||
128 | /* write in one transfer to avoid data inconsistency */ | ||
129 | return spi_rtc_io(inbuf, NULL, 8); | ||
130 | } | ||
131 | |||
132 | static unsigned long | ||
133 | rtc_rx5c348_get_time(void) | ||
134 | { | ||
135 | unsigned char inbuf[8], outbuf[8]; | ||
136 | unsigned int year, month, day, hour, minute, second; | ||
137 | |||
138 | inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND); | ||
139 | memset(inbuf + 1, 0, 7); | ||
140 | /* read in one transfer to avoid data inconsistency */ | ||
141 | if (spi_rtc_io(inbuf, outbuf, 8)) | ||
142 | return 0; | ||
143 | second = outbuf[1]; | ||
144 | BCD_TO_BIN(second); | ||
145 | minute = outbuf[2]; | ||
146 | BCD_TO_BIN(minute); | ||
147 | if (srtc_24h) { | ||
148 | hour = outbuf[3]; | ||
149 | BCD_TO_BIN(hour); | ||
150 | } else { | ||
151 | hour = outbuf[3] & ~Rx5C348_BIT_PM; | ||
152 | BCD_TO_BIN(hour); | ||
153 | hour %= 12; | ||
154 | if (outbuf[3] & Rx5C348_BIT_PM) | ||
155 | hour += 12; | ||
156 | } | ||
157 | day = outbuf[5]; | ||
158 | BCD_TO_BIN(day); | ||
159 | month = outbuf[6] & ~Rx5C348_BIT_Y2K; | ||
160 | BCD_TO_BIN(month); | ||
161 | year = outbuf[7]; | ||
162 | BCD_TO_BIN(year); | ||
163 | year += EPOCH; | ||
164 | |||
165 | return mktime(year, month, day, hour, minute, second); | ||
166 | } | ||
167 | |||
168 | void __init | ||
169 | rtc_rx5c348_init(int chipid) | ||
170 | { | ||
171 | unsigned char inbuf[2], outbuf[2]; | ||
172 | srtc_chipid = chipid; | ||
173 | /* turn on RTC if it is not on */ | ||
174 | inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2); | ||
175 | inbuf[1] = 0; | ||
176 | spi_rtc_io(inbuf, outbuf, 2); | ||
177 | if (outbuf[1] & Rx5C348_BIT_XSTP) { | ||
178 | inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2); | ||
179 | inbuf[1] = 0; | ||
180 | spi_rtc_io(inbuf, NULL, 2); | ||
181 | } | ||
182 | |||
183 | inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1); | ||
184 | inbuf[1] = 0; | ||
185 | spi_rtc_io(inbuf, outbuf, 2); | ||
186 | if (outbuf[1] & Rx5C348_BIT_24H) | ||
187 | srtc_24h = 1; | ||
188 | |||
189 | /* set the function pointers */ | ||
190 | rtc_mips_get_time = rtc_rx5c348_get_time; | ||
191 | rtc_mips_set_time = rtc_rx5c348_set_time; | ||
192 | } | ||
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/arch/mips/tx4938/toshiba_rbtx4938/Makefile index 226941279d75..10c94e62bf5b 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/Makefile +++ b/arch/mips/tx4938/toshiba_rbtx4938/Makefile | |||
@@ -6,4 +6,4 @@ | |||
6 | # unless it's something special (ie not a .c file). | 6 | # unless it's something special (ie not a .c file). |
7 | # | 7 | # |
8 | 8 | ||
9 | obj-y += prom.o setup.o irq.o spi_eeprom.o spi_txx9.o | 9 | obj-y += prom.o setup.o irq.o spi_eeprom.o |
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 2e96dbb248b1..91aea7aff515 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c | |||
@@ -165,8 +165,6 @@ toshiba_rbtx4938_irq_ioc_disable(unsigned int irq) | |||
165 | TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); | 165 | TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); |
166 | } | 166 | } |
167 | 167 | ||
168 | extern void __init txx9_spi_irqinit(int irc_irq); | ||
169 | |||
170 | void __init arch_init_irq(void) | 168 | void __init arch_init_irq(void) |
171 | { | 169 | { |
172 | extern void tx4938_irq_init(void); | 170 | extern void tx4938_irq_init(void); |
@@ -185,9 +183,5 @@ void __init arch_init_irq(void) | |||
185 | /* Onboard 10M Ether: High Active */ | 183 | /* Onboard 10M Ether: High Active */ |
186 | TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040); | 184 | TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040); |
187 | 185 | ||
188 | if (tx4938_ccfgptr->pcfg & TX4938_PCFG_SPI_SEL) { | ||
189 | txx9_spi_irqinit(RBTX4938_IRQ_IRC_SPI); | ||
190 | } | ||
191 | |||
192 | wbflush(); | 186 | wbflush(); |
193 | } | 187 | } |
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index 12b9f4f9c3a2..361d89a81175 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c | |||
@@ -14,13 +14,13 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/ioport.h> | 16 | #include <linux/ioport.h> |
17 | #include <linux/proc_fs.h> | ||
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
20 | #include <linux/console.h> | 19 | #include <linux/console.h> |
21 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
22 | #include <linux/pm.h> | 21 | #include <linux/pm.h> |
23 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/clk.h> | ||
24 | 24 | ||
25 | #include <asm/wbflush.h> | 25 | #include <asm/wbflush.h> |
26 | #include <asm/reboot.h> | 26 | #include <asm/reboot.h> |
@@ -29,13 +29,15 @@ | |||
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | #include <asm/bootinfo.h> | 31 | #include <asm/bootinfo.h> |
32 | #include <asm/gpio.h> | ||
33 | #include <asm/tx4938/rbtx4938.h> | 32 | #include <asm/tx4938/rbtx4938.h> |
34 | #ifdef CONFIG_SERIAL_TXX9 | 33 | #ifdef CONFIG_SERIAL_TXX9 |
35 | #include <linux/tty.h> | 34 | #include <linux/tty.h> |
36 | #include <linux/serial.h> | 35 | #include <linux/serial.h> |
37 | #include <linux/serial_core.h> | 36 | #include <linux/serial_core.h> |
38 | #endif | 37 | #endif |
38 | #include <linux/spi/spi.h> | ||
39 | #include <asm/tx4938/spi.h> | ||
40 | #include <asm/gpio.h> | ||
39 | 41 | ||
40 | extern void rbtx4938_time_init(void) __init; | 42 | extern void rbtx4938_time_init(void) __init; |
41 | extern char * __init prom_getcmdline(void); | 43 | extern char * __init prom_getcmdline(void); |
@@ -575,44 +577,33 @@ arch_initcall(tx4938_pcibios_init); | |||
575 | #define SEEPROM3_CS 1 /* IOC */ | 577 | #define SEEPROM3_CS 1 /* IOC */ |
576 | #define SRTC_CS 2 /* IOC */ | 578 | #define SRTC_CS 2 /* IOC */ |
577 | 579 | ||
578 | static int rbtx4938_spi_cs_func(int chipid, int on) | 580 | #ifdef CONFIG_PCI |
581 | static unsigned char rbtx4938_ethaddr[17]; | ||
582 | static int __init rbtx4938_ethaddr_init(void) | ||
579 | { | 583 | { |
580 | unsigned char bit; | 584 | unsigned char sum; |
581 | switch (chipid) { | 585 | int i; |
582 | case RBTX4938_SEEPROM1_CHIPID: | 586 | |
583 | if (on) | 587 | /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ |
584 | tx4938_pioptr->dout &= ~(1 << SEEPROM1_CS); | 588 | if (spi_eeprom_read(SEEPROM1_CS, 0, |
585 | else | 589 | rbtx4938_ethaddr, sizeof(rbtx4938_ethaddr))) |
586 | tx4938_pioptr->dout |= (1 << SEEPROM1_CS); | 590 | printk(KERN_ERR "seeprom: read error.\n"); |
587 | return 0; | 591 | else { |
588 | break; | 592 | unsigned char *dat = rbtx4938_ethaddr; |
589 | case RBTX4938_SEEPROM2_CHIPID: | 593 | if (strcmp(dat, "MAC") != 0) |
590 | bit = (1 << SEEPROM2_CS); | 594 | printk(KERN_WARNING "seeprom: bad signature.\n"); |
591 | break; | 595 | for (i = 0, sum = 0; i < sizeof(dat); i++) |
592 | case RBTX4938_SEEPROM3_CHIPID: | 596 | sum += dat[i]; |
593 | bit = (1 << SEEPROM3_CS); | 597 | if (sum) |
594 | break; | 598 | printk(KERN_WARNING "seeprom: bad checksum.\n"); |
595 | case RBTX4938_SRTC_CHIPID: | ||
596 | bit = (1 << SRTC_CS); | ||
597 | break; | ||
598 | default: | ||
599 | return -ENODEV; | ||
600 | } | 599 | } |
601 | /* bit1,2,4 are low active, bit3 is high active */ | ||
602 | *rbtx4938_spics_ptr = | ||
603 | (*rbtx4938_spics_ptr & ~bit) | | ||
604 | ((on ? (bit ^ 0x0b) : ~(bit ^ 0x0b)) & bit); | ||
605 | return 0; | 600 | return 0; |
606 | } | 601 | } |
607 | 602 | device_initcall(rbtx4938_ethaddr_init); | |
608 | #ifdef CONFIG_PCI | ||
609 | extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len); | ||
610 | 603 | ||
611 | int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr) | 604 | int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr) |
612 | { | 605 | { |
613 | struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata; | 606 | struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata; |
614 | static unsigned char dat[17]; | ||
615 | static int read_dat = 0; | ||
616 | int ch = 0; | 607 | int ch = 0; |
617 | 608 | ||
618 | if (channel != &tx4938_pci_controller[1]) | 609 | if (channel != &tx4938_pci_controller[1]) |
@@ -628,29 +619,11 @@ int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr) | |||
628 | default: | 619 | default: |
629 | return -ENODEV; | 620 | return -ENODEV; |
630 | } | 621 | } |
631 | if (!read_dat) { | 622 | memcpy(addr, &rbtx4938_ethaddr[4 + 6 * ch], 6); |
632 | unsigned char sum; | ||
633 | int i; | ||
634 | read_dat = 1; | ||
635 | /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ | ||
636 | if (spi_eeprom_read(RBTX4938_SEEPROM1_CHIPID, | ||
637 | 0, dat, sizeof(dat))) { | ||
638 | printk(KERN_ERR "seeprom: read error.\n"); | ||
639 | } else { | ||
640 | if (strcmp(dat, "MAC") != 0) | ||
641 | printk(KERN_WARNING "seeprom: bad signature.\n"); | ||
642 | for (i = 0, sum = 0; i < sizeof(dat); i++) | ||
643 | sum += dat[i]; | ||
644 | if (sum) | ||
645 | printk(KERN_WARNING "seeprom: bad checksum.\n"); | ||
646 | } | ||
647 | } | ||
648 | memcpy(addr, &dat[4 + 6 * ch], 6); | ||
649 | return 0; | 623 | return 0; |
650 | } | 624 | } |
651 | #endif /* CONFIG_PCI */ | 625 | #endif /* CONFIG_PCI */ |
652 | 626 | ||
653 | extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)); | ||
654 | static void __init rbtx4938_spi_setup(void) | 627 | static void __init rbtx4938_spi_setup(void) |
655 | { | 628 | { |
656 | /* set SPI_SEL */ | 629 | /* set SPI_SEL */ |
@@ -658,7 +631,6 @@ static void __init rbtx4938_spi_setup(void) | |||
658 | /* chip selects for SPI devices */ | 631 | /* chip selects for SPI devices */ |
659 | tx4938_pioptr->dout |= (1 << SEEPROM1_CS); | 632 | tx4938_pioptr->dout |= (1 << SEEPROM1_CS); |
660 | tx4938_pioptr->dir |= (1 << SEEPROM1_CS); | 633 | tx4938_pioptr->dir |= (1 << SEEPROM1_CS); |
661 | txx9_spi_init(TX4938_SPI_REG, rbtx4938_spi_cs_func); | ||
662 | } | 634 | } |
663 | 635 | ||
664 | static struct resource rbtx4938_fpga_resource; | 636 | static struct resource rbtx4938_fpga_resource; |
@@ -897,10 +869,8 @@ void tx4938_report_pcic_status(void) | |||
897 | /* We use onchip r4k counter or TMR timer as our system wide timer | 869 | /* We use onchip r4k counter or TMR timer as our system wide timer |
898 | * interrupt running at 100HZ. */ | 870 | * interrupt running at 100HZ. */ |
899 | 871 | ||
900 | extern void __init rtc_rx5c348_init(int chipid); | ||
901 | void __init rbtx4938_time_init(void) | 872 | void __init rbtx4938_time_init(void) |
902 | { | 873 | { |
903 | rtc_rx5c348_init(RBTX4938_SRTC_CHIPID); | ||
904 | mips_hpt_frequency = txx9_cpu_clock / 2; | 874 | mips_hpt_frequency = txx9_cpu_clock / 2; |
905 | } | 875 | } |
906 | 876 | ||
@@ -1017,29 +987,6 @@ void __init toshiba_rbtx4938_setup(void) | |||
1017 | *rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr); | 987 | *rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr); |
1018 | } | 988 | } |
1019 | 989 | ||
1020 | #ifdef CONFIG_PROC_FS | ||
1021 | extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid); | ||
1022 | static int __init tx4938_spi_proc_setup(void) | ||
1023 | { | ||
1024 | struct proc_dir_entry *tx4938_spi_eeprom_dir; | ||
1025 | |||
1026 | tx4938_spi_eeprom_dir = proc_mkdir("spi_eeprom", 0); | ||
1027 | |||
1028 | if (!tx4938_spi_eeprom_dir) | ||
1029 | return -ENOMEM; | ||
1030 | |||
1031 | /* don't allow user access to RBTX4938_SEEPROM1_CHIPID | ||
1032 | * as it contains eth0 and eth1 MAC addresses | ||
1033 | */ | ||
1034 | spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM2_CHIPID); | ||
1035 | spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM3_CHIPID); | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | __initcall(tx4938_spi_proc_setup); | ||
1041 | #endif | ||
1042 | |||
1043 | static int __init rbtx4938_ne_init(void) | 990 | static int __init rbtx4938_ne_init(void) |
1044 | { | 991 | { |
1045 | struct resource res[] = { | 992 | struct resource res[] = { |
@@ -1161,3 +1108,73 @@ void gpio_set_value(unsigned gpio, int value) | |||
1161 | else | 1108 | else |
1162 | rbtx4938_spi_gpio_set(gpio, value); | 1109 | rbtx4938_spi_gpio_set(gpio, value); |
1163 | } | 1110 | } |
1111 | |||
1112 | /* SPI support */ | ||
1113 | |||
1114 | static void __init txx9_spi_init(unsigned long base, int irq) | ||
1115 | { | ||
1116 | struct resource res[] = { | ||
1117 | { | ||
1118 | .start = base, | ||
1119 | .end = base + 0x20 - 1, | ||
1120 | .flags = IORESOURCE_MEM, | ||
1121 | .parent = &tx4938_reg_resource, | ||
1122 | }, { | ||
1123 | .start = irq, | ||
1124 | .flags = IORESOURCE_IRQ, | ||
1125 | }, | ||
1126 | }; | ||
1127 | platform_device_register_simple("txx9spi", 0, | ||
1128 | res, ARRAY_SIZE(res)); | ||
1129 | } | ||
1130 | |||
1131 | static int __init rbtx4938_spi_init(void) | ||
1132 | { | ||
1133 | struct spi_board_info srtc_info = { | ||
1134 | .modalias = "rs5c348", | ||
1135 | .max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */ | ||
1136 | .bus_num = 0, | ||
1137 | .chip_select = 16 + SRTC_CS, | ||
1138 | /* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS */ | ||
1139 | .mode = SPI_MODE_1 | SPI_CS_HIGH, | ||
1140 | }; | ||
1141 | spi_register_board_info(&srtc_info, 1); | ||
1142 | spi_eeprom_register(SEEPROM1_CS); | ||
1143 | spi_eeprom_register(16 + SEEPROM2_CS); | ||
1144 | spi_eeprom_register(16 + SEEPROM3_CS); | ||
1145 | txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI); | ||
1146 | return 0; | ||
1147 | } | ||
1148 | arch_initcall(rbtx4938_spi_init); | ||
1149 | |||
1150 | /* Minimum CLK support */ | ||
1151 | |||
1152 | struct clk *clk_get(struct device *dev, const char *id) | ||
1153 | { | ||
1154 | if (!strcmp(id, "spi-baseclk")) | ||
1155 | return (struct clk *)(txx9_gbus_clock / 2 / 4); | ||
1156 | return ERR_PTR(-ENOENT); | ||
1157 | } | ||
1158 | EXPORT_SYMBOL(clk_get); | ||
1159 | |||
1160 | int clk_enable(struct clk *clk) | ||
1161 | { | ||
1162 | return 0; | ||
1163 | } | ||
1164 | EXPORT_SYMBOL(clk_enable); | ||
1165 | |||
1166 | void clk_disable(struct clk *clk) | ||
1167 | { | ||
1168 | } | ||
1169 | EXPORT_SYMBOL(clk_disable); | ||
1170 | |||
1171 | unsigned long clk_get_rate(struct clk *clk) | ||
1172 | { | ||
1173 | return (unsigned long)clk; | ||
1174 | } | ||
1175 | EXPORT_SYMBOL(clk_get_rate); | ||
1176 | |||
1177 | void clk_put(struct clk *clk) | ||
1178 | { | ||
1179 | } | ||
1180 | EXPORT_SYMBOL(clk_put); | ||
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c index 89596e62f909..4d6b4ade5e8c 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c | |||
@@ -10,209 +10,90 @@ | |||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | 10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) |
11 | */ | 11 | */ |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/delay.h> | 13 | #include <linux/device.h> |
14 | #include <linux/proc_fs.h> | 14 | #include <linux/spi/spi.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/spi/eeprom.h> |
16 | #include <asm/tx4938/spi.h> | 16 | #include <asm/tx4938/spi.h> |
17 | #include <asm/tx4938/tx4938.h> | ||
18 | 17 | ||
19 | /* ATMEL 250x0 instructions */ | 18 | #define AT250X0_PAGE_SIZE 8 |
20 | #define ATMEL_WREN 0x06 | ||
21 | #define ATMEL_WRDI 0x04 | ||
22 | #define ATMEL_RDSR 0x05 | ||
23 | #define ATMEL_WRSR 0x01 | ||
24 | #define ATMEL_READ 0x03 | ||
25 | #define ATMEL_WRITE 0x02 | ||
26 | 19 | ||
27 | #define ATMEL_SR_BSY 0x01 | 20 | /* register board information for at25 driver */ |
28 | #define ATMEL_SR_WEN 0x02 | 21 | int __init spi_eeprom_register(int chipid) |
29 | #define ATMEL_SR_BP0 0x04 | ||
30 | #define ATMEL_SR_BP1 0x08 | ||
31 | |||
32 | DEFINE_SPINLOCK(spi_eeprom_lock); | ||
33 | |||
34 | static struct spi_dev_desc seeprom_dev_desc = { | ||
35 | .baud = 1500000, /* 1.5Mbps */ | ||
36 | .tcss = 1, | ||
37 | .tcsh = 1, | ||
38 | .tcsr = 1, | ||
39 | .byteorder = 1, /* MSB-First */ | ||
40 | .polarity = 0, /* High-Active */ | ||
41 | .phase = 0, /* Sample-Then-Shift */ | ||
42 | |||
43 | }; | ||
44 | static inline int | ||
45 | spi_eeprom_io(int chipid, | ||
46 | unsigned char **inbufs, unsigned int *incounts, | ||
47 | unsigned char **outbufs, unsigned int *outcounts) | ||
48 | { | ||
49 | return txx9_spi_io(chipid, &seeprom_dev_desc, | ||
50 | inbufs, incounts, outbufs, outcounts, 0); | ||
51 | } | ||
52 | |||
53 | int spi_eeprom_write_enable(int chipid, int enable) | ||
54 | { | 22 | { |
55 | unsigned char inbuf[1]; | 23 | static struct spi_eeprom eeprom = { |
56 | unsigned char *inbufs[1]; | 24 | .name = "at250x0", |
57 | unsigned int incounts[2]; | 25 | .byte_len = 128, |
58 | unsigned long flags; | 26 | .page_size = AT250X0_PAGE_SIZE, |
59 | int stat; | 27 | .flags = EE_ADDR1, |
60 | inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI; | 28 | }; |
61 | inbufs[0] = inbuf; | 29 | struct spi_board_info info = { |
62 | incounts[0] = sizeof(inbuf); | 30 | .modalias = "at25", |
63 | incounts[1] = 0; | 31 | .max_speed_hz = 1500000, /* 1.5Mbps */ |
64 | spin_lock_irqsave(&spi_eeprom_lock, flags); | 32 | .bus_num = 0, |
65 | stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL); | 33 | .chip_select = chipid, |
66 | spin_unlock_irqrestore(&spi_eeprom_lock, flags); | 34 | .platform_data = &eeprom, |
67 | return stat; | 35 | /* Mode 0: High-Active, Sample-Then-Shift */ |
68 | } | 36 | }; |
69 | 37 | ||
70 | static int spi_eeprom_read_status_nolock(int chipid) | 38 | return spi_register_board_info(&info, 1); |
71 | { | ||
72 | unsigned char inbuf[2], outbuf[2]; | ||
73 | unsigned char *inbufs[1], *outbufs[1]; | ||
74 | unsigned int incounts[2], outcounts[2]; | ||
75 | int stat; | ||
76 | inbuf[0] = ATMEL_RDSR; | ||
77 | inbuf[1] = 0; | ||
78 | inbufs[0] = inbuf; | ||
79 | incounts[0] = sizeof(inbuf); | ||
80 | incounts[1] = 0; | ||
81 | outbufs[0] = outbuf; | ||
82 | outcounts[0] = sizeof(outbuf); | ||
83 | outcounts[1] = 0; | ||
84 | stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts); | ||
85 | if (stat < 0) | ||
86 | return stat; | ||
87 | return outbuf[1]; | ||
88 | } | 39 | } |
89 | 40 | ||
90 | int spi_eeprom_read_status(int chipid) | 41 | /* simple temporary spi driver to provide early access to seeprom. */ |
91 | { | ||
92 | unsigned long flags; | ||
93 | int stat; | ||
94 | spin_lock_irqsave(&spi_eeprom_lock, flags); | ||
95 | stat = spi_eeprom_read_status_nolock(chipid); | ||
96 | spin_unlock_irqrestore(&spi_eeprom_lock, flags); | ||
97 | return stat; | ||
98 | } | ||
99 | 42 | ||
100 | int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len) | 43 | static struct read_param { |
101 | { | 44 | int chipid; |
102 | unsigned char inbuf[2]; | 45 | int address; |
103 | unsigned char *inbufs[2], *outbufs[2]; | 46 | unsigned char *buf; |
104 | unsigned int incounts[2], outcounts[3]; | 47 | int len; |
105 | unsigned long flags; | 48 | } *read_param; |
106 | int stat; | ||
107 | inbuf[0] = ATMEL_READ; | ||
108 | inbuf[1] = address; | ||
109 | inbufs[0] = inbuf; | ||
110 | inbufs[1] = NULL; | ||
111 | incounts[0] = sizeof(inbuf); | ||
112 | incounts[1] = 0; | ||
113 | outbufs[0] = NULL; | ||
114 | outbufs[1] = buf; | ||
115 | outcounts[0] = 2; | ||
116 | outcounts[1] = len; | ||
117 | outcounts[2] = 0; | ||
118 | spin_lock_irqsave(&spi_eeprom_lock, flags); | ||
119 | stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts); | ||
120 | spin_unlock_irqrestore(&spi_eeprom_lock, flags); | ||
121 | return stat; | ||
122 | } | ||
123 | 49 | ||
124 | int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len) | 50 | static int __init early_seeprom_probe(struct spi_device *spi) |
125 | { | 51 | { |
126 | unsigned char inbuf[2]; | 52 | int stat = 0; |
127 | unsigned char *inbufs[2]; | 53 | u8 cmd[2]; |
128 | unsigned int incounts[3]; | 54 | int len = read_param->len; |
129 | unsigned long flags; | 55 | char *buf = read_param->buf; |
130 | int i, stat; | 56 | int address = read_param->address; |
131 | 57 | ||
132 | if (address / 8 != (address + len - 1) / 8) | 58 | dev_info(&spi->dev, "spiclk %u KHz.\n", |
133 | return -EINVAL; | 59 | (spi->max_speed_hz + 500) / 1000); |
134 | stat = spi_eeprom_write_enable(chipid, 1); | 60 | if (read_param->chipid != spi->chip_select) |
135 | if (stat < 0) | 61 | return -ENODEV; |
136 | return stat; | 62 | while (len > 0) { |
137 | stat = spi_eeprom_read_status(chipid); | 63 | /* spi_write_then_read can only work with small chunk */ |
138 | if (stat < 0) | 64 | int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE; |
139 | return stat; | 65 | cmd[0] = 0x03; /* AT25_READ */ |
140 | if (!(stat & ATMEL_SR_WEN)) | 66 | cmd[1] = address; |
141 | return -EPERM; | 67 | stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c); |
142 | 68 | buf += c; | |
143 | inbuf[0] = ATMEL_WRITE; | 69 | len -= c; |
144 | inbuf[1] = address; | 70 | address += c; |
145 | inbufs[0] = inbuf; | ||
146 | inbufs[1] = buf; | ||
147 | incounts[0] = sizeof(inbuf); | ||
148 | incounts[1] = len; | ||
149 | incounts[2] = 0; | ||
150 | spin_lock_irqsave(&spi_eeprom_lock, flags); | ||
151 | stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL); | ||
152 | if (stat < 0) | ||
153 | goto unlock_return; | ||
154 | |||
155 | /* write start. max 10ms */ | ||
156 | for (i = 10; i > 0; i--) { | ||
157 | int stat = spi_eeprom_read_status_nolock(chipid); | ||
158 | if (stat < 0) | ||
159 | goto unlock_return; | ||
160 | if (!(stat & ATMEL_SR_BSY)) | ||
161 | break; | ||
162 | mdelay(1); | ||
163 | } | 71 | } |
164 | spin_unlock_irqrestore(&spi_eeprom_lock, flags); | ||
165 | if (i == 0) | ||
166 | return -EIO; | ||
167 | return len; | ||
168 | unlock_return: | ||
169 | spin_unlock_irqrestore(&spi_eeprom_lock, flags); | ||
170 | return stat; | 72 | return stat; |
171 | } | 73 | } |
172 | 74 | ||
173 | #ifdef CONFIG_PROC_FS | 75 | static struct spi_driver early_seeprom_driver __initdata = { |
174 | #define MAX_SIZE 0x80 /* for ATMEL 25010 */ | 76 | .driver = { |
175 | static int spi_eeprom_read_proc(char *page, char **start, off_t off, | 77 | .name = "at25", |
176 | int count, int *eof, void *data) | 78 | .owner = THIS_MODULE, |
177 | { | 79 | }, |
178 | unsigned int size = MAX_SIZE; | 80 | .probe = early_seeprom_probe, |
179 | if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0) | 81 | }; |
180 | size = 0; | ||
181 | return size; | ||
182 | } | ||
183 | |||
184 | static int spi_eeprom_write_proc(struct file *file, const char *buffer, | ||
185 | unsigned long count, void *data) | ||
186 | { | ||
187 | unsigned int size = MAX_SIZE; | ||
188 | int i; | ||
189 | if (file->f_pos >= size) | ||
190 | return -EIO; | ||
191 | if (file->f_pos + count > size) | ||
192 | count = size - file->f_pos; | ||
193 | for (i = 0; i < count; i += 8) { | ||
194 | int len = count - i < 8 ? count - i : 8; | ||
195 | if (spi_eeprom_write((int)data, file->f_pos, | ||
196 | (unsigned char *)buffer, len) < 0) { | ||
197 | count = -EIO; | ||
198 | break; | ||
199 | } | ||
200 | buffer += len; | ||
201 | file->f_pos += len; | ||
202 | } | ||
203 | return count; | ||
204 | } | ||
205 | 82 | ||
206 | __init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid) | 83 | int __init spi_eeprom_read(int chipid, int address, |
84 | unsigned char *buf, int len) | ||
207 | { | 85 | { |
208 | struct proc_dir_entry *entry; | 86 | int ret; |
209 | char name[128]; | 87 | struct read_param param = { |
210 | sprintf(name, "seeprom-%d", chipid); | 88 | .chipid = chipid, |
211 | entry = create_proc_entry(name, 0600, dir); | 89 | .address = address, |
212 | if (entry) { | 90 | .buf = buf, |
213 | entry->read_proc = spi_eeprom_read_proc; | 91 | .len = len |
214 | entry->write_proc = spi_eeprom_write_proc; | 92 | }; |
215 | entry->data = (void *)chipid; | 93 | |
216 | } | 94 | read_param = ¶m; |
95 | ret = spi_register_driver(&early_seeprom_driver); | ||
96 | if (!ret) | ||
97 | spi_unregister_driver(&early_seeprom_driver); | ||
98 | return ret; | ||
217 | } | 99 | } |
218 | #endif /* CONFIG_PROC_FS */ | ||
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c deleted file mode 100644 index 08b20cdfd7b3..000000000000 --- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c +++ /dev/null | |||
@@ -1,164 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/wait.h> | ||
20 | #include <asm/tx4938/spi.h> | ||
21 | #include <asm/tx4938/tx4938.h> | ||
22 | |||
23 | static int (*txx9_spi_cs_func)(int chipid, int on); | ||
24 | static DEFINE_SPINLOCK(txx9_spi_lock); | ||
25 | |||
26 | extern unsigned int txx9_gbus_clock; | ||
27 | |||
28 | #define SPI_FIFO_SIZE 4 | ||
29 | |||
30 | void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)) | ||
31 | { | ||
32 | txx9_spi_cs_func = cs_func; | ||
33 | /* enter config mode */ | ||
34 | tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR; | ||
35 | } | ||
36 | |||
37 | static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait); | ||
38 | |||
39 | static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id) | ||
40 | { | ||
41 | /* disable rx intr */ | ||
42 | tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE; | ||
43 | wake_up(&txx9_spi_wait); | ||
44 | |||
45 | return IRQ_HANDLED; | ||
46 | } | ||
47 | |||
48 | static struct irqaction txx9_spi_action = { | ||
49 | .handler = txx9_spi_interrupt, | ||
50 | .name = "spi", | ||
51 | }; | ||
52 | |||
53 | void __init txx9_spi_irqinit(int irc_irq) | ||
54 | { | ||
55 | setup_irq(irc_irq, &txx9_spi_action); | ||
56 | } | ||
57 | |||
58 | int txx9_spi_io(int chipid, struct spi_dev_desc *desc, | ||
59 | unsigned char **inbufs, unsigned int *incounts, | ||
60 | unsigned char **outbufs, unsigned int *outcounts, | ||
61 | int cansleep) | ||
62 | { | ||
63 | unsigned int incount, outcount; | ||
64 | unsigned char *inp, *outp; | ||
65 | int ret; | ||
66 | unsigned long flags; | ||
67 | |||
68 | spin_lock_irqsave(&txx9_spi_lock, flags); | ||
69 | if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) { | ||
70 | spin_unlock_irqrestore(&txx9_spi_lock, flags); | ||
71 | return -EBUSY; | ||
72 | } | ||
73 | /* enter config mode */ | ||
74 | tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR; | ||
75 | tx4938_spiptr->cr0 = | ||
76 | (desc->byteorder ? TXx9_SPCR0_SBOS : 0) | | ||
77 | (desc->polarity ? TXx9_SPCR0_SPOL : 0) | | ||
78 | (desc->phase ? TXx9_SPCR0_SPHA : 0) | | ||
79 | 0x08; | ||
80 | tx4938_spiptr->cr1 = | ||
81 | (((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) | | ||
82 | 0x08 /* 8 bit only */; | ||
83 | /* enter active mode */ | ||
84 | tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE; | ||
85 | spin_unlock_irqrestore(&txx9_spi_lock, flags); | ||
86 | |||
87 | /* CS ON */ | ||
88 | if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) { | ||
89 | spin_unlock_irqrestore(&txx9_spi_lock, flags); | ||
90 | return ret; | ||
91 | } | ||
92 | udelay(desc->tcss); | ||
93 | |||
94 | /* do scatter IO */ | ||
95 | inp = inbufs ? *inbufs : NULL; | ||
96 | outp = outbufs ? *outbufs : NULL; | ||
97 | incount = 0; | ||
98 | outcount = 0; | ||
99 | while (1) { | ||
100 | unsigned char data; | ||
101 | unsigned int count; | ||
102 | int i; | ||
103 | if (!incount) { | ||
104 | incount = incounts ? *incounts++ : 0; | ||
105 | inp = (incount && inbufs) ? *inbufs++ : NULL; | ||
106 | } | ||
107 | if (!outcount) { | ||
108 | outcount = outcounts ? *outcounts++ : 0; | ||
109 | outp = (outcount && outbufs) ? *outbufs++ : NULL; | ||
110 | } | ||
111 | if (!inp && !outp) | ||
112 | break; | ||
113 | count = SPI_FIFO_SIZE; | ||
114 | if (incount) | ||
115 | count = min(count, incount); | ||
116 | if (outcount) | ||
117 | count = min(count, outcount); | ||
118 | |||
119 | /* now tx must be idle... */ | ||
120 | while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE)) | ||
121 | ; | ||
122 | |||
123 | tx4938_spiptr->cr0 = | ||
124 | (tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) | | ||
125 | ((count - 1) << 12); | ||
126 | if (cansleep) { | ||
127 | /* enable rx intr */ | ||
128 | tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE; | ||
129 | } | ||
130 | /* send */ | ||
131 | for (i = 0; i < count; i++) | ||
132 | tx4938_spiptr->dr = inp ? *inp++ : 0; | ||
133 | /* wait all rx data */ | ||
134 | if (cansleep) { | ||
135 | wait_event(txx9_spi_wait, | ||
136 | tx4938_spiptr->sr & TXx9_SPSR_SRRDY); | ||
137 | } else { | ||
138 | while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI)) | ||
139 | ; | ||
140 | } | ||
141 | /* receive */ | ||
142 | for (i = 0; i < count; i++) { | ||
143 | data = tx4938_spiptr->dr; | ||
144 | if (outp) | ||
145 | *outp++ = data; | ||
146 | } | ||
147 | if (incount) | ||
148 | incount -= count; | ||
149 | if (outcount) | ||
150 | outcount -= count; | ||
151 | } | ||
152 | |||
153 | /* CS OFF */ | ||
154 | udelay(desc->tcsh); | ||
155 | txx9_spi_cs_func(chipid, 0); | ||
156 | udelay(desc->tcsr); | ||
157 | |||
158 | spin_lock_irqsave(&txx9_spi_lock, flags); | ||
159 | /* enter config mode */ | ||
160 | tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR; | ||
161 | spin_unlock_irqrestore(&txx9_spi_lock, flags); | ||
162 | |||
163 | return 0; | ||
164 | } | ||