]>
Commit | Line | Data |
---|---|---|
23fbee9d | 1 | /* |
23fbee9d RB |
2 | * Setup pointers to hardware-dependent routines. |
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 | */ | |
23fbee9d RB |
12 | #include <linux/init.h> |
13 | #include <linux/types.h> | |
14 | #include <linux/ioport.h> | |
23fbee9d | 15 | #include <linux/delay.h> |
57e386ce | 16 | #include <linux/platform_device.h> |
4cad154b | 17 | #include <linux/gpio.h> |
51f607c7 | 18 | #include <linux/mtd/physmap.h> |
fcdb27ad | 19 | |
23fbee9d | 20 | #include <asm/reboot.h> |
23fbee9d | 21 | #include <asm/io.h> |
89d63fe1 AN |
22 | #include <asm/txx9/generic.h> |
23 | #include <asm/txx9/pci.h> | |
22b1d707 | 24 | #include <asm/txx9/rbtx4938.h> |
f74cf6ff | 25 | #include <linux/spi/spi.h> |
22b1d707 | 26 | #include <asm/txx9/spi.h> |
4cad154b | 27 | #include <asm/txx9pio.h> |
23fbee9d | 28 | |
7b226094 | 29 | static void rbtx4938_machine_restart(char *command) |
23fbee9d RB |
30 | { |
31 | local_irq_disable(); | |
66140c8e AN |
32 | writeb(1, rbtx4938_softresetlock_addr); |
33 | writeb(1, rbtx4938_sfvol_addr); | |
34 | writeb(1, rbtx4938_softreset_addr); | |
a49297e8 AN |
35 | /* fallback */ |
36 | (*_machine_halt)(); | |
23fbee9d RB |
37 | } |
38 | ||
89d63fe1 | 39 | static void __init rbtx4938_pci_setup(void) |
23fbee9d | 40 | { |
23fbee9d | 41 | #ifdef CONFIG_PCI |
89d63fe1 AN |
42 | int extarb = !(__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCIARB); |
43 | struct pci_controller *c = &txx9_primary_pcic; | |
23fbee9d | 44 | |
89d63fe1 | 45 | register_pci_controller(c); |
23fbee9d | 46 | |
89d63fe1 AN |
47 | if (__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66) |
48 | txx9_pci_option = | |
49 | (txx9_pci_option & ~TXX9_PCI_OPT_CLK_MASK) | | |
50 | TXX9_PCI_OPT_CLK_66; /* already configured */ | |
23fbee9d RB |
51 | |
52 | /* Reset PCI Bus */ | |
66140c8e | 53 | writeb(0, rbtx4938_pcireset_addr); |
23fbee9d | 54 | /* Reset PCIC */ |
89d63fe1 AN |
55 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); |
56 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | |
57 | TXX9_PCI_OPT_CLK_66) | |
23fbee9d RB |
58 | tx4938_pciclk66_setup(); |
59 | mdelay(10); | |
60 | /* clear PCIC reset */ | |
89d63fe1 | 61 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); |
66140c8e | 62 | writeb(1, rbtx4938_pcireset_addr); |
89d63fe1 | 63 | iob(); |
23fbee9d RB |
64 | |
65 | tx4938_report_pciclk(); | |
89d63fe1 AN |
66 | tx4927_pcic_setup(tx4938_pcicptr, c, extarb); |
67 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | |
68 | TXX9_PCI_OPT_CLK_AUTO && | |
69 | txx9_pci66_check(c, 0, 0)) { | |
23fbee9d | 70 | /* Reset PCI Bus */ |
66140c8e | 71 | writeb(0, rbtx4938_pcireset_addr); |
23fbee9d | 72 | /* Reset PCIC */ |
89d63fe1 | 73 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); |
23fbee9d RB |
74 | tx4938_pciclk66_setup(); |
75 | mdelay(10); | |
76 | /* clear PCIC reset */ | |
89d63fe1 | 77 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); |
66140c8e | 78 | writeb(1, rbtx4938_pcireset_addr); |
89d63fe1 | 79 | iob(); |
23fbee9d RB |
80 | /* Reinitialize PCIC */ |
81 | tx4938_report_pciclk(); | |
89d63fe1 | 82 | tx4927_pcic_setup(tx4938_pcicptr, c, extarb); |
23fbee9d RB |
83 | } |
84 | ||
89d63fe1 AN |
85 | if (__raw_readq(&tx4938_ccfgptr->pcfg) & |
86 | (TX4938_PCFG_ETH0_SEL|TX4938_PCFG_ETH1_SEL)) { | |
87 | /* Reset PCIC1 */ | |
88 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST); | |
89 | /* PCI1DMD==0 => PCI1CLK==GBUSCLK/2 => PCI66 */ | |
90 | if (!(__raw_readq(&tx4938_ccfgptr->ccfg) | |
91 | & TX4938_CCFG_PCI1DMD)) | |
92 | tx4938_ccfg_set(TX4938_CCFG_PCI1_66); | |
93 | mdelay(10); | |
94 | /* clear PCIC1 reset */ | |
95 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST); | |
96 | tx4938_report_pci1clk(); | |
97 | ||
98 | /* mem:64K(max), io:64K(max) (enough for ETH0,ETH1) */ | |
99 | c = txx9_alloc_pci_controller(NULL, 0, 0x10000, 0, 0x10000); | |
100 | register_pci_controller(c); | |
101 | tx4927_pcic_setup(tx4938_pcic1ptr, c, 0); | |
102 | } | |
455cc256 | 103 | tx4938_setup_pcierr_irq(); |
23fbee9d | 104 | #endif /* CONFIG_PCI */ |
89d63fe1 | 105 | } |
23fbee9d RB |
106 | |
107 | /* SPI support */ | |
108 | ||
109 | /* chip select for SPI devices */ | |
70342287 RB |
110 | #define SEEPROM1_CS 7 /* PIO7 */ |
111 | #define SEEPROM2_CS 0 /* IOC */ | |
112 | #define SEEPROM3_CS 1 /* IOC */ | |
113 | #define SRTC_CS 2 /* IOC */ | |
d75a40e9 | 114 | #define SPI_BUSNO 0 |
23fbee9d | 115 | |
f74cf6ff | 116 | static int __init rbtx4938_ethaddr_init(void) |
23fbee9d | 117 | { |
edcaf1a6 | 118 | #ifdef CONFIG_PCI |
2db30150 | 119 | unsigned char dat[17]; |
f74cf6ff AN |
120 | unsigned char sum; |
121 | int i; | |
122 | ||
123 | /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ | |
d75a40e9 | 124 | if (spi_eeprom_read(SPI_BUSNO, SEEPROM1_CS, 0, dat, sizeof(dat))) { |
f74cf6ff | 125 | printk(KERN_ERR "seeprom: read error.\n"); |
2db30150 AN |
126 | return -ENODEV; |
127 | } else { | |
f74cf6ff AN |
128 | if (strcmp(dat, "MAC") != 0) |
129 | printk(KERN_WARNING "seeprom: bad signature.\n"); | |
130 | for (i = 0, sum = 0; i < sizeof(dat); i++) | |
131 | sum += dat[i]; | |
132 | if (sum) | |
133 | printk(KERN_WARNING "seeprom: bad checksum.\n"); | |
23fbee9d | 134 | } |
c49f91f5 | 135 | tx4938_ethaddr_init(&dat[4], &dat[4 + 6]); |
edcaf1a6 | 136 | #endif /* CONFIG_PCI */ |
23fbee9d RB |
137 | return 0; |
138 | } | |
23fbee9d | 139 | |
23fbee9d RB |
140 | static void __init rbtx4938_spi_setup(void) |
141 | { | |
142 | /* set SPI_SEL */ | |
89d63fe1 | 143 | txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_SPI_SEL); |
23fbee9d RB |
144 | } |
145 | ||
146 | static struct resource rbtx4938_fpga_resource; | |
23fbee9d | 147 | |
edcaf1a6 | 148 | static void __init rbtx4938_time_init(void) |
23fbee9d | 149 | { |
94a4c329 | 150 | tx4938_time_init(0); |
23fbee9d RB |
151 | } |
152 | ||
edcaf1a6 | 153 | static void __init rbtx4938_mem_setup(void) |
23fbee9d RB |
154 | { |
155 | unsigned long long pcfg; | |
23fbee9d | 156 | |
23fbee9d RB |
157 | if (txx9_master_clock == 0) |
158 | txx9_master_clock = 25000000; /* 25MHz */ | |
94a4c329 AN |
159 | |
160 | tx4938_setup(); | |
161 | ||
162 | #ifdef CONFIG_PCI | |
163 | txx9_alloc_pci_controller(&txx9_primary_pcic, 0, 0, 0, 0); | |
07517529 | 164 | txx9_board_pcibios_setup = tx4927_pcibios_setup; |
94a4c329 | 165 | #else |
23fbee9d RB |
166 | set_io_port_base(RBTX4938_ETHER_BASE); |
167 | #endif | |
168 | ||
7779a5e0 | 169 | tx4938_sio_init(7372800, 0); |
23fbee9d RB |
170 | |
171 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61 | |
e6332374 | 172 | pr_info("PIOSEL: disabling both ATA and NAND selection\n"); |
89d63fe1 AN |
173 | txx9_clear64(&tx4938_ccfgptr->pcfg, |
174 | TX4938_PCFG_NDF_SEL | TX4938_PCFG_ATA_SEL); | |
23fbee9d RB |
175 | #endif |
176 | ||
177 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND | |
e6332374 | 178 | pr_info("PIOSEL: enabling NAND selection\n"); |
89d63fe1 AN |
179 | txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); |
180 | txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); | |
23fbee9d RB |
181 | #endif |
182 | ||
183 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA | |
e6332374 | 184 | pr_info("PIOSEL: enabling ATA selection\n"); |
89d63fe1 AN |
185 | txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); |
186 | txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); | |
23fbee9d RB |
187 | #endif |
188 | ||
e6332374 AN |
189 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_KEEP |
190 | pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); | |
191 | pr_info("PIOSEL: NAND %s, ATA %s\n", | |
192 | (pcfg & TX4938_PCFG_NDF_SEL) ? "enabled" : "disabled", | |
193 | (pcfg & TX4938_PCFG_ATA_SEL) ? "enabled" : "disabled"); | |
194 | #endif | |
195 | ||
23fbee9d | 196 | rbtx4938_spi_setup(); |
89d63fe1 | 197 | pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); /* updated */ |
23fbee9d RB |
198 | /* fixup piosel */ |
199 | if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) == | |
66140c8e AN |
200 | TX4938_PCFG_ATA_SEL) |
201 | writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x04, | |
202 | rbtx4938_piosel_addr); | |
23fbee9d | 203 | else if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) == |
66140c8e AN |
204 | TX4938_PCFG_NDF_SEL) |
205 | writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x08, | |
206 | rbtx4938_piosel_addr); | |
207 | else | |
208 | writeb(readb(rbtx4938_piosel_addr) & ~(0x08 | 0x04), | |
209 | rbtx4938_piosel_addr); | |
23fbee9d RB |
210 | |
211 | rbtx4938_fpga_resource.name = "FPGA Registers"; | |
212 | rbtx4938_fpga_resource.start = CPHYSADDR(RBTX4938_FPGA_REG_ADDR); | |
213 | rbtx4938_fpga_resource.end = CPHYSADDR(RBTX4938_FPGA_REG_ADDR) + 0xffff; | |
214 | rbtx4938_fpga_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | |
8d795f2a | 215 | if (request_resource(&txx9_ce_res[2], &rbtx4938_fpga_resource)) |
bb72f1f7 | 216 | printk(KERN_ERR "request resource for fpga failed\n"); |
23fbee9d | 217 | |
23fbee9d | 218 | _machine_restart = rbtx4938_machine_restart; |
23fbee9d | 219 | |
66140c8e AN |
220 | writeb(0xff, rbtx4938_led_addr); |
221 | printk(KERN_INFO "RBTX4938 --- FPGA(Rev %02x) DIPSW:%02x,%02x\n", | |
222 | readb(rbtx4938_fpga_rev_addr), | |
223 | readb(rbtx4938_dipsw_addr), readb(rbtx4938_bdipsw_addr)); | |
23fbee9d RB |
224 | } |
225 | ||
bb72f1f7 | 226 | static void __init rbtx4938_ne_init(void) |
57e386ce AN |
227 | { |
228 | struct resource res[] = { | |
229 | { | |
230 | .start = RBTX4938_RTL_8019_BASE, | |
231 | .end = RBTX4938_RTL_8019_BASE + 0x20 - 1, | |
232 | .flags = IORESOURCE_IO, | |
233 | }, { | |
234 | .start = RBTX4938_RTL_8019_IRQ, | |
235 | .flags = IORESOURCE_IRQ, | |
236 | } | |
237 | }; | |
bb72f1f7 | 238 | platform_device_register_simple("ne", -1, res, ARRAY_SIZE(res)); |
57e386ce | 239 | } |
3896b054 | 240 | |
3896b054 AN |
241 | static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock); |
242 | ||
4cad154b AN |
243 | static void rbtx4938_spi_gpio_set(struct gpio_chip *chip, unsigned int offset, |
244 | int value) | |
3896b054 AN |
245 | { |
246 | u8 val; | |
247 | unsigned long flags; | |
3896b054 | 248 | spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags); |
66140c8e | 249 | val = readb(rbtx4938_spics_addr); |
3896b054 | 250 | if (value) |
4cad154b | 251 | val |= 1 << offset; |
3896b054 | 252 | else |
4cad154b | 253 | val &= ~(1 << offset); |
66140c8e | 254 | writeb(val, rbtx4938_spics_addr); |
3896b054 AN |
255 | mmiowb(); |
256 | spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags); | |
257 | } | |
258 | ||
4cad154b AN |
259 | static int rbtx4938_spi_gpio_dir_out(struct gpio_chip *chip, |
260 | unsigned int offset, int value) | |
3896b054 | 261 | { |
4cad154b | 262 | rbtx4938_spi_gpio_set(chip, offset, value); |
3896b054 AN |
263 | return 0; |
264 | } | |
265 | ||
4cad154b AN |
266 | static struct gpio_chip rbtx4938_spi_gpio_chip = { |
267 | .set = rbtx4938_spi_gpio_set, | |
268 | .direction_output = rbtx4938_spi_gpio_dir_out, | |
269 | .label = "RBTX4938-SPICS", | |
270 | .base = 16, | |
271 | .ngpio = 3, | |
272 | }; | |
f74cf6ff | 273 | |
f74cf6ff AN |
274 | static int __init rbtx4938_spi_init(void) |
275 | { | |
276 | struct spi_board_info srtc_info = { | |
9f90a03a | 277 | .modalias = "rtc-rs5c348", |
f74cf6ff AN |
278 | .max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */ |
279 | .bus_num = 0, | |
280 | .chip_select = 16 + SRTC_CS, | |
281 | /* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS */ | |
282 | .mode = SPI_MODE_1 | SPI_CS_HIGH, | |
283 | }; | |
284 | spi_register_board_info(&srtc_info, 1); | |
d75a40e9 AN |
285 | spi_eeprom_register(SPI_BUSNO, SEEPROM1_CS, 128); |
286 | spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM2_CS, 128); | |
287 | spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM3_CS, 128); | |
4cad154b AN |
288 | gpio_request(16 + SRTC_CS, "rtc-rs5c348"); |
289 | gpio_direction_output(16 + SRTC_CS, 0); | |
290 | gpio_request(SEEPROM1_CS, "seeprom1"); | |
291 | gpio_direction_output(SEEPROM1_CS, 1); | |
292 | gpio_request(16 + SEEPROM2_CS, "seeprom2"); | |
293 | gpio_direction_output(16 + SEEPROM2_CS, 1); | |
294 | gpio_request(16 + SEEPROM3_CS, "seeprom3"); | |
295 | gpio_direction_output(16 + SEEPROM3_CS, 1); | |
d75a40e9 | 296 | tx4938_spi_init(SPI_BUSNO); |
f74cf6ff AN |
297 | return 0; |
298 | } | |
4cad154b | 299 | |
51f607c7 AN |
300 | static void __init rbtx4938_mtd_init(void) |
301 | { | |
302 | struct physmap_flash_data pdata = { | |
303 | .width = 4, | |
304 | }; | |
305 | ||
306 | switch (readb(rbtx4938_bdipsw_addr) & 7) { | |
307 | case 0: | |
308 | /* Boot */ | |
309 | txx9_physmap_flash_init(0, 0x1fc00000, 0x400000, &pdata); | |
310 | /* System */ | |
311 | txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); | |
312 | break; | |
313 | case 1: | |
314 | /* System */ | |
315 | txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); | |
316 | /* Boot */ | |
317 | txx9_physmap_flash_init(1, 0x1ec00000, 0x400000, &pdata); | |
318 | break; | |
319 | case 2: | |
320 | /* Ext */ | |
321 | txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); | |
322 | /* System */ | |
323 | txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); | |
324 | /* Boot */ | |
325 | txx9_physmap_flash_init(2, 0x1dc00000, 0x400000, &pdata); | |
326 | break; | |
327 | case 3: | |
328 | /* Boot */ | |
329 | txx9_physmap_flash_init(1, 0x1bc00000, 0x400000, &pdata); | |
330 | /* System */ | |
331 | txx9_physmap_flash_init(2, 0x1a000000, 0x1000000, &pdata); | |
332 | break; | |
333 | } | |
334 | } | |
335 | ||
edcaf1a6 | 336 | static void __init rbtx4938_arch_init(void) |
4cad154b | 337 | { |
4cad154b | 338 | gpiochip_add(&rbtx4938_spi_gpio_chip); |
89d63fe1 | 339 | rbtx4938_pci_setup(); |
edcaf1a6 | 340 | rbtx4938_spi_init(); |
4cad154b | 341 | } |
f74cf6ff | 342 | |
edcaf1a6 | 343 | static void __init rbtx4938_device_init(void) |
f74cf6ff | 344 | { |
edcaf1a6 AN |
345 | rbtx4938_ethaddr_init(); |
346 | rbtx4938_ne_init(); | |
68314725 | 347 | tx4938_wdt_init(); |
51f607c7 | 348 | rbtx4938_mtd_init(); |
a591f5d3 AN |
349 | /* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */ |
350 | tx4938_ndfmc_init(10, 35); | |
5d1d2f8c | 351 | tx4938_ata_init(RBTX4938_IRQ_IOC_ATA, 0, 1); |
f48c8c95 | 352 | tx4938_dmac_init(0, 2); |
742cd586 AN |
353 | tx4938_aclc_init(); |
354 | platform_device_register_simple("txx9aclc-generic", -1, NULL, 0); | |
c3b28ae2 | 355 | tx4938_sramc_init(); |
ae027ead | 356 | txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL); |
f74cf6ff | 357 | } |
f74cf6ff | 358 | |
edcaf1a6 | 359 | struct txx9_board_vec rbtx4938_vec __initdata = { |
edcaf1a6 AN |
360 | .system = "Toshiba RBTX4938", |
361 | .prom_init = rbtx4938_prom_init, | |
362 | .mem_setup = rbtx4938_mem_setup, | |
363 | .irq_setup = rbtx4938_irq_setup, | |
364 | .time_init = rbtx4938_time_init, | |
365 | .device_init = rbtx4938_device_init, | |
366 | .arch_init = rbtx4938_arch_init, | |
367 | #ifdef CONFIG_PCI | |
368 | .pci_map_irq = rbtx4938_pci_map_irq, | |
369 | #endif | |
370 | }; |