X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=arch%2Fmips%2Ftx4938%2Ftoshiba_rbtx4938%2Fsetup.c;h=96e833cd4c14260e6ea40a77ebef990ceae6433d;hb=7d9ef601ddf0a42d11df3bdaaf28078fd2995eab;hp=9166cd4557eb01f1b5e7db4777d882ac4a97416c;hpb=95d465fd750897ab32462a6702fbfe1b122cbbc0;p=mv-sheeva.git diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index 9166cd4557e..f236b1ff892 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -11,16 +11,16 @@ * * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) */ -#include #include #include #include -#include #include #include #include #include #include +#include +#include #include #include @@ -35,6 +35,9 @@ #include #include #endif +#include +#include +#include extern void rbtx4938_time_init(void) __init; extern char * __init prom_getcmdline(void); @@ -349,7 +352,7 @@ static struct pci_dev *fake_pci_dev(struct pci_controller *hose, static struct pci_dev dev; static struct pci_bus bus; - dev.sysdata = (void *)hose; + dev.sysdata = bus.sysdata = hose; dev.devfn = devfn; bus.number = busnr; bus.ops = hose->pci_ops; @@ -382,8 +385,10 @@ int txboard_pci66_check(struct pci_controller *hose, int top_bus, int current_bu printk("PCI: Checking 66MHz capabilities...\n"); for (pci_devfn=devfn_start; pci_devfnccfg & TX4938_CCFG_PCIXARB); PCIBIOS_MIN_IO = 0x00001000UL; - PCIBIOS_MIN_MEM = 0x01000000UL; mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]); io_base[0] = txboard_request_phys_region_shrink(&io_size[0]); @@ -574,82 +578,43 @@ arch_initcall(tx4938_pcibios_init); #define SEEPROM3_CS 1 /* IOC */ #define SRTC_CS 2 /* IOC */ -static int rbtx4938_spi_cs_func(int chipid, int on) -{ - unsigned char bit; - switch (chipid) { - case RBTX4938_SEEPROM1_CHIPID: - if (on) - tx4938_pioptr->dout &= ~(1 << SEEPROM1_CS); - else - tx4938_pioptr->dout |= (1 << SEEPROM1_CS); - return 0; - break; - case RBTX4938_SEEPROM2_CHIPID: - bit = (1 << SEEPROM2_CS); - break; - case RBTX4938_SEEPROM3_CHIPID: - bit = (1 << SEEPROM3_CS); - break; - case RBTX4938_SRTC_CHIPID: - bit = (1 << SRTC_CS); - break; - default: - return -ENODEV; - } - /* bit1,2,4 are low active, bit3 is high active */ - *rbtx4938_spics_ptr = - (*rbtx4938_spics_ptr & ~bit) | - ((on ? (bit ^ 0x0b) : ~(bit ^ 0x0b)) & bit); - return 0; -} - #ifdef CONFIG_PCI -extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len); - -int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr) +static int __init rbtx4938_ethaddr_init(void) { - struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata; - static unsigned char dat[17]; - static int read_dat = 0; - int ch = 0; + unsigned char dat[17]; + unsigned char sum; + int i; - if (channel != &tx4938_pci_controller[1]) - return -ENODEV; - /* TX4938 PCIC1 */ - switch (PCI_SLOT(dev->devfn)) { - case TX4938_PCIC_IDSEL_AD_TO_SLOT(31): - ch = 0; - break; - case TX4938_PCIC_IDSEL_AD_TO_SLOT(30): - ch = 1; - break; - default: + /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ + if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) { + printk(KERN_ERR "seeprom: read error.\n"); return -ENODEV; + } else { + if (strcmp(dat, "MAC") != 0) + printk(KERN_WARNING "seeprom: bad signature.\n"); + for (i = 0, sum = 0; i < sizeof(dat); i++) + sum += dat[i]; + if (sum) + printk(KERN_WARNING "seeprom: bad checksum.\n"); } - if (!read_dat) { - unsigned char sum; - int i; - read_dat = 1; - /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ - if (spi_eeprom_read(RBTX4938_SEEPROM1_CHIPID, - 0, dat, sizeof(dat))) { - printk(KERN_ERR "seeprom: read error.\n"); - } else { - if (strcmp(dat, "MAC") != 0) - printk(KERN_WARNING "seeprom: bad signature.\n"); - for (i = 0, sum = 0; i < sizeof(dat); i++) - sum += dat[i]; - if (sum) - printk(KERN_WARNING "seeprom: bad checksum.\n"); - } + for (i = 0; i < 2; i++) { + unsigned int slot = TX4938_PCIC_IDSEL_AD_TO_SLOT(31 - i); + unsigned int id = (1 << 8) | PCI_DEVFN(slot, 0); /* bus 1 */ + struct platform_device *pdev; + if (!(tx4938_ccfgptr->pcfg & + (i ? TX4938_PCFG_ETH1_SEL : TX4938_PCFG_ETH0_SEL))) + continue; + pdev = platform_device_alloc("tc35815-mac", id); + if (!pdev || + platform_device_add_data(pdev, &dat[4 + 6 * i], 6) || + platform_device_add(pdev)) + platform_device_put(pdev); } - memcpy(addr, &dat[4 + 6 * ch], 6); return 0; } +device_initcall(rbtx4938_ethaddr_init); #endif /* CONFIG_PCI */ -extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)); static void __init rbtx4938_spi_setup(void) { /* set SPI_SEL */ @@ -657,14 +622,16 @@ static void __init rbtx4938_spi_setup(void) /* chip selects for SPI devices */ tx4938_pioptr->dout |= (1 << SEEPROM1_CS); tx4938_pioptr->dir |= (1 << SEEPROM1_CS); - txx9_spi_init(TX4938_SPI_REG, rbtx4938_spi_cs_func); } static struct resource rbtx4938_fpga_resource; static char pcode_str[8]; static struct resource tx4938_reg_resource = { - pcode_str, TX4938_REG_BASE, TX4938_REG_BASE+TX4938_REG_SIZE, IORESOURCE_MEM + .start = TX4938_REG_BASE, + .end = TX4938_REG_BASE + TX4938_REG_SIZE, + .name = pcode_str, + .flags = IORESOURCE_MEM }; void __init tx4938_board_setup(void) @@ -690,7 +657,7 @@ void __init tx4938_board_setup(void) /* clocks */ if (txx9_master_clock) { - /* calculate gbus_clock and cpu_clock from master_clock */ + /* calculate gbus_clock and cpu_clock_freq from master_clock */ divmode = (unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_DIVMODE_MASK; switch (divmode) { case TX4938_CCFG_DIVMODE_8: @@ -724,7 +691,7 @@ void __init tx4938_board_setup(void) if (txx9_cpu_clock == 0) { txx9_cpu_clock = 300000000; /* 300MHz */ } - /* calculate gbus_clock and master_clock from cpu_clock */ + /* calculate gbus_clock and master_clock from cpu_clock_freq */ cpuclk = txx9_cpu_clock; divmode = (unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_DIVMODE_MASK; switch (divmode) { @@ -806,10 +773,6 @@ void __init tx4938_board_setup(void) txboard_add_phys_region(base, size); } - /* IRC */ - /* disable interrupt control */ - tx4938_ircptr->cer = 0; - /* TMR */ /* disable all timers */ for (i = 0; i < TX4938_NR_TMR; i++) { @@ -893,10 +856,8 @@ void tx4938_report_pcic_status(void) /* We use onchip r4k counter or TMR timer as our system wide timer * interrupt running at 100HZ. */ -extern void __init rtc_rx5c348_init(int chipid); void __init rbtx4938_time_init(void) { - rtc_rx5c348_init(RBTX4938_SRTC_CHIPID); mips_hpt_frequency = txx9_cpu_clock / 2; } @@ -910,9 +871,6 @@ void __init toshiba_rbtx4938_setup(void) if (txx9_master_clock == 0) txx9_master_clock = 25000000; /* 25MHz */ tx4938_board_setup(); - /* setup irq stuff */ - TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000000); /* irq trigger */ - TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM1), 0x00000000); /* irq trigger */ /* setup serial stuff */ TX4938_WR(0xff1ff314, 0x00000000); /* h/w flow control off */ TX4938_WR(0xff1ff414, 0x00000000); /* h/w flow control off */ @@ -932,7 +890,7 @@ void __init toshiba_rbtx4938_setup(void) req.iotype = UPIO_MEM; req.membase = (char *)(0xff1ff300 + i * 0x100); req.mapbase = 0xff1ff300 + i * 0x100; - req.irq = 32 + i; + req.irq = RBTX4938_IRQ_IRC_SIO(i); req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/; req.uartclk = 50000000; early_serial_txx9_setup(&req); @@ -1013,25 +971,194 @@ void __init toshiba_rbtx4938_setup(void) *rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr); } -#ifdef CONFIG_PROC_FS -extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid); -static int __init tx4938_spi_proc_setup(void) +static int __init rbtx4938_ne_init(void) { - struct proc_dir_entry *tx4938_spi_eeprom_dir; + struct resource res[] = { + { + .start = RBTX4938_RTL_8019_BASE, + .end = RBTX4938_RTL_8019_BASE + 0x20 - 1, + .flags = IORESOURCE_IO, + }, { + .start = RBTX4938_RTL_8019_IRQ, + .flags = IORESOURCE_IRQ, + } + }; + struct platform_device *dev = + platform_device_register_simple("ne", -1, + res, ARRAY_SIZE(res)); + return IS_ERR(dev) ? PTR_ERR(dev) : 0; +} +device_initcall(rbtx4938_ne_init); - tx4938_spi_eeprom_dir = proc_mkdir("spi_eeprom", 0); +/* GPIO support */ - if (!tx4938_spi_eeprom_dir) - return -ENOMEM; +static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock); - /* don't allow user access to RBTX4938_SEEPROM1_CHIPID - * as it contains eth0 and eth1 MAC addresses - */ - spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM2_CHIPID); - spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM3_CHIPID); +static void rbtx4938_spi_gpio_set(unsigned gpio, int value) +{ + u8 val; + unsigned long flags; + gpio -= 16; + spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags); + val = *rbtx4938_spics_ptr; + if (value) + val |= 1 << gpio; + else + val &= ~(1 << gpio); + *rbtx4938_spics_ptr = val; + mmiowb(); + spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags); +} +static int rbtx4938_spi_gpio_dir_out(unsigned gpio, int value) +{ + rbtx4938_spi_gpio_set(gpio, value); return 0; } -__initcall(tx4938_spi_proc_setup); -#endif +static DEFINE_SPINLOCK(tx4938_gpio_lock); + +static int tx4938_gpio_get(unsigned gpio) +{ + return tx4938_pioptr->din & (1 << gpio); +} + +static void tx4938_gpio_set_raw(unsigned gpio, int value) +{ + u32 val; + val = tx4938_pioptr->dout; + if (value) + val |= 1 << gpio; + else + val &= ~(1 << gpio); + tx4938_pioptr->dout = val; +} + +static void tx4938_gpio_set(unsigned gpio, int value) +{ + unsigned long flags; + spin_lock_irqsave(&tx4938_gpio_lock, flags); + tx4938_gpio_set_raw(gpio, value); + mmiowb(); + spin_unlock_irqrestore(&tx4938_gpio_lock, flags); +} + +static int tx4938_gpio_dir_in(unsigned gpio) +{ + spin_lock_irq(&tx4938_gpio_lock); + tx4938_pioptr->dir &= ~(1 << gpio); + mmiowb(); + spin_unlock_irq(&tx4938_gpio_lock); + return 0; +} + +static int tx4938_gpio_dir_out(unsigned int gpio, int value) +{ + spin_lock_irq(&tx4938_gpio_lock); + tx4938_gpio_set_raw(gpio, value); + tx4938_pioptr->dir |= 1 << gpio; + mmiowb(); + spin_unlock_irq(&tx4938_gpio_lock); + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + if (gpio < 16) + return tx4938_gpio_dir_in(gpio); + return -EINVAL; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + if (gpio < 16) + return tx4938_gpio_dir_out(gpio, value); + if (gpio < 16 + 3) + return rbtx4938_spi_gpio_dir_out(gpio, value); + return -EINVAL; +} + +int gpio_get_value(unsigned gpio) +{ + if (gpio < 16) + return tx4938_gpio_get(gpio); + return 0; +} + +void gpio_set_value(unsigned gpio, int value) +{ + if (gpio < 16) + tx4938_gpio_set(gpio, value); + else + rbtx4938_spi_gpio_set(gpio, value); +} + +/* SPI support */ + +static void __init txx9_spi_init(unsigned long base, int irq) +{ + struct resource res[] = { + { + .start = base, + .end = base + 0x20 - 1, + .flags = IORESOURCE_MEM, + .parent = &tx4938_reg_resource, + }, { + .start = irq, + .flags = IORESOURCE_IRQ, + }, + }; + platform_device_register_simple("spi_txx9", 0, + res, ARRAY_SIZE(res)); +} + +static int __init rbtx4938_spi_init(void) +{ + struct spi_board_info srtc_info = { + .modalias = "rtc-rs5c348", + .max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */ + .bus_num = 0, + .chip_select = 16 + SRTC_CS, + /* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS */ + .mode = SPI_MODE_1 | SPI_CS_HIGH, + }; + spi_register_board_info(&srtc_info, 1); + spi_eeprom_register(SEEPROM1_CS); + spi_eeprom_register(16 + SEEPROM2_CS); + spi_eeprom_register(16 + SEEPROM3_CS); + txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI); + return 0; +} +arch_initcall(rbtx4938_spi_init); + +/* Minimum CLK support */ + +struct clk *clk_get(struct device *dev, const char *id) +{ + if (!strcmp(id, "spi-baseclk")) + return (struct clk *)(txx9_gbus_clock / 2 / 4); + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return (unsigned long)clk; +} +EXPORT_SYMBOL(clk_get_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put);